Merge tag 'drm-misc-next-2022-08-20-1' of git://anongit.freedesktop.org/drm/drm-misc...
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 6 Sep 2022 08:56:03 +0000 (10:56 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 6 Sep 2022 08:56:04 +0000 (10:56 +0200)
drm-misc-next for v6.1:

UAPI Changes:

Cross-subsystem Changes:
- DMA-buf: documentation updates.
- Assorted small fixes to vga16fb
- Fix fbdev drivers to use the aperture helpers.
- Make removal of conflicting drivers work correctly without fbdev enabled.

Core Changes:
- bridge, scheduler, dp-mst: Assorted small fixes.
- Add more format helpers to fourcc, and use it to replace the cpp usage.
- Add DRM_FORMAT_Cxx, DRM_FORMAT_Rxx (single channel), and DRM_FORMAT_Dxx
  ("darkness", inverted single channel)
- Add packed AYUV8888 and XYUV8888 formats.
- Assorted documentation updates.
- Rename ttm_bo_init to ttm_bo_init_validate.
- Allow TTM bo's to exist without backing store.
- Convert drm selftests to kunit.
- Add managed init functions for (panel) bridge, crtc, encoder and connector.
- Fix endianness handling in various format conversion helpers.
- Make tests pass on big-endian platforms, and add test for rgb888 -> rgb565
- Move DRM_PLANE_HELPER_NO_SCALING to atomic helpers and rename, so
  drm_plane_helper is no longer needed in most drivers.
- Use idr_init_base instead of idr_init.
- Rename FB and GEM CMA helpers to DMA helpers.
- Rework XRGB8888 related conversion helpers, and add drm_fb_blit() that
  takes a iosys_map. Make drm_fb_memcpy take an iosys_map too.
- Move edid luminance calculation to core, and use it in i915.

Driver Changes:
- bridge/{adv7511,ti-sn65dsi86,parade-ps8640}, panel/{simple,nt35510,tc358767},
  nouveau, sun4i, mipi-dsi, mgag200, bochs, arm, komeda, vmwgfx, pl111:
  Assorted small fixes and doc updates.
- vc4: Rework hdmi power up, and depend on PM.
- panel/simple: Add Samsung LTL101AL01.
- ingenic: Add JZ4760(B) support, avoid a modeset when sharpness property
  is unchanged, and use the new PM ops.
- Revert some amdgpu commits that cause garbaged graphics when starting
  X, and reapply them with the real problem fixed.
- Completely rework vc4 init to use managed helpers.
- Rename via_drv to via_dri1, and move all stuff there only used by the
  dri1 implementation in preperation for atomic modeset.
- Use regmap bulk write in ssd130x.
- Power sequence and clock updates to it6505.
- Split panel-sitrox-st7701  init sequence and rework mode programming code.
- virtio: Improve error and edge conditions handling, and convert to use managed
  helpers.
- Add Samsung LTL101AL01, B120XAN01.0, R140NWF5 RH, DMT028VGHMCMI-1A T, panels.
- Add generic fbdev support to komeda.
- Split mgag200 modeset handling to make it more model-specific.
- Convert simpledrm to use atomic helpers.
- Improve udl suspend/disconnect handling.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/f0c71766-61e8-19b7-763a-5fbcdefc633d@linux.intel.com
486 files changed:
Documentation/devicetree/bindings/display/ingenic,lcd.yaml
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
Documentation/devicetree/bindings/display/panel/sitronix,st7701.yaml
Documentation/gpu/drm-kms-helpers.rst
Documentation/gpu/drm-mm.rst
Documentation/gpu/todo.rst
drivers/dma-buf/sync_file.c
drivers/firmware/sysfb.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
drivers/gpu/drm/arm/Kconfig
drivers/gpu/drm/arm/display/Kconfig
drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
drivers/gpu/drm/arm/display/komeda/komeda_drv.c
drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.c
drivers/gpu/drm/arm/display/komeda/komeda_kms.h
drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
drivers/gpu/drm/arm/display/komeda/komeda_plane.c
drivers/gpu/drm/arm/hdlcd_crtc.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/arm/malidp_mw.c
drivers/gpu/drm/arm/malidp_planes.c
drivers/gpu/drm/arm/malidp_regs.h
drivers/gpu/drm/armada/armada_crtc.c
drivers/gpu/drm/armada/armada_gem.c
drivers/gpu/drm/armada/armada_overlay.c
drivers/gpu/drm/armada/armada_plane.c
drivers/gpu/drm/aspeed/Kconfig
drivers/gpu/drm/aspeed/aspeed_gfx_crtc.c
drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/atmel-hlcdc/Kconfig
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
drivers/gpu/drm/bridge/adv7511/adv7511.h
drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/analogix/anx7625.c
drivers/gpu/drm/bridge/chipone-icn6211.c
drivers/gpu/drm/bridge/ite-it6505.c
drivers/gpu/drm/bridge/lontium-lt9611.c
drivers/gpu/drm/bridge/panel.c
drivers/gpu/drm/bridge/parade-ps8640.c
drivers/gpu/drm/bridge/tc358762.c
drivers/gpu/drm/bridge/tc358764.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/display/drm_dp_helper.c
drivers/gpu/drm/display/drm_dp_mst_topology.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_auth.c
drivers/gpu/drm/drm_bridge.c
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_color_mgmt.c
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_encoder.c
drivers/gpu/drm/drm_fb_cma_helper.c [deleted file]
drivers/gpu/drm/drm_fb_dma_helper.c [new file with mode: 0644]
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/drm_format_helper.c
drivers/gpu/drm/drm_fourcc.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem_cma_helper.c [deleted file]
drivers/gpu/drm/drm_gem_dma_helper.c [new file with mode: 0644]
drivers/gpu/drm/drm_gem_framebuffer_helper.c
drivers/gpu/drm/drm_gem_shmem_helper.c
drivers/gpu/drm/drm_gem_vram_helper.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_mipi_dbi.c
drivers/gpu/drm/drm_mipi_dsi.c
drivers/gpu/drm/drm_mode_config.c
drivers/gpu/drm/drm_modeset_helper.c
drivers/gpu/drm/drm_plane_helper.c
drivers/gpu/drm/drm_simple_kms_helper.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/fsl-dcu/Kconfig
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c
drivers/gpu/drm/gma500/psb_intel_display.c
drivers/gpu/drm/gud/gud_pipe.c
drivers/gpu/drm/hisilicon/kirin/Kconfig
drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
drivers/gpu/drm/i915/display/i9xx_plane.c
drivers/gpu/drm/i915/display/intel_atomic.c
drivers/gpu/drm/i915/display/intel_atomic_plane.c
drivers/gpu/drm/i915/display/intel_crtc.c
drivers/gpu/drm/i915/display/intel_cursor.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
drivers/gpu/drm/i915/display/intel_sprite.c
drivers/gpu/drm/i915/display/skl_universal_plane.c
drivers/gpu/drm/i915/gem/i915_gem_ttm.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/imx/Kconfig
drivers/gpu/drm/imx/dcss/Kconfig
drivers/gpu/drm/imx/dcss/dcss-kms.c
drivers/gpu/drm/imx/dcss/dcss-plane.c
drivers/gpu/drm/imx/imx-drm-core.c
drivers/gpu/drm/imx/imx-drm.h
drivers/gpu/drm/imx/ipuv3-crtc.c
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/ingenic/Kconfig
drivers/gpu/drm/ingenic/ingenic-drm-drv.c
drivers/gpu/drm/ingenic/ingenic-ipu.c
drivers/gpu/drm/kmb/Kconfig
drivers/gpu/drm/kmb/kmb_drv.c
drivers/gpu/drm/kmb/kmb_plane.c
drivers/gpu/drm/logicvc/Kconfig
drivers/gpu/drm/logicvc/logicvc_crtc.c
drivers/gpu/drm/logicvc/logicvc_drm.c
drivers/gpu/drm/logicvc/logicvc_interface.c
drivers/gpu/drm/logicvc/logicvc_layer.c
drivers/gpu/drm/logicvc/logicvc_mode.c
drivers/gpu/drm/mcde/Kconfig
drivers/gpu/drm/mcde/mcde_display.c
drivers/gpu/drm/mcde/mcde_drv.c
drivers/gpu/drm/mediatek/Kconfig
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_gem.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/meson/Kconfig
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/meson/meson_overlay.c
drivers/gpu/drm/meson/meson_plane.c
drivers/gpu/drm/mgag200/Makefile
drivers/gpu/drm/mgag200/mgag200_bmc.c [new file with mode: 0644]
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/mgag200/mgag200_drv.h
drivers/gpu/drm/mgag200/mgag200_g200.c
drivers/gpu/drm/mgag200/mgag200_g200eh.c
drivers/gpu/drm/mgag200/mgag200_g200eh3.c
drivers/gpu/drm/mgag200/mgag200_g200er.c
drivers/gpu/drm/mgag200/mgag200_g200ev.c
drivers/gpu/drm/mgag200/mgag200_g200ew3.c
drivers/gpu/drm/mgag200/mgag200_g200se.c
drivers/gpu/drm/mgag200/mgag200_g200wb.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/mgag200/mgag200_pll.c [deleted file]
drivers/gpu/drm/mgag200/mgag200_reg.h
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_drv.h
drivers/gpu/drm/mxsfb/Kconfig
drivers/gpu/drm/mxsfb/lcdif_drv.c
drivers/gpu/drm/mxsfb/lcdif_kms.c
drivers/gpu/drm/mxsfb/mxsfb_drv.c
drivers/gpu/drm/mxsfb/mxsfb_kms.c
drivers/gpu/drm/nouveau/dispnv04/crtc.c
drivers/gpu/drm/nouveau/dispnv50/base507c.c
drivers/gpu/drm/nouveau/dispnv50/curs507a.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/ovly507e.c
drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c
drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_prime.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/omapdrm/omap_overlay.c
drivers/gpu/drm/omapdrm/omap_plane.c
drivers/gpu/drm/panel/Kconfig
drivers/gpu/drm/panel/panel-asus-z00t-tm5p5-n35596.c
drivers/gpu/drm/panel/panel-boe-bf060y8m-aj0.c
drivers/gpu/drm/panel/panel-boe-himax8279d.c
drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
drivers/gpu/drm/panel/panel-dsi-cm.c
drivers/gpu/drm/panel/panel-ebbg-ft8719.c
drivers/gpu/drm/panel/panel-edp.c
drivers/gpu/drm/panel/panel-elida-kd35t133.c
drivers/gpu/drm/panel/panel-feixin-k101-im2ba02.c
drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
drivers/gpu/drm/panel/panel-ilitek-ili9341.c
drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
drivers/gpu/drm/panel/panel-innolux-p079zca.c
drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c
drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
drivers/gpu/drm/panel/panel-khadas-ts050.c
drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
drivers/gpu/drm/panel/panel-leadtek-ltk500hd1829.c
drivers/gpu/drm/panel/panel-mantix-mlaf057we51.c
drivers/gpu/drm/panel/panel-novatek-nt35510.c
drivers/gpu/drm/panel/panel-novatek-nt35560.c
drivers/gpu/drm/panel/panel-novatek-nt35950.c
drivers/gpu/drm/panel/panel-novatek-nt36672a.c
drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
drivers/gpu/drm/panel/panel-raydium-rm67191.c
drivers/gpu/drm/panel/panel-raydium-rm68200.c
drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c
drivers/gpu/drm/panel/panel-samsung-s6e88a0-ams452ef01.c
drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
drivers/gpu/drm/panel/panel-samsung-sofef00.c
drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
drivers/gpu/drm/panel/panel-sharp-ls060t1sx01.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/panel/panel-sitronix-st7701.c
drivers/gpu/drm/panel/panel-sitronix-st7703.c
drivers/gpu/drm/panel/panel-sony-tulip-truly-nt35521.c
drivers/gpu/drm/panel/panel-tdo-tl070wsh30.c
drivers/gpu/drm/panel/panel-truly-nt35597.c
drivers/gpu/drm/panel/panel-visionox-rm69299.c
drivers/gpu/drm/panel/panel-xinpeng-xpp055c272.c
drivers/gpu/drm/panfrost/Kconfig
drivers/gpu/drm/panfrost/Makefile
drivers/gpu/drm/panfrost/panfrost_dump.c [new file with mode: 0644]
drivers/gpu/drm/panfrost/panfrost_dump.h [new file with mode: 0644]
drivers/gpu/drm/panfrost/panfrost_job.c
drivers/gpu/drm/panfrost/panfrost_regs.h
drivers/gpu/drm/pl111/Kconfig
drivers/gpu/drm/pl111/pl111_display.c
drivers/gpu/drm/pl111/pl111_drv.c
drivers/gpu/drm/pl111/pl111_versatile.c
drivers/gpu/drm/qxl/qxl_display.c
drivers/gpu/drm/qxl/qxl_object.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/rcar-du/Kconfig
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rcar-du/rcar_du_kms.c
drivers/gpu/drm/rcar-du/rcar_du_plane.c
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
drivers/gpu/drm/rockchip/Kconfig
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_gem.c
drivers/gpu/drm/rockchip/rockchip_drm_vop.c
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/selftests/Makefile [deleted file]
drivers/gpu/drm/selftests/drm_buddy_selftests.h [deleted file]
drivers/gpu/drm/selftests/drm_cmdline_selftests.h [deleted file]
drivers/gpu/drm/selftests/drm_mm_selftests.h [deleted file]
drivers/gpu/drm/selftests/drm_modeset_selftests.h [deleted file]
drivers/gpu/drm/selftests/drm_selftest.c [deleted file]
drivers/gpu/drm/selftests/drm_selftest.h [deleted file]
drivers/gpu/drm/selftests/test-drm_buddy.c [deleted file]
drivers/gpu/drm/selftests/test-drm_cmdline_parser.c [deleted file]
drivers/gpu/drm/selftests/test-drm_damage_helper.c [deleted file]
drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c [deleted file]
drivers/gpu/drm/selftests/test-drm_format.c [deleted file]
drivers/gpu/drm/selftests/test-drm_framebuffer.c [deleted file]
drivers/gpu/drm/selftests/test-drm_mm.c [deleted file]
drivers/gpu/drm/selftests/test-drm_modeset_common.c [deleted file]
drivers/gpu/drm/selftests/test-drm_modeset_common.h [deleted file]
drivers/gpu/drm/selftests/test-drm_plane_helper.c [deleted file]
drivers/gpu/drm/selftests/test-drm_rect.c [deleted file]
drivers/gpu/drm/shmobile/Kconfig
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/shmobile/shmob_drm_kms.c
drivers/gpu/drm/shmobile/shmob_drm_kms.h
drivers/gpu/drm/shmobile/shmob_drm_plane.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/solomon/ssd130x-spi.c
drivers/gpu/drm/solomon/ssd130x.c
drivers/gpu/drm/sprd/Kconfig
drivers/gpu/drm/sprd/sprd_dpu.c
drivers/gpu/drm/sprd/sprd_drm.c
drivers/gpu/drm/sti/Kconfig
drivers/gpu/drm/sti/sti_crtc.c
drivers/gpu/drm/sti/sti_cursor.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sti/sti_gdp.c
drivers/gpu/drm/sti/sti_hqvdp.c
drivers/gpu/drm/sti/sti_plane.c
drivers/gpu/drm/sti/sti_plane.h
drivers/gpu/drm/stm/Kconfig
drivers/gpu/drm/stm/drv.c
drivers/gpu/drm/stm/ltdc.c
drivers/gpu/drm/sun4i/Kconfig
drivers/gpu/drm/sun4i/sun4i_backend.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/sun4i/sun4i_frontend.c
drivers/gpu/drm/sun4i/sun4i_layer.c
drivers/gpu/drm/sun4i/sun8i_mixer.c
drivers/gpu/drm/sun4i/sun8i_ui_layer.c
drivers/gpu/drm/sun4i/sun8i_vi_layer.c
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/fb.c
drivers/gpu/drm/tegra/plane.c
drivers/gpu/drm/tests/Makefile
drivers/gpu/drm/tests/drm_buddy_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_cmdline_parser_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_damage_helper_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_dp_mst_helper_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_format_helper_test.c
drivers/gpu/drm/tests/drm_format_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_framebuffer_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_mm_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_plane_helper_test.c [new file with mode: 0644]
drivers/gpu/drm/tests/drm_rect_test.c [new file with mode: 0644]
drivers/gpu/drm/tidss/Kconfig
drivers/gpu/drm/tidss/tidss_crtc.c
drivers/gpu/drm/tidss/tidss_dispc.c
drivers/gpu/drm/tidss/tidss_drv.c
drivers/gpu/drm/tidss/tidss_kms.c
drivers/gpu/drm/tidss/tidss_plane.c
drivers/gpu/drm/tilcdc/Kconfig
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/tilcdc/tilcdc_drv.c
drivers/gpu/drm/tilcdc/tilcdc_plane.c
drivers/gpu/drm/tiny/Kconfig
drivers/gpu/drm/tiny/arcpgu.c
drivers/gpu/drm/tiny/bochs.c
drivers/gpu/drm/tiny/cirrus.c
drivers/gpu/drm/tiny/hx8357d.c
drivers/gpu/drm/tiny/ili9163.c
drivers/gpu/drm/tiny/ili9225.c
drivers/gpu/drm/tiny/ili9341.c
drivers/gpu/drm/tiny/ili9486.c
drivers/gpu/drm/tiny/mi0283qt.c
drivers/gpu/drm/tiny/panel-mipi-dbi.c
drivers/gpu/drm/tiny/repaper.c
drivers/gpu/drm/tiny/simpledrm.c
drivers/gpu/drm/tiny/st7586.c
drivers/gpu/drm/tiny/st7735r.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/gpu/drm/tve200/Kconfig
drivers/gpu/drm/tve200/tve200_display.c
drivers/gpu/drm/tve200/tve200_drv.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_main.c
drivers/gpu/drm/udl/udl_modeset.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/v3d/v3d_drv.c
drivers/gpu/drm/v3d/v3d_gem.c
drivers/gpu/drm/v3d/v3d_perfmon.c
drivers/gpu/drm/vboxvideo/vbox_mode.c
drivers/gpu/drm/vc4/Kconfig
drivers/gpu/drm/vc4/vc4_bo.c
drivers/gpu/drm/vc4/vc4_crtc.c
drivers/gpu/drm/vc4/vc4_debugfs.c
drivers/gpu/drm/vc4/vc4_dpi.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_drv.h
drivers/gpu/drm/vc4/vc4_dsi.c
drivers/gpu/drm/vc4/vc4_gem.c
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/gpu/drm/vc4/vc4_hdmi.h
drivers/gpu/drm/vc4/vc4_hvs.c
drivers/gpu/drm/vc4/vc4_irq.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_perfmon.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vc4/vc4_render_cl.c
drivers/gpu/drm/vc4/vc4_txp.c
drivers/gpu/drm/vc4/vc4_v3d.c
drivers/gpu/drm/vc4/vc4_validate.c
drivers/gpu/drm/vc4/vc4_validate_shaders.c
drivers/gpu/drm/vc4/vc4_vec.c
drivers/gpu/drm/via/Makefile
drivers/gpu/drm/via/via_3d_reg.h
drivers/gpu/drm/via/via_dma.c [deleted file]
drivers/gpu/drm/via/via_dmablit.c [deleted file]
drivers/gpu/drm/via/via_dmablit.h [deleted file]
drivers/gpu/drm/via/via_dri1.c [new file with mode: 0644]
drivers/gpu/drm/via/via_drv.c [deleted file]
drivers/gpu/drm/via/via_drv.h [deleted file]
drivers/gpu/drm/via/via_irq.c [deleted file]
drivers/gpu/drm/via/via_map.c [deleted file]
drivers/gpu/drm/via/via_mm.c [deleted file]
drivers/gpu/drm/via/via_verifier.c [deleted file]
drivers/gpu/drm/via/via_verifier.h [deleted file]
drivers/gpu/drm/via/via_video.c [deleted file]
drivers/gpu/drm/virtio/virtgpu_drv.c
drivers/gpu/drm/virtio/virtgpu_drv.h
drivers/gpu/drm/virtio/virtgpu_gem.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/gpu/drm/virtio/virtgpu_object.c
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/gpu/drm/virtio/virtgpu_vq.c
drivers/gpu/drm/vkms/vkms_plane.c
drivers/gpu/drm/vmwgfx/device_include/vm_basic_types.h
drivers/gpu/drm/vmwgfx/ttm_object.h
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/drm/xlnx/Kconfig
drivers/gpu/drm/xlnx/zynqmp_disp.c
drivers/gpu/drm/xlnx/zynqmp_dpsub.c
drivers/staging/sm750fb/sm750.c
drivers/video/aperture.c
drivers/video/fbdev/arkfb.c
drivers/video/fbdev/asiliantfb.c
drivers/video/fbdev/aty/aty128fb.c
drivers/video/fbdev/aty/atyfb_base.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/carminefb.c
drivers/video/fbdev/chipsfb.c
drivers/video/fbdev/cirrusfb.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/cyber2000fb.c
drivers/video/fbdev/geode/gx1fb_core.c
drivers/video/fbdev/geode/gxfb_core.c
drivers/video/fbdev/geode/lxfb_core.c
drivers/video/fbdev/gxt4500.c
drivers/video/fbdev/hyperv_fb.c
drivers/video/fbdev/i740fb.c
drivers/video/fbdev/i810/i810_main.c
drivers/video/fbdev/imsttfb.c
drivers/video/fbdev/intelfb/intelfbdrv.c
drivers/video/fbdev/kyro/fbdev.c
drivers/video/fbdev/matrox/matroxfb_base.c
drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
drivers/video/fbdev/neofb.c
drivers/video/fbdev/nvidia/nvidia.c
drivers/video/fbdev/pm2fb.c
drivers/video/fbdev/pm3fb.c
drivers/video/fbdev/pvr2fb.c
drivers/video/fbdev/riva/fbdev.c
drivers/video/fbdev/s3fb.c
drivers/video/fbdev/savage/savagefb_driver.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/skeletonfb.c
drivers/video/fbdev/sm712fb.c
drivers/video/fbdev/sstfb.c
drivers/video/fbdev/sunxvr2500.c
drivers/video/fbdev/sunxvr500.c
drivers/video/fbdev/tdfxfb.c
drivers/video/fbdev/tgafb.c
drivers/video/fbdev/tridentfb.c
drivers/video/fbdev/vermilion/vermilion.c
drivers/video/fbdev/vga16fb.c
drivers/video/fbdev/via/via-core.c
drivers/video/fbdev/vt8623fb.c
include/drm/drm_atomic_helper.h
include/drm/drm_bridge.h
include/drm/drm_connector.h
include/drm/drm_crtc.h
include/drm/drm_encoder.h
include/drm/drm_fb_cma_helper.h [deleted file]
include/drm/drm_fb_dma_helper.h [new file with mode: 0644]
include/drm/drm_file.h
include/drm/drm_format_helper.h
include/drm/drm_fourcc.h
include/drm/drm_framebuffer.h
include/drm/drm_gem.h
include/drm/drm_gem_cma_helper.h [deleted file]
include/drm/drm_gem_dma_helper.h [new file with mode: 0644]
include/drm/drm_gem_shmem_helper.h
include/drm/drm_mipi_dsi.h
include/drm/drm_plane_helper.h
include/drm/ttm/ttm_bo_api.h
include/linux/dma-resv.h
include/linux/fb.h
include/linux/iosys-map.h
include/uapi/drm/drm_fourcc.h
include/uapi/drm/drm_mode.h
include/uapi/drm/panfrost_drm.h
include/video/vga.h

index 0049010b37caf2a0559268ff9a378312348fe14a..c0bb02fb49f4b23057d01c4af699772f1daff7c5 100644 (file)
@@ -17,6 +17,8 @@ properties:
     enum:
       - ingenic,jz4740-lcd
       - ingenic,jz4725b-lcd
+      - ingenic,jz4760-lcd
+      - ingenic,jz4760b-lcd
       - ingenic,jz4770-lcd
       - ingenic,jz4780-lcd
 
index bc8e9c0c1dc3c10690072db819a04327cc1fa0e9..133f2bae04b52c110164a38a0446bc98b9e7567c 100644 (file)
@@ -280,6 +280,8 @@ properties:
       - samsung,atna33xc20
         # Samsung 12.2" (2560x1600 pixels) TFT LCD panel
       - samsung,lsn122dl01-c01
+        # Samsung Electronics 10.1" WXGA (1280x800) TFT LCD panel
+      - samsung,ltl101al01
         # Samsung Electronics 10.1" WSVGA TFT LCD panel
       - samsung,ltn101nt05
         # Samsung Electronics 14" WXGA (1366x768) TFT LCD panel
index 6dff59fe4be14cf51c8719712150db89896ebbb3..34d5e20c6cb3244b3f5d50c30a14c45bbb8b3444 100644 (file)
@@ -17,6 +17,9 @@ description: |
   Techstar TS8550B is 480x854, 2-lane MIPI DSI LCD panel which has
   inbuilt ST7701 chip.
 
+  Densitron DMT028VGHMCMI-1A is 480x640, 2-lane MIPI DSI LCD panel
+  which has built-in ST7701 chip.
+
 allOf:
   - $ref: panel-common.yaml#
 
@@ -24,6 +27,7 @@ properties:
   compatible:
     items:
       - enum:
+          - densitron,dmt028vghmcmi-1a
           - techstar,ts8550b
       - const: sitronix,st7701
 
index 2d473bc64c9f399d21af16a63c583857850b5317..dbc85fd7a9718b9b506473db0ffa8ef9233c9be8 100644 (file)
@@ -122,13 +122,13 @@ format Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_format_helper.c
    :export:
 
-Framebuffer CMA Helper Functions Reference
+Framebuffer DMA Helper Functions Reference
 ==========================================
 
-.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
-   :doc: framebuffer cma helper functions
+.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c
+   :doc: framebuffer dma helper functions
 
-.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c
    :export:
 
 Framebuffer GEM Helper Reference
index f32ccce5722d0aa684d262b437d53ca93019c092..a79fd3549ff8c267c195d225c0d2c722803c7b56 100644 (file)
@@ -300,12 +300,12 @@ Drivers that want to map the GEM object upfront instead of handling page
 faults can implement their own mmap file operation handler.
 
 For platforms without MMU the GEM core provides a helper method
-drm_gem_cma_get_unmapped_area(). The mmap() routines will call this to get a
+drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a
 proposed address for the mapping.
 
-To use drm_gem_cma_get_unmapped_area(), drivers must fill the struct
+To use drm_gem_dma_get_unmapped_area(), drivers must fill the struct
 :c:type:`struct file_operations <file_operations>` get_unmapped_area field with
-a pointer on drm_gem_cma_get_unmapped_area().
+a pointer on drm_gem_dma_get_unmapped_area().
 
 More detailed information about get_unmapped_area can be found in
 Documentation/admin-guide/mm/nommu-mmap.rst
@@ -355,16 +355,16 @@ GEM Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_gem.c
    :export:
 
-GEM CMA Helper Functions Reference
+GEM DMA Helper Functions Reference
 ----------------------------------
 
-.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
-   :doc: cma helpers
+.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c
+   :doc: dma helpers
 
-.. kernel-doc:: include/drm/drm_gem_cma_helper.h
+.. kernel-doc:: include/drm/drm_gem_dma_helper.h
    :internal:
 
-.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c
    :export:
 
 GEM SHMEM Helper Function Reference
index 513b20ccef1e1f0603f7e2626e3377fdd1ee3968..7634c27ac562b69c80e9ff22ff128e328b789510 100644 (file)
@@ -322,18 +322,6 @@ Contact: Daniel Vetter, Noralf Tronnes
 
 Level: Advanced
 
-idr_init_base()
----------------
-
-DRM core&drivers uses a lot of idr (integer lookup directories) for mapping
-userspace IDs to internal objects, and in most places ID=0 means NULL and hence
-is never used. Switching to idr_init_base() for these would make the idr more
-efficient.
-
-Contact: Daniel Vetter
-
-Level: Starter
-
 struct drm_gem_object_funcs
 ---------------------------
 
@@ -343,19 +331,6 @@ converted, except for struct drm_driver.gem_prime_mmap.
 
 Level: Intermediate
 
-Rename CMA helpers to DMA helpers
----------------------------------
-
-CMA (standing for contiguous memory allocator) is really a bit an accident of
-what these were used for first, a much better name would be DMA helpers. In the
-text these should even be called coherent DMA memory helpers (so maybe CDM, but
-no one knows what that means) since underneath they just use dma_alloc_coherent.
-
-Contact: Laurent Pinchart, Daniel Vetter
-
-Level: Intermediate (mostly because it is a huge tasks without good partial
-milestones, not technically itself that challenging)
-
 connector register/unregister fixes
 -----------------------------------
 
@@ -617,17 +592,6 @@ Contact: Javier Martinez Canillas <javierm@redhat.com>
 
 Level: Intermediate
 
-Convert Kernel Selftests (kselftest) to KUnit tests when appropriate
---------------------------------------------------------------------
-
-Many of the `Kselftest <https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html>`_
-tests in DRM could be converted to Kunit tests instead, since that framework
-is more suitable for unit testing.
-
-Contact: Javier Martinez Canillas <javierm@redhat.com>
-
-Level: Starter
-
 Enable trinity for DRM
 ----------------------
 
index 3ebec19a8e0296fb6c17ecc99424800ad5b8a05a..af57799c86ceec5bb4b8f4354aa3bbc822211771 100644 (file)
@@ -132,7 +132,7 @@ EXPORT_SYMBOL(sync_file_get_fence);
 char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
 {
        if (sync_file->user_name[0]) {
-               strlcpy(buf, sync_file->user_name, len);
+               strscpy(buf, sync_file->user_name, len);
        } else {
                struct dma_fence *fence = sync_file->fence;
 
@@ -172,7 +172,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
                return NULL;
        }
        sync_file->fence = fence;
-       strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
+       strscpy(sync_file->user_name, name, sizeof(sync_file->user_name));
        return sync_file;
 }
 
@@ -262,9 +262,9 @@ err_put_fd:
 static int sync_fill_fence_info(struct dma_fence *fence,
                                 struct sync_fence_info *info)
 {
-       strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
+       strscpy(info->obj_name, fence->ops->get_timeline_name(fence),
                sizeof(info->obj_name));
-       strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
+       strscpy(info->driver_name, fence->ops->get_driver_name(fence),
                sizeof(info->driver_name));
 
        info->status = dma_fence_get_status(fence);
index 1f276f108cc9364ae949ec32e31321af2f6c4385..3fd3563d962b87d73ff2fc2bb3079461cd9f22e0 100644 (file)
@@ -94,6 +94,10 @@ static __init int sysfb_init(void)
                name = "efi-framebuffer";
        else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
                name = "vesa-framebuffer";
+       else if (si->orig_video_isVGA == VIDEO_TYPE_VGAC)
+               name = "vga-framebuffer";
+       else if (si->orig_video_isVGA == VIDEO_TYPE_EGAC)
+               name = "ega-framebuffer";
        else
                name = "platform-framebuffer";
 
index 6c2256e8474bee5b364f6aba57a67604e74d0327..0b2ad7212ee66822760ad07438e181f612f788cd 100644 (file)
@@ -50,10 +50,9 @@ config DRM_DEBUG_MM
 
          If in doubt, say "N".
 
-config DRM_DEBUG_SELFTEST
-       tristate "kselftests for DRM"
-       depends on DRM
-       depends on DEBUG_KERNEL
+config DRM_KUNIT_TEST
+       tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
+       depends on DRM && KUNIT
        select PRIME_NUMBERS
        select DRM_DISPLAY_DP_HELPER
        select DRM_DISPLAY_HELPER
@@ -61,19 +60,6 @@ config DRM_DEBUG_SELFTEST
        select DRM_KMS_HELPER
        select DRM_BUDDY
        select DRM_EXPORT_FOR_TESTS if m
-       default n
-       help
-         This option provides kernel modules that can be used to run
-         various selftests on parts of the DRM api. This option is not
-         useful for distributions or general kernels, but only for kernel
-         developers working on DRM and associated drivers.
-
-         If in doubt, say "N".
-
-config DRM_KUNIT_TEST
-       tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
-       depends on DRM && KUNIT=y
-       select DRM_KMS_HELPER
        default KUNIT_ALL_TESTS
        help
          This builds unit tests for DRM. This option is not useful for
@@ -214,11 +200,11 @@ config DRM_TTM_HELPER
        help
          Helpers for ttm-based gem objects
 
-config DRM_GEM_CMA_HELPER
+config DRM_GEM_DMA_HELPER
        tristate
        depends on DRM
        help
-         Choose this if you need the GEM CMA helper functions
+         Choose this if you need the GEM DMA helper functions
 
 config DRM_GEM_SHMEM_HELPER
        tristate
index e7af358e6dda595af9ecb7f6023bd8c69b826392..25d0ba31050938c0db4b76369ac894a59b40936c 100644 (file)
@@ -40,9 +40,9 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
 
 obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
 
-drm_cma_helper-y := drm_gem_cma_helper.o
-drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o
-obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
+drm_dma_helper-y := drm_gem_dma_helper.o
+drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o
+obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o
 
 drm_shmem_helper-y := drm_gem_shmem_helper.o
 obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
@@ -75,7 +75,6 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 # Drivers and the rest
 #
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
 obj-$(CONFIG_DRM_KUNIT_TEST) += tests/
 
 obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
index 8ee4e8491f3917ab9a7d56bca2283a456afdc3a1..afe22f83d4a6429470ffda2359b4314a7f300b8d 100644 (file)
@@ -848,7 +848,7 @@ void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr,
 
        mgr->adev = adev;
        mutex_init(&mgr->lock);
-       idr_init(&mgr->ctx_handles);
+       idr_init_base(&mgr->ctx_handles, 1);
 
        for (i = 0; i < AMDGPU_HW_IP_NUM; ++i)
                atomic64_set(&mgr->time_spend[i], 0);
index 1369c25448dc2b34c4a11f7c9a185a7748e403c8..77668c3dae5bfdeb98799e38daca83b12f00bb2d 100644 (file)
@@ -1160,7 +1160,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
        }
 
        mutex_init(&fpriv->bo_list_lock);
-       idr_init(&fpriv->bo_list_handles);
+       idr_init_base(&fpriv->bo_list_handles, 1);
 
        amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
 
index d788a00043a5caa4bfc54906450299bfc8941e87..37322550d75086f2f740059b03c561e6ea8774a8 100644 (file)
@@ -38,7 +38,6 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
index 4570ad4493905869ccd04f9fb639d9214d5e87a3..e6a9b9fc9e0bb1fb5996a80ed5b447dc5efbbd3e 100644 (file)
@@ -591,7 +591,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
        if (!bp->destroy)
                bp->destroy = &amdgpu_bo_destroy;
 
-       r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type,
+       r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, bp->type,
                                 &bo->placement, page_align, &ctx,  NULL,
                                 bp->resv, bp->destroy);
        if (unlikely(r != 0))
@@ -1309,7 +1309,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
        if (bo->base.resv == &bo->base._resv)
                amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo);
 
-       if (bo->resource->mem_type != TTM_PL_VRAM ||
+       if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||
            !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) ||
            adev->in_suspend || adev->shutdown)
                return;
index 134575a3893c535cdfd77bd5de2b902c05ba8254..2e97099808ca3434dc26c4186da6e56a204a27fc 100644 (file)
@@ -471,7 +471,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
 
        adev = amdgpu_ttm_adev(bo->bdev);
 
-       if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
+       if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
+                        bo->ttm == NULL)) {
                ttm_bo_move_null(bo, new_mem);
                goto out;
        }
index 576849e9529642a033d6ab768c1560dbb02aaf6c..f4b5301ea2a02e2794b85a79b814a93742b5f710 100644 (file)
@@ -282,8 +282,8 @@ static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
                return PTR_ERR(crtc_state);
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  false, true);
        if (ret != 0)
                return ret;
index 5140d9c2bf3b40b689134fa9017cf9953aedecd6..19d595321a60f86d90a2ce48c513bca30cbf5fa6 100644 (file)
@@ -88,6 +88,7 @@
 #include <drm/drm_vblank.h>
 #include <drm/drm_audio_component.h>
 #include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
 
 #include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
 
@@ -2812,15 +2813,12 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
 
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 {
-       u32 max_avg, min_cll, max, min, q, r;
        struct amdgpu_dm_backlight_caps *caps;
        struct amdgpu_display_manager *dm;
        struct drm_connector *conn_base;
        struct amdgpu_device *adev;
        struct dc_link *link = NULL;
-       static const u8 pre_computed_values[] = {
-               50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
-               71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
+       struct drm_luminance_range_info *luminance_range;
        int i;
 
        if (!aconnector || !aconnector->dc_link)
@@ -2842,8 +2840,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        caps = &dm->backlight_caps[i];
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
-       max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall;
-       min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
 
        if (caps->ext_caps->bits.oled == 1 /*||
            caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
@@ -2855,31 +2851,9 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        else if (amdgpu_backlight == 1)
                caps->aux_support = true;
 
-       /* From the specification (CTA-861-G), for calculating the maximum
-        * luminance we need to use:
-        *      Luminance = 50*2**(CV/32)
-        * Where CV is a one-byte value.
-        * For calculating this expression we may need float point precision;
-        * to avoid this complexity level, we take advantage that CV is divided
-        * by a constant. From the Euclids division algorithm, we know that CV
-        * can be written as: CV = 32*q + r. Next, we replace CV in the
-        * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just
-        * need to pre-compute the value of r/32. For pre-computing the values
-        * We just used the following Ruby line:
-        *      (0...32).each {|cv| puts (50*2**(cv/32.0)).round}
-        * The results of the above expressions can be verified at
-        * pre_computed_values.
-        */
-       q = max_avg >> 5;
-       r = max_avg % 32;
-       max = (1 << q) * pre_computed_values[r];
-
-       // min luminance: maxLum * (CV/255)^2 / 100
-       q = DIV_ROUND_CLOSEST(min_cll, 255);
-       min = max * DIV_ROUND_CLOSEST((q * q), 100);
-
-       caps->aux_max_input_signal = max;
-       caps->aux_min_input_signal = min;
+       luminance_range = &conn_base->display_info.luminance_range;
+       caps->aux_min_input_signal = luminance_range->min_luminance;
+       caps->aux_max_input_signal = luminance_range->max_luminance;
 }
 
 void amdgpu_dm_update_connector_after_detect(
index fca7cf9dbaeec50a42f5591409f325bc7f0eeade..c450dd66d194bceb3a76379502280455e6008c84 100644 (file)
@@ -1562,7 +1562,7 @@ int dm_drm_plane_get_property(struct drm_plane *plane,
 static const struct drm_plane_funcs dm_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset = dm_drm_plane_reset,
        .atomic_duplicate_state = dm_drm_plane_duplicate_state,
        .atomic_destroy_state = dm_drm_plane_destroy_state,
index 6e3f1d600541aae14ae25d38cd7fd5458fec955b..c1b89274d2a44ac135f6da34ab537fb232031097 100644 (file)
@@ -6,7 +6,7 @@ config DRM_HDLCD
        depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
        depends on COMMON_CLK
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        help
          Choose this option if you have an ARM High Definition Colour LCD
          controller.
@@ -27,7 +27,7 @@ config DRM_MALI_DISPLAY
        depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
        depends on COMMON_CLK
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VIDEOMODE_HELPERS
        help
          Choose this option if you want to compile the ARM Mali Display
index e91598b60781aad3cecbcd1fcd4a80f9f43a48d3..4acc4285a4eb06dd5c3e462963e50df75a587484 100644 (file)
@@ -4,7 +4,7 @@ config DRM_KOMEDA
        depends on DRM && OF
        depends on COMMON_CLK
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VIDEOMODE_HELPERS
        help
          Choose this option if you want to compile the ARM Komeda display
index daa1faccd3e7e3253365e24b025206ba1d46bc63..6c56f5662bc7bc54b83d58323c795a36b14027b8 100644 (file)
@@ -310,8 +310,7 @@ static int d71_reset(struct d71_dev *d71)
        u32 __iomem *gcu = d71->gcu_addr;
        int ret;
 
-       malidp_write32_mask(gcu, BLK_CONTROL,
-                           GCU_CONTROL_SRST, GCU_CONTROL_SRST);
+       malidp_write32(gcu, BLK_CONTROL, GCU_CONTROL_SRST);
 
        ret = dp_wait_cond(!(malidp_read32(gcu, BLK_CONTROL) & GCU_CONTROL_SRST),
                           100, 1000, 10000);
index 59172acb973803d29c853ea4f2ad9a5538770ae3..4cc07d6bb9d82eb4bb475a2bff2d1f732417391f 100644 (file)
@@ -11,7 +11,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_vblank.h>
 
@@ -235,7 +234,7 @@ void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
                        crtc->state->event = NULL;
                        drm_crtc_send_vblank_event(crtc, event);
                } else {
-                       DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
+                       DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n",
                                 drm_crtc_index(&kcrtc->base));
                }
                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
@@ -286,7 +285,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
        komeda_crtc_do_flush(crtc, old);
 }
 
-static void
+void
 komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
                                         struct completion *input_flip_done)
 {
index ba16895690f1c42cd5a781532471db0c96b60e7b..9fce4239d4ad4d39f19428029e0f41a09b4b5524 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/component.h>
 #include <linux/pm_runtime.h>
+#include <drm/drm_fb_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_of.h>
 #include "komeda_dev.h"
@@ -72,6 +73,7 @@ static int komeda_bind(struct device *dev)
        }
 
        dev_set_drvdata(dev, mdrv);
+       drm_fbdev_generic_setup(&mdrv->kms->base, 32);
 
        return 0;
 
index 3c372d2deb0a697bbb4a20287ba3a48c4e74f29d..df5da5a447555c50bd98ffc36e6b80d03b52352f 100644 (file)
@@ -5,9 +5,9 @@
  *
  */
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 
 #include "komeda_framebuffer.h"
@@ -137,7 +137,7 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb,
                }
 
                min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i)
-                        - to_drm_gem_cma_obj(obj)->paddr;
+                        - to_drm_gem_dma_obj(obj)->dma_addr;
                if (obj->size < min_size) {
                        DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n",
                                      i, obj->size, min_size);
@@ -239,7 +239,7 @@ dma_addr_t
 komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
 {
        struct drm_framebuffer *fb = &kfb->base;
-       const struct drm_gem_cma_object *obj;
+       const struct drm_gem_dma_object *obj;
        u32 offset, plane_x, plane_y, block_w, block_sz;
 
        if (plane >= fb->format->num_planes) {
@@ -247,7 +247,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
                return -EINVAL;
        }
 
-       obj = drm_fb_cma_get_gem_obj(fb, plane);
+       obj = drm_fb_dma_get_gem_obj(fb, plane);
 
        offset = fb->offsets[plane];
        if (!fb->modifier) {
@@ -260,7 +260,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
                        + plane_y * fb->pitches[plane];
        }
 
-       return obj->paddr + offset;
+       return obj->dma_addr + offset;
 }
 
 /* if the fb can be supported by a specific layer */
index 93b7f09b96ca95041ee25760df81d2e4c1f19547..451746ebbe7138cdbafbe42914e546d1db05e1aa 100644 (file)
@@ -11,7 +11,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
@@ -21,9 +21,9 @@
 #include "komeda_framebuffer.h"
 #include "komeda_kms.h"
 
-DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops);
+DEFINE_DRM_GEM_DMA_FOPS(komeda_cma_fops);
 
-static int komeda_gem_cma_dumb_create(struct drm_file *file,
+static int komeda_gem_dma_dumb_create(struct drm_file *file,
                                      struct drm_device *dev,
                                      struct drm_mode_create_dumb *args)
 {
@@ -32,7 +32,7 @@ static int komeda_gem_cma_dumb_create(struct drm_file *file,
 
        args->pitch = ALIGN(pitch, mdev->chip.bus_width);
 
-       return drm_gem_cma_dumb_create_internal(file, dev, args);
+       return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
 
 static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
@@ -60,7 +60,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
 static const struct drm_driver komeda_kms_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .lastclose                      = drm_fb_helper_lastclose,
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_dma_dumb_create),
        .fops = &komeda_cma_fops,
        .name = "komeda",
        .desc = "Arm Komeda Display Processor driver",
@@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = {
        .minor = 1,
 };
 
+static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state)
+{
+       struct drm_device *dev = state->dev;
+       struct komeda_kms_dev *kms = to_kdev(dev);
+       int i;
+
+       for (i = 0; i < kms->n_crtcs; i++) {
+               struct komeda_crtc *kcrtc = &kms->crtcs[i];
+
+               if (kcrtc->base.state->active) {
+                       struct completion *flip_done = NULL;
+                       if (kcrtc->base.state->event)
+                               flip_done = kcrtc->base.state->event->base.completion;
+                       komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done);
+               }
+       }
+       drm_atomic_helper_commit_hw_done(state);
+}
+
 static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *dev = old_state->dev;
@@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
 
        drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
-       drm_atomic_helper_commit_hw_done(old_state);
+       komeda_kms_atomic_commit_hw_done(old_state);
 
        drm_atomic_helper_wait_for_flip_done(dev, old_state);
 
index 7889e380ab23c17734fe7259f6f2425d67ce8210..7339339ef6b87cc0f8a06e02a0a6014ebce37c70 100644 (file)
@@ -183,6 +183,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms);
 
 void komeda_crtc_handle_event(struct komeda_crtc   *kcrtc,
                              struct komeda_events *evts);
+void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
+                                             struct completion *input_flip_done);
 
 struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
 void komeda_kms_detach(struct komeda_kms_dev *kms);
index e672b9cffee3c986f2c3a47cac2ea0b19c02cd56..3276a3e82c628ecc47e512bbd5244157451dadd3 100644 (file)
@@ -1271,7 +1271,7 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
        return 0;
 }
 
-/* Since standalong disabled components must be disabled separately and in the
+/* Since standalone disabled components must be disabled separately and in the
  * last, So a complete disable operation may needs to call pipeline_disable
  * twice (two phase disabling).
  * Phase 1: disable the common components, flush it.
index dff22dec54b511bacb29097defea80b7334441b9..c20ff72f0ae580f2ddd6fe19d1c36d1a0022cf59 100644 (file)
@@ -7,7 +7,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include "komeda_dev.h"
 #include "komeda_kms.h"
index afc9cd8565015b9e3d3b92be715939ef111fbd9e..7030339fa2323642421b43c98d8a970a63b42ed5 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_of.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
@@ -252,8 +251,8 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
                        return -EINVAL;
                return drm_atomic_helper_check_plane_state(new_plane_state,
                                                           crtc_state,
-                                                          DRM_PLANE_HELPER_NO_SCALING,
-                                                          DRM_PLANE_HELPER_NO_SCALING,
+                                                          DRM_PLANE_NO_SCALING,
+                                                          DRM_PLANE_NO_SCALING,
                                                           false, true);
        }
 
@@ -274,7 +273,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
                return;
 
        dest_h = drm_rect_height(&new_plane_state->dst);
-       scanout_start = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
+       scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
 
        hdlcd = plane->dev->dev_private;
        hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
index e89ae0ec60eb76d4a9f79a124a2554ea082a3898..a032003c340cc9690ff352456cebf776209e2fb3 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 
+#include <drm/drm_aperture.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_module.h>
@@ -40,8 +40,7 @@
 
 static irqreturn_t hdlcd_irq(int irq, void *arg)
 {
-       struct drm_device *drm = arg;
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       struct hdlcd_drm_private *hdlcd = arg;
        unsigned long irq_status;
 
        irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
@@ -69,61 +68,32 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-static void hdlcd_irq_preinstall(struct drm_device *drm)
+static int hdlcd_irq_install(struct hdlcd_drm_private *hdlcd)
 {
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
+       int ret;
+
        /* Ensure interrupts are disabled */
        hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
        hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
-}
-
-static void hdlcd_irq_postinstall(struct drm_device *drm)
-{
-#ifdef CONFIG_DEBUG_FS
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
-       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-       /* enable debug interrupts */
-       irq_mask |= HDLCD_DEBUG_INT_MASK;
-
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
-#endif
-}
-
-static int hdlcd_irq_install(struct drm_device *drm, int irq)
-{
-       int ret;
-
-       if (irq == IRQ_NOTCONNECTED)
-               return -ENOTCONN;
-
-       hdlcd_irq_preinstall(drm);
 
-       ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm);
+       ret = request_irq(hdlcd->irq, hdlcd_irq, 0, "hdlcd", hdlcd);
        if (ret)
                return ret;
 
-       hdlcd_irq_postinstall(drm);
+#ifdef CONFIG_DEBUG_FS
+       /* enable debug interrupts */
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, HDLCD_DEBUG_INT_MASK);
+#endif
 
        return 0;
 }
 
-static void hdlcd_irq_uninstall(struct drm_device *drm)
+static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd)
 {
-       struct hdlcd_drm_private *hdlcd = drm->dev_private;
        /* disable all the interrupts that we might have enabled */
-       unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
-
-#ifdef CONFIG_DEBUG_FS
-       /* disable debug interrupts */
-       irq_mask &= ~HDLCD_DEBUG_INT_MASK;
-#endif
-
-       /* disable vsync interrupts */
-       irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
-       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
+       hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
 
-       free_irq(hdlcd->irq, drm);
+       free_irq(hdlcd->irq, hdlcd);
 }
 
 static int hdlcd_load(struct drm_device *drm, unsigned long flags)
@@ -183,7 +153,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
                goto irq_fail;
        hdlcd->irq = ret;
 
-       ret = hdlcd_irq_install(drm, hdlcd->irq);
+       ret = hdlcd_irq_install(hdlcd);
        if (ret < 0) {
                DRM_ERROR("failed to install IRQ handler\n");
                goto irq_fail;
@@ -255,11 +225,11 @@ static void hdlcd_debugfs_init(struct drm_minor *minor)
 }
 #endif
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver hdlcd_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init = hdlcd_debugfs_init,
 #endif
@@ -314,6 +284,15 @@ static int hdlcd_drm_bind(struct device *dev)
                goto err_vblank;
        }
 
+       /*
+        * If EFI left us running, take over from simple framebuffer
+        * drivers. Read HDLCD_REG_COMMAND to see if we are enabled.
+        */
+       if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) {
+               hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
+               drm_aperture_remove_framebuffers(false, &hdlcd_driver);
+       }
+
        drm_mode_config_reset(drm);
        drm_kms_helper_poll_init(drm);
 
@@ -335,7 +314,7 @@ err_pm_active:
 err_unload:
        of_node_put(hdlcd->crtc.port);
        hdlcd->crtc.port = NULL;
-       hdlcd_irq_uninstall(drm);
+       hdlcd_irq_uninstall(hdlcd);
        of_reserved_mem_device_release(drm->dev);
 err_free:
        drm_mode_config_cleanup(drm);
@@ -357,7 +336,7 @@ static void hdlcd_drm_unbind(struct device *dev)
        hdlcd->crtc.port = NULL;
        pm_runtime_get_sync(dev);
        drm_atomic_helper_shutdown(drm);
-       hdlcd_irq_uninstall(drm);
+       hdlcd_irq_uninstall(hdlcd);
        pm_runtime_put(dev);
        if (pm_runtime_enabled(dev))
                pm_runtime_disable(dev);
index d5aef21426cf9764f914d3c8f58796afed664c39..1d0b0c54ccc74a96d1486e2108b1e007f4600ee1 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_module.h>
@@ -457,7 +456,7 @@ static int malidp_irq_init(struct platform_device *pdev)
        return 0;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static int malidp_dumb_create(struct drm_file *file_priv,
                              struct drm_device *drm,
@@ -469,7 +468,7 @@ static int malidp_dumb_create(struct drm_file *file_priv,
 
        args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment);
 
-       return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
+       return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -566,7 +565,7 @@ static void malidp_debugfs_init(struct drm_minor *minor)
 
 static const struct drm_driver malidp_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init = malidp_debugfs_init,
 #endif
index b66ca5b33a7f4837e5e5b19a49cc2325318dab0f..ef76d0e6ee2fc479372dfbc12bfcd6718e9ddb2f 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_writeback.h>
 
@@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
 
        n_planes = fb->format->num_planes;
        for (i = 0; i < n_planes; i++) {
-               struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);
+               struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, i);
                /* memory write buffers are never rotated */
                u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0);
 
@@ -170,7 +170,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
                        return -EINVAL;
                }
                mw_state->pitches[i] = fb->pitches[i];
-               mw_state->addrs[i] = obj->paddr + fb->offsets[i];
+               mw_state->addrs[i] = obj->dma_addr + fb->offsets[i];
        }
        mw_state->n_planes = n_planes;
 
index 8a9562642d16d16b545bf7544a41decbce886c04..45f5e35e7f243b8a0ffde89bc7e9f2e9f07dd17c 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 
 #include "malidp_hw.h"
@@ -334,15 +333,15 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
 
        for (i = 0; i < ms->n_planes; i++) {
                struct drm_gem_object *obj;
-               struct drm_gem_cma_object *cma_obj;
+               struct drm_gem_dma_object *dma_obj;
                struct sg_table *sgt;
                struct scatterlist *sgl;
 
                obj = drm_gem_fb_get_obj(ms->base.fb, i);
-               cma_obj = to_drm_gem_cma_obj(obj);
+               dma_obj = to_drm_gem_dma_obj(obj);
 
-               if (cma_obj->sgt)
-                       sgt = cma_obj->sgt;
+               if (dma_obj->sgt)
+                       sgt = dma_obj->sgt;
                else
                        sgt = obj->funcs->get_sg_table(obj);
 
@@ -353,14 +352,14 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
 
                while (sgl) {
                        if (sgl->length < pgsize) {
-                               if (!cma_obj->sgt)
+                               if (!dma_obj->sgt)
                                        kfree(sgt);
                                return false;
                        }
 
                        sgl = sg_next(sgl);
                }
-               if (!cma_obj->sgt)
+               if (!dma_obj->sgt)
                        kfree(sgt);
        }
 
@@ -715,7 +714,7 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
                                       struct malidp_plane *mp,
                                       int plane_index)
 {
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        u16 ptr;
        struct drm_plane *plane = &mp->base;
        bool afbc = fb->modifier ? true : false;
@@ -723,27 +722,27 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
        ptr = mp->layer->ptr + (plane_index << 4);
 
        /*
-        * drm_fb_cma_get_gem_addr() alters the physical base address of the
+        * drm_fb_dma_get_gem_addr() alters the physical base address of the
         * framebuffer as per the plane's src_x, src_y co-ordinates (ie to
         * take care of source cropping).
         * For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
         * and _AD_CROP_V registers.
         */
        if (!afbc) {
-               paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
-                                               plane_index);
+               dma_addr = drm_fb_dma_get_gem_addr(fb, plane->state,
+                                                  plane_index);
        } else {
-               struct drm_gem_cma_object *obj;
+               struct drm_gem_dma_object *obj;
 
-               obj = drm_fb_cma_get_gem_obj(fb, plane_index);
+               obj = drm_fb_dma_get_gem_obj(fb, plane_index);
 
                if (WARN_ON(!obj))
                        return;
-               paddr = obj->paddr;
+               dma_addr = obj->dma_addr;
        }
 
-       malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
-       malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
+       malidp_hw_write(mp->hwdev, lower_32_bits(dma_addr), ptr);
+       malidp_hw_write(mp->hwdev, upper_32_bits(dma_addr), ptr + 4);
 }
 
 static void malidp_de_set_plane_afbc(struct drm_plane *plane)
index 514c50dcb74ddd65462b4e621a4b5f7199718f9a..3bc16db70ddbeb7112667e7261d9a75ce6fc8377 100644 (file)
 #define     MALIDP_SE_COEFFTAB_DATA_MASK       0x3fff
 #define     MALIDP_SE_SET_COEFFTAB_DATA(x) \
                ((x) & MALIDP_SE_COEFFTAB_DATA_MASK)
-/* Enhance coeffents reigster offset */
+/* Enhance coefficients register offset */
 #define MALIDP_SE_IMAGE_ENH                    0x3C
 /* ENH_LIMITS offset 0x0 */
 #define     MALIDP_SE_ENH_LOW_LEVEL            24
index b7bb90ae787f7cb209aedff1caf3fa383f340f50..15dd667aa2e76840efffa9100f07046b7a70a02f 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
index 147abf1a3968d49db12af0cdca358985c71a2bbb..5430265ad4588377b5efb02e486725fd8b12660a 100644 (file)
@@ -107,11 +107,11 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
        }
 
        /*
-        * We could grab something from CMA if it's enabled, but that
+        * We could grab something from DMA if it's enabled, but that
         * involves building in a problem:
         *
-        * CMA's interface uses dma_alloc_coherent(), which provides us
-        * with an CPU virtual address and a device address.
+        * GEM DMA helper interface uses dma_alloc_coherent(), which provides
+        * us with an CPU virtual address and a device address.
         *
         * The CPU virtual address may be either an address in the kernel
         * direct mapped region (for example, as it would be on x86) or
index 424250535fed9e87a088e82250d86061790c27e0..f21eb8fb76d87285584ac93a0619cf8f83251f05 100644 (file)
@@ -298,12 +298,6 @@ fail:
        return ret;
 }
 
-static void armada_ovl_plane_destroy(struct drm_plane *plane)
-{
-       drm_plane_cleanup(plane);
-       kfree(plane);
-}
-
 static void armada_overlay_reset(struct drm_plane *plane)
 {
        struct armada_overlay_state *state;
@@ -468,7 +462,7 @@ static int armada_overlay_get_property(struct drm_plane *plane,
 static const struct drm_plane_funcs armada_ovl_plane_funcs = {
        .update_plane   = armada_overlay_plane_update,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = armada_ovl_plane_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset          = armada_overlay_reset,
        .atomic_duplicate_state = armada_overlay_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
index 959d7f0a5108512eb99fe13634b72b10622cfbe3..cc47c032dbc151a463cbd0b0d048c74c2828f253 100644 (file)
@@ -288,7 +288,7 @@ struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane)
 static const struct drm_plane_funcs armada_primary_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset          = armada_plane_reset,
        .atomic_duplicate_state = armada_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
index 024ccab14f884aa8a4226b0925edbc722515e105..8137c39b057bb386a8a109d6ce0d817e91e341ac 100644 (file)
@@ -5,7 +5,7 @@ config DRM_ASPEED_GFX
        depends on (COMPILE_TEST || ARCH_ASPEED)
        depends on MMU
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DMA_CMA if HAVE_DMA_CONTIGUOUS
        select CMA if HAVE_DMA_CONTIGUOUS
        select MFD_SYSCON
index f3788d7d82d6b30bec915f4c69d2d4b6d2b2ca2b..55a3444a51d8a84acc250a5c2dd0ba95059b0aa2 100644 (file)
@@ -7,11 +7,11 @@
 
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
@@ -168,7 +168,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe,
        struct drm_crtc *crtc = &pipe->crtc;
        struct drm_framebuffer *fb = pipe->plane.state->fb;
        struct drm_pending_vblank_event *event;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
 
        spin_lock_irq(&crtc->dev->event_lock);
        event = crtc->state->event;
@@ -185,10 +185,10 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe,
        if (!fb)
                return;
 
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
        if (!gem)
                return;
-       writel(gem->paddr, priv->base + CRT_ADDR);
+       writel(gem->dma_addr, priv->base + CRT_ADDR);
 }
 
 static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe)
index 7780b72de9e806b373b22b28d5309dca681315fc..a94f1a9e8f4094b16bc8f9bcb7c7d1a64d194c17 100644 (file)
@@ -16,9 +16,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -246,11 +245,11 @@ static void aspeed_gfx_unload(struct drm_device *drm)
        drm_kms_helper_poll_fini(drm);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver aspeed_gfx_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops = &fops,
        .name = "aspeed-gfx-drm",
        .desc = "ASPEED GFX DRM",
index 214b10178454d9a02b0bd6051cada60447eab108..103bd4fa698bd3bf7fa918ce45be3e393f308c02 100644 (file)
@@ -42,7 +42,6 @@
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_gem_vram_helper.h>
 #include <drm/drm_managed.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
@@ -555,8 +554,8 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
                                                   new_plane_state->crtc);
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  false, true);
        if (ret)
                return ret;
@@ -779,8 +778,8 @@ static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
                                                   new_plane_state->crtc);
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        if (ret)
                return ret;
index 8ae679f1a51852306f27d7a8a48b4b5b92a0fead..3bdbab3a6333bbb3e80443de99d6ff76cd85c6c2 100644 (file)
@@ -2,7 +2,7 @@
 config DRM_ATMEL_HLCDC
        tristate "DRM Support for ATMEL HLCDC Display Controller"
        depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_PANEL
        help
index 651e3c10936067d57b114c8d0c44091a8a4c38be..f7e7f4e919c779eebeaa32136089632482af0927 100644 (file)
@@ -20,7 +20,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -730,11 +730,11 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
        clk_disable_unprepare(dc->hlcdc->periph_clk);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver atmel_hlcdc_dc_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops = &fops,
        .name = "atmel-hlcdc",
        .desc = "Atmel HLCD Controller DRM",
index 2306ceb3e9999781da2fdf4a1577b06f092eafbe..daa508504f47d69e81a336c37e89355ade59fa59 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "atmel_hlcdc_dc.h"
 
@@ -449,9 +448,9 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
        sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
 
        for (i = 0; i < state->nplanes; i++) {
-               struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
+               struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
 
-               state->dscrs[i]->addr = gem->paddr + state->offsets[i];
+               state->dscrs[i]->addr = gem->dma_addr + state->offsets[i];
 
                atmel_hlcdc_layer_write_reg(&plane->layer,
                                            ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
index a031a0cd1f181022e193d9d4cc6a26ea343082a0..94de73cbeb2ddd893652e947648360e838a61ebe 100644 (file)
@@ -394,10 +394,7 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
 #else
 static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 {
-       unsigned int offset = adv7511->type == ADV7533 ?
-                                               ADV7533_REG_CEC_OFFSET : 0;
-
-       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
+       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
                     ADV7511_CEC_CTRL_POWER_DOWN);
        return 0;
 }
index 0b266f28f150f980ec6c514fe08010ecaa217cca..99964f5a5457b7f402ee27f325a43b1cd267da6a 100644 (file)
@@ -359,7 +359,7 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
                goto err_cec_alloc;
        }
 
-       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
+       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
        /* cec soft reset */
        regmap_write(adv7511->regmap_cec,
                     ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
@@ -386,7 +386,7 @@ err_cec_alloc:
        dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
                 ret);
 err_cec_parse_dt:
-       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
+       regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
                     ADV7511_CEC_CTRL_POWER_DOWN);
        return ret == -EPROBE_DEFER ? ret : 0;
 }
index 38bf28720f3a2993cca051c886061eeaab3f7b46..6031bdd9234203025498b7f4319b90762f9b9c1d 100644 (file)
@@ -1340,9 +1340,6 @@ static int adv7511_remove(struct i2c_client *i2c)
 {
        struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
 
-       i2c_unregister_device(adv7511->i2c_cec);
-       clk_disable_unprepare(adv7511->cec_clk);
-
        adv7511_uninit_regulators(adv7511);
 
        drm_bridge_remove(&adv7511->bridge);
@@ -1350,6 +1347,8 @@ static int adv7511_remove(struct i2c_client *i2c)
        adv7511_audio_exit(adv7511);
 
        cec_unregister_adapter(adv7511->cec_adap);
+       i2c_unregister_device(adv7511->i2c_cec);
+       clk_disable_unprepare(adv7511->cec_clk);
 
        i2c_unregister_device(adv7511->i2c_packet);
        i2c_unregister_device(adv7511->i2c_edid);
index d1f1d525aeb6d4e4bb788a61914d9682fc318dbb..79fc7a50b4976dde5c46fb1fd3c65d882a010c04 100644 (file)
@@ -1642,6 +1642,7 @@ static int anx7625_parse_dt(struct device *dev,
        anx7625_get_swing_setting(dev, pdata);
 
        pdata->is_dpi = 0; /* default dsi mode */
+       of_node_put(pdata->mipi_host_node);
        pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
        if (!pdata->mipi_host_node) {
                DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
index 481c86b2406e8b8f8a9de793c86825e1e40d9329..b07d2d16c3cfc3f9397b9d71ccbb7330cd97464e 100644 (file)
@@ -735,14 +735,12 @@ static int chipone_i2c_probe(struct i2c_client *client,
        return chipone_dsi_host_attach(icn);
 }
 
-static int chipone_dsi_remove(struct mipi_dsi_device *dsi)
+static void chipone_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct chipone *icn = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_bridge_remove(&icn->bridge);
-
-       return 0;
 }
 
 static const struct of_device_id chipone_of_match[] = {
index 4b673c4792d77aa6f7b56b23741d5617a3bcbc8e..f9251ec49bf0991b28ca98e82e48732021704acb 100644 (file)
@@ -506,6 +506,9 @@ static int it6505_read(struct it6505 *it6505, unsigned int reg_addr)
        int err;
        struct device *dev = &it6505->client->dev;
 
+       if (!it6505->powered)
+               return -ENODEV;
+
        err = regmap_read(it6505->regmap, reg_addr, &value);
        if (err < 0) {
                dev_err(dev, "read failed reg[0x%x] err: %d", reg_addr, err);
@@ -521,6 +524,9 @@ static int it6505_write(struct it6505 *it6505, unsigned int reg_addr,
        int err;
        struct device *dev = &it6505->client->dev;
 
+       if (!it6505->powered)
+               return -ENODEV;
+
        err = regmap_write(it6505->regmap, reg_addr, reg_val);
 
        if (err < 0) {
@@ -538,6 +544,9 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
        int err;
        struct device *dev = &it6505->client->dev;
 
+       if (!it6505->powered)
+               return -ENODEV;
+
        err = regmap_update_bits(it6505->regmap, reg, mask, value);
        if (err < 0) {
                dev_err(dev, "write reg[0x%x] = 0x%x mask = 0x%x failed err %d",
@@ -682,7 +691,7 @@ static void it6505_calc_video_info(struct it6505 *it6505)
        DRM_DEV_DEBUG_DRIVER(dev, "hactive_start:%d, vactive_start:%d",
                             hdes, vdes);
 
-       for (i = 0; i < 10; i++) {
+       for (i = 0; i < 3; i++) {
                it6505_set_bits(it6505, REG_DATA_CTRL0, ENABLE_PCLK_COUNTER,
                                ENABLE_PCLK_COUNTER);
                usleep_range(10000, 15000);
@@ -699,7 +708,7 @@ static void it6505_calc_video_info(struct it6505 *it6505)
                return;
        }
 
-       sum /= 10;
+       sum /= 3;
        pclk = 13500 * 2048 / sum;
        it6505->video_info.clock = pclk;
        it6505->video_info.hdisplay = hdew;
@@ -2341,8 +2350,6 @@ static void it6505_irq_hpd(struct it6505 *it6505)
 
                if (!it6505_get_video_status(it6505))
                        it6505_video_reset(it6505);
-
-               it6505_calc_video_info(it6505);
        } else {
                memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
 
@@ -2559,13 +2566,12 @@ static int it6505_poweron(struct it6505 *it6505)
                usleep_range(10000, 20000);
        }
 
+       it6505->powered = true;
        it6505_reset_logic(it6505);
        it6505_int_mask_enable(it6505);
        it6505_init(it6505);
        it6505_lane_off(it6505);
 
-       it6505->powered = true;
-
        return 0;
 }
 
@@ -2945,6 +2951,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
        if (ret)
                dev_err(dev, "Failed to setup AVI infoframe: %d", ret);
 
+       it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link,
+                                    DP_SET_POWER_D0);
+
        it6505_update_video_parameter(it6505, mode);
 
        ret = it6505_send_video_infoframe(it6505, &frame);
@@ -3044,7 +3053,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
                return PTR_ERR(pdata->ovdd);
        }
 
-       pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+       pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
        if (IS_ERR(pdata->gpiod_reset)) {
                dev_err(dev, "gpiod_reset gpio not found");
                return PTR_ERR(pdata->gpiod_reset);
index 8a60e83482a045082670fbd496610c17bc6c1b1e..5fccacc159f0038ae89a01eb28d9dba65fd095cf 100644 (file)
@@ -813,13 +813,14 @@ static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt961
 
        drm_connector_helper_add(&lt9611->connector,
                                 &lt9611_bridge_connector_helper_funcs);
-       drm_connector_attach_encoder(&lt9611->connector, bridge->encoder);
 
        if (!bridge->encoder) {
                DRM_ERROR("Parent encoder object not found");
                return -ENODEV;
        }
 
+       drm_connector_attach_encoder(&lt9611->connector, bridge->encoder);
+
        return 0;
 }
 
index 4277bf4f032bebac4d4e91ef53547d0037fe6478..216af76d00427b52b5a9392969798fe2c5f1f62c 100644 (file)
@@ -8,6 +8,7 @@
 #include <drm/drm_bridge.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
@@ -367,6 +368,44 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
 }
 EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
 
+static void drmm_drm_panel_bridge_release(struct drm_device *drm, void *ptr)
+{
+       struct drm_bridge *bridge = ptr;
+
+       drm_panel_bridge_remove(bridge);
+}
+
+/**
+ * drmm_panel_bridge_add - Creates a DRM-managed &drm_bridge and
+ *                         &drm_connector that just calls the
+ *                         appropriate functions from &drm_panel.
+ *
+ * @drm: DRM device to tie the bridge lifetime to
+ * @panel: The drm_panel being wrapped.  Must be non-NULL.
+ *
+ * This is the DRM-managed version of drm_panel_bridge_add() which
+ * automatically calls drm_panel_bridge_remove() when @dev is cleaned
+ * up.
+ */
+struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm,
+                                        struct drm_panel *panel)
+{
+       struct drm_bridge *bridge;
+       int ret;
+
+       bridge = drm_panel_bridge_add_typed(panel, panel->connector_type);
+       if (IS_ERR(bridge))
+               return bridge;
+
+       ret = drmm_add_action_or_reset(drm, drmm_drm_panel_bridge_release,
+                                      bridge);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return bridge;
+}
+EXPORT_SYMBOL(drmm_panel_bridge_add);
+
 /**
  * drm_panel_bridge_connector - return the connector for the panel bridge
  * @bridge: The drm_bridge.
@@ -420,4 +459,39 @@ struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
        return bridge;
 }
 EXPORT_SYMBOL(devm_drm_of_get_bridge);
+
+/**
+ * drmm_of_get_bridge - Return next bridge in the chain
+ * @drm: device to tie the bridge lifetime to
+ * @np: device tree node containing encoder output ports
+ * @port: port in the device tree node
+ * @endpoint: endpoint in the device tree node
+ *
+ * Given a DT node's port and endpoint number, finds the connected node
+ * and returns the associated bridge if any, or creates and returns a
+ * drm panel bridge instance if a panel is connected.
+ *
+ * Returns a drmm managed pointer to the bridge if successful, or an error
+ * pointer otherwise.
+ */
+struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
+                                     struct device_node *np,
+                                     u32 port, u32 endpoint)
+{
+       struct drm_bridge *bridge;
+       struct drm_panel *panel;
+       int ret;
+
+       ret = drm_of_find_panel_or_bridge(np, port, endpoint,
+                                         &panel, &bridge);
+       if (ret)
+               return ERR_PTR(ret);
+
+       if (panel)
+               bridge = drmm_panel_bridge_add(drm, panel);
+
+       return bridge;
+}
+EXPORT_SYMBOL(drmm_of_get_bridge);
+
 #endif
index 31e88cb39f8a0d7fc013f81aa4cf46ea6bd3cc56..49107a6cdac189f6bbff07c997a0602c77650c23 100644 (file)
@@ -631,8 +631,8 @@ static int ps8640_probe(struct i2c_client *client)
        if (!ps_bridge)
                return -ENOMEM;
 
-       ps_bridge->supplies[0].supply = "vdd33";
-       ps_bridge->supplies[1].supply = "vdd12";
+       ps_bridge->supplies[0].supply = "vdd12";
+       ps_bridge->supplies[1].supply = "vdd33";
        ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies),
                                      ps_bridge->supplies);
        if (ret)
index 40439da4db49797646d4c8227b38718f62c80cc5..7f4fce1aa998886100918c04190afa775797fab2 100644 (file)
@@ -241,14 +241,12 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int tc358762_remove(struct mipi_dsi_device *dsi)
+static void tc358762_remove(struct mipi_dsi_device *dsi)
 {
        struct tc358762 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_bridge_remove(&ctx->bridge);
-
-       return 0;
 }
 
 static const struct of_device_id tc358762_of_match[] = {
index fdfb14aca926f0c65742e22475d356c1f19131e9..53259c12d7778bd08cc39b3638aebe044cc292c5 100644 (file)
@@ -381,14 +381,12 @@ static int tc358764_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int tc358764_remove(struct mipi_dsi_device *dsi)
+static void tc358764_remove(struct mipi_dsi_device *dsi)
 {
        struct tc358764 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_bridge_remove(&ctx->bridge);
-
-       return 0;
 }
 
 static const struct of_device_id tc358764_of_match[] = {
index 02bd757a89874acc36d43ec3ed82a9e701ec432b..baaed4d37911979b8d4d00197c36c4ff995f7309 100644 (file)
@@ -889,6 +889,7 @@ static int tc_set_edp_video_mode(struct tc_data *tc,
        u32 dp0_syncval;
        u32 bits_per_pixel = 24;
        u32 in_bw, out_bw;
+       u32 dpipxlfmt;
 
        /*
         * Recommended maximum number of symbols transferred in a transfer unit:
@@ -938,10 +939,15 @@ static int tc_set_edp_video_mode(struct tc_data *tc,
        if (ret)
                return ret;
 
-       ret = regmap_write(tc->regmap, DPIPXLFMT,
-                          VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
-                          DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 |
-                          DPI_BPP_RGB888);
+       dpipxlfmt = DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888;
+
+       if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+               dpipxlfmt |= VS_POL_ACTIVE_LOW;
+
+       if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+               dpipxlfmt |= HS_POL_ACTIVE_LOW;
+
+       ret = regmap_write(tc->regmap, DPIPXLFMT, dpipxlfmt);
        if (ret)
                return ret;
 
@@ -1244,7 +1250,13 @@ static int tc_main_link_disable(struct tc_data *tc)
        if (ret)
                return ret;
 
-       return regmap_write(tc->regmap, DP0CTL, 0);
+       ret = regmap_write(tc->regmap, DP0CTL, 0);
+       if (ret)
+               return ret;
+
+       return regmap_update_bits(tc->regmap, DP_PHY_CTRL,
+                                 PHY_M0_RST | PHY_M1_RST | PHY_M0_EN,
+                                 PHY_M0_RST | PHY_M1_RST);
 }
 
 static int tc_dsi_rx_enable(struct tc_data *tc)
@@ -1252,10 +1264,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc)
        u32 value;
        int ret;
 
-       regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 3);
-       regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 3);
-       regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 3);
-       regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 3);
+       regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5);
+       regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5);
+       regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5);
+       regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5);
        regmap_write(tc->regmap, PPI_D0S_ATMR, 0);
        regmap_write(tc->regmap, PPI_D1S_ATMR, 0);
        regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
@@ -1496,41 +1508,16 @@ tc_edp_bridge_atomic_disable(struct drm_bridge *bridge,
                dev_err(tc->dev, "main link disable error: %d\n", ret);
 }
 
-static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
-                                const struct drm_display_mode *mode,
-                                struct drm_display_mode *adj)
-{
-       /* Fixup sync polarities, both hsync and vsync are active low */
-       adj->flags = mode->flags;
-       adj->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
-       adj->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
-
-       return true;
-}
-
-static int tc_common_atomic_check(struct drm_bridge *bridge,
-                                 struct drm_bridge_state *bridge_state,
-                                 struct drm_crtc_state *crtc_state,
-                                 struct drm_connector_state *conn_state,
-                                 const unsigned int max_khz)
-{
-       tc_bridge_mode_fixup(bridge, &crtc_state->mode,
-                            &crtc_state->adjusted_mode);
-
-       if (crtc_state->adjusted_mode.clock > max_khz)
-               return -EINVAL;
-
-       return 0;
-}
-
 static int tc_dpi_atomic_check(struct drm_bridge *bridge,
                               struct drm_bridge_state *bridge_state,
                               struct drm_crtc_state *crtc_state,
                               struct drm_connector_state *conn_state)
 {
        /* DSI->DPI interface clock limitation: upto 100 MHz */
-       return tc_common_atomic_check(bridge, bridge_state, crtc_state,
-                                     conn_state, 100000);
+       if (crtc_state->adjusted_mode.clock > 100000)
+               return -EINVAL;
+
+       return 0;
 }
 
 static int tc_edp_atomic_check(struct drm_bridge *bridge,
@@ -1539,8 +1526,10 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge,
                               struct drm_connector_state *conn_state)
 {
        /* DPI->(e)DP interface clock limitation: upto 154 MHz */
-       return tc_common_atomic_check(bridge, bridge_state, crtc_state,
-                                     conn_state, 154000);
+       if (crtc_state->adjusted_mode.clock > 154000)
+               return -EINVAL;
+
+       return 0;
 }
 
 static enum drm_mode_status
@@ -1783,7 +1772,6 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
        .atomic_check = tc_edp_atomic_check,
        .atomic_enable = tc_edp_bridge_atomic_enable,
        .atomic_disable = tc_edp_bridge_atomic_disable,
-       .mode_fixup = tc_bridge_mode_fixup,
        .detect = tc_bridge_detect,
        .get_edid = tc_get_edid,
        .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
@@ -2010,9 +1998,10 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc)
 
        for_each_endpoint_of_node(dev->of_node, node) {
                of_graph_parse_endpoint(node, &endpoint);
-               if (endpoint.port > 2)
+               if (endpoint.port > 2) {
+                       of_node_put(node);
                        return -EINVAL;
-
+               }
                mode |= BIT(endpoint.port);
        }
 
index d6dd4d99a229a50e1ce180dd30153bd0a9594bff..90bbabde159596761bdc704dc3d61ff419130a84 100644 (file)
@@ -698,11 +698,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
        struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
        int ret;
 
-       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
-               DRM_ERROR("Fix bridge driver to make connector optional!");
-               return -EINVAL;
-       }
-
        pdata->aux.drm_dev = bridge->dev;
        ret = drm_dp_aux_register(&pdata->aux);
        if (ret < 0) {
@@ -710,15 +705,18 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
                return ret;
        }
 
-       /* We never want the next bridge to *also* create a connector: */
-       flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
-
-       /* Attach the next bridge */
+       /*
+        * Attach the next bridge.
+        * We never want the next bridge to *also* create a connector.
+        */
        ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge,
-                               &pdata->bridge, flags);
+                               &pdata->bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
        if (ret < 0)
                goto err_initted_aux;
 
+       if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
+               return 0;
+
        pdata->connector = drm_bridge_connector_init(pdata->bridge.dev,
                                                     pdata->bridge.encoder);
        if (IS_ERR(pdata->connector)) {
@@ -779,9 +777,9 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata)
        regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
 }
 
-static unsigned int ti_sn_bridge_get_bpp(struct ti_sn65dsi86 *pdata)
+static unsigned int ti_sn_bridge_get_bpp(struct drm_connector *connector)
 {
-       if (pdata->connector->display_info.bpc <= 6)
+       if (connector->display_info.bpc <= 6)
                return 18;
        else
                return 24;
@@ -796,7 +794,7 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
        0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
 };
 
-static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
+static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata, unsigned int bpp)
 {
        unsigned int bit_rate_khz, dp_rate_mhz;
        unsigned int i;
@@ -804,7 +802,7 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
                &pdata->bridge.encoder->crtc->state->adjusted_mode;
 
        /* Calculate minimum bit rate based on our pixel clock. */
-       bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata);
+       bit_rate_khz = mode->clock * bpp;
 
        /* Calculate minimum DP data rate, taking 80% as per DP spec */
        dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM,
@@ -1016,12 +1014,21 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
                                       struct drm_bridge_state *old_bridge_state)
 {
        struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
+       struct drm_connector *connector;
        const char *last_err_str = "No supported DP rate";
        unsigned int valid_rates;
        int dp_rate_idx;
        unsigned int val;
        int ret = -EINVAL;
        int max_dp_lanes;
+       unsigned int bpp;
+
+       connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state,
+                                                            bridge->encoder);
+       if (!connector) {
+               dev_err_ratelimited(pdata->dev, "Could not get the connector\n");
+               return;
+       }
 
        max_dp_lanes = ti_sn_get_max_lanes(pdata);
        pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes);
@@ -1047,8 +1054,9 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
        drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET,
                           DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
 
+       bpp = ti_sn_bridge_get_bpp(connector);
        /* Set the DP output format (18 bpp or 24 bpp) */
-       val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0;
+       val = bpp == 18 ? BPP_18_RGB : 0;
        regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val);
 
        /* DP lane config */
@@ -1059,7 +1067,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
        valid_rates = ti_sn_bridge_read_valid_rates(pdata);
 
        /* Train until we run out of rates */
-       for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata);
+       for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata, bpp);
             dp_rate_idx < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut);
             dp_rate_idx++) {
                if (!(valid_rates & BIT(dp_rate_idx)))
@@ -1198,10 +1206,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
        int ret;
 
        pdata->next_bridge = devm_drm_of_get_bridge(pdata->dev, np, 1, 0);
-       if (IS_ERR(pdata->next_bridge)) {
-               DRM_ERROR("failed to create panel bridge\n");
-               return PTR_ERR(pdata->next_bridge);
-       }
+       if (IS_ERR(pdata->next_bridge))
+               return dev_err_probe(pdata->dev, PTR_ERR(pdata->next_bridge),
+                                    "failed to create panel bridge\n");
 
        ti_sn_bridge_parse_lanes(pdata, np);
 
index e5bab236b3ae5c29b801879d0cf6edf6f558ee91..32b295003f49ae5660380f54f494c4313d84ebf7 100644 (file)
@@ -1597,7 +1597,7 @@ static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg)
 
 /*
  * Calculate the length of the i2c transfer in usec, assuming
- * the i2c bus speed is as specified. Gives the the "worst"
+ * the i2c bus speed is as specified. Gives the "worst"
  * case estimate, ie. successful while as long as possible.
  * Doesn't account the "MOT" bit, and instead assumes each
  * message includes a START, ADDRESS and STOP. Neither does it
index 57e65423e50d2ea4f6b38d20c5d4bc2357fed1bb..7a94a5288e8d7823e006d1557d2c3a0443888fbb 100644 (file)
@@ -4907,14 +4907,14 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
                seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
 
                ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
-               if (ret) {
+               if (ret != 2) {
                        seq_printf(m, "faux/mst read failed\n");
                        goto out;
                }
                seq_printf(m, "faux/mst: %*ph\n", 2, buf);
 
                ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
-               if (ret) {
+               if (ret != 1) {
                        seq_printf(m, "mst ctrl read failed\n");
                        goto out;
                }
@@ -4922,7 +4922,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
 
                /* dump the standard OUI branch header */
                ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
-               if (ret) {
+               if (ret != DP_BRANCH_OUI_HEADER_SIZE) {
                        seq_printf(m, "branch oui read failed\n");
                        goto out;
                }
index 8bf41aa240687e50aa1bbbcc850cc7bc224a5d7b..c6abfd3d4b620e472a5ef0863715c413fac6e880 100644 (file)
@@ -38,7 +38,6 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_self_refresh_helper.h>
 #include <drm/drm_vblank.h>
index 6e433d465f41d671dd9f92bd9e3f592283077f05..cf92a9ae8034c94c508f9f23cdbff1144952bb1c 100644 (file)
@@ -140,14 +140,14 @@ struct drm_master *drm_master_create(struct drm_device *dev)
 
        kref_init(&master->refcount);
        drm_master_legacy_init(master);
-       idr_init(&master->magic_map);
+       idr_init_base(&master->magic_map, 1);
        master->dev = dev;
 
        /* initialize the tree of output resource lessees */
        INIT_LIST_HEAD(&master->lessees);
        INIT_LIST_HEAD(&master->lessee_list);
        idr_init(&master->leases);
-       idr_init(&master->lessee_idr);
+       idr_init_base(&master->lessee_idr, 1);
 
        return master;
 }
index 6abf7a2407e9362466c521fda6f8703bf52b848c..1545c50fd1c8f696f256fc30de20d9ddc2b3daee 100644 (file)
@@ -847,8 +847,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
                                    struct drm_connector_state *conn_state,
                                    u32 out_bus_fmt)
 {
+       unsigned int i, num_in_bus_fmts = 0;
        struct drm_bridge_state *cur_state;
-       unsigned int num_in_bus_fmts, i;
        struct drm_bridge *prev_bridge;
        u32 *in_bus_fmts;
        int ret;
@@ -969,7 +969,7 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
        struct drm_connector *conn = conn_state->connector;
        struct drm_encoder *encoder = bridge->encoder;
        struct drm_bridge_state *last_bridge_state;
-       unsigned int i, num_out_bus_fmts;
+       unsigned int i, num_out_bus_fmts = 0;
        struct drm_bridge *last_bridge;
        u32 *out_bus_fmts;
        int ret = 0;
index af3b7395bf6932f70e0b199cfed4d4af9fd4d542..2b230b4d694237524ca52f8e110e415c4d9575d1 100644 (file)
@@ -264,7 +264,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
 
        dumb_args.width = width;
        dumb_args.height = height;
-       dumb_args.bpp = info->cpp[0] * 8;
+       dumb_args.bpp = drm_format_info_bpp(info, 0);
        ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
        if (ret)
                goto err_delete;
@@ -373,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
        int ret;
 
        info = drm_format_info(format);
-       fb_req.bpp = info->cpp[0] * 8;
+       fb_req.bpp = drm_format_info_bpp(info, 0);
        fb_req.depth = info->depth;
        fb_req.width = width;
        fb_req.height = height;
index 17c6c3eefcd661dd0bd0d64cb12663d5a9b55a12..d021497841b84665b08db26088ec67eab9c5f45e 100644 (file)
@@ -575,7 +575,7 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
                len++;
        }
 
-       prop = drm_property_create_enum(dev, 0, "COLOR_RANGE",
+       prop = drm_property_create_enum(dev, 0, "COLOR_RANGE",
                                        enum_list, len);
        if (!prop)
                return -ENOMEM;
index 1ab083b35e3b9c06338a55cee7bf8d5015470a1a..e3142c8142b30cb0fe9019ca64f5c890a527095f 100644 (file)
 
 #include <drm/drm_auth.h>
 #include <drm/drm_connector.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
+#include <drm/drm_file.h>
+#include <drm/drm_managed.h>
 #include <drm/drm_panel.h>
-#include <drm/drm_utils.h>
 #include <drm/drm_print.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_file.h>
 #include <drm/drm_privacy_screen_consumer.h>
 #include <drm/drm_sysfs.h>
+#include <drm/drm_utils.h>
 
 #include <linux/fb.h>
 #include <linux/uaccess.h>
@@ -214,23 +215,11 @@ void drm_connector_free_work_fn(struct work_struct *work)
        }
 }
 
-/**
- * drm_connector_init - Init a preallocated connector
- * @dev: DRM device
- * @connector: the connector to init
- * @funcs: callbacks for this connector
- * @connector_type: user visible type of the connector
- *
- * Initialises a preallocated connector. Connectors should be
- * subclassed as part of driver connector objects.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_connector_init(struct drm_device *dev,
-                      struct drm_connector *connector,
-                      const struct drm_connector_funcs *funcs,
-                      int connector_type)
+static int __drm_connector_init(struct drm_device *dev,
+                               struct drm_connector *connector,
+                               const struct drm_connector_funcs *funcs,
+                               int connector_type,
+                               struct i2c_adapter *ddc)
 {
        struct drm_mode_config *config = &dev->mode_config;
        int ret;
@@ -278,6 +267,9 @@ int drm_connector_init(struct drm_device *dev,
                goto out_put_type_id;
        }
 
+       /* provide ddc symlink in sysfs */
+       connector->ddc = ddc;
+
        INIT_LIST_HEAD(&connector->global_connector_list_entry);
        INIT_LIST_HEAD(&connector->probed_modes);
        INIT_LIST_HEAD(&connector->modes);
@@ -334,6 +326,38 @@ out_put:
 
        return ret;
 }
+
+/**
+ * drm_connector_init - Init a preallocated connector
+ * @dev: DRM device
+ * @connector: the connector to init
+ * @funcs: callbacks for this connector
+ * @connector_type: user visible type of the connector
+ *
+ * Initialises a preallocated connector. Connectors should be
+ * subclassed as part of driver connector objects.
+ *
+ * At driver unload time the driver's &drm_connector_funcs.destroy hook
+ * should call drm_connector_cleanup() and free the connector structure.
+ * The connector structure should not be allocated with devm_kzalloc().
+ *
+ * Note: consider using drmm_connector_init() instead of
+ * drm_connector_init() to let the DRM managed resource infrastructure
+ * take care of cleanup and deallocation.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_connector_init(struct drm_device *dev,
+                      struct drm_connector *connector,
+                      const struct drm_connector_funcs *funcs,
+                      int connector_type)
+{
+       if (drm_WARN_ON(dev, !(funcs && funcs->destroy)))
+               return -EINVAL;
+
+       return __drm_connector_init(dev, connector, funcs, connector_type, NULL);
+}
 EXPORT_SYMBOL(drm_connector_init);
 
 /**
@@ -347,8 +371,16 @@ EXPORT_SYMBOL(drm_connector_init);
  * Initialises a preallocated connector. Connectors should be
  * subclassed as part of driver connector objects.
  *
+ * At driver unload time the driver's &drm_connector_funcs.destroy hook
+ * should call drm_connector_cleanup() and free the connector structure.
+ * The connector structure should not be allocated with devm_kzalloc().
+ *
  * Ensures that the ddc field of the connector is correctly set.
  *
+ * Note: consider using drmm_connector_init() instead of
+ * drm_connector_init_with_ddc() to let the DRM managed resource
+ * infrastructure take care of cleanup and deallocation.
+ *
  * Returns:
  * Zero on success, error code on failure.
  */
@@ -357,19 +389,64 @@ int drm_connector_init_with_ddc(struct drm_device *dev,
                                const struct drm_connector_funcs *funcs,
                                int connector_type,
                                struct i2c_adapter *ddc)
+{
+       if (drm_WARN_ON(dev, !(funcs && funcs->destroy)))
+               return -EINVAL;
+
+       return __drm_connector_init(dev, connector, funcs, connector_type, ddc);
+}
+EXPORT_SYMBOL(drm_connector_init_with_ddc);
+
+static void drm_connector_cleanup_action(struct drm_device *dev,
+                                        void *ptr)
+{
+       struct drm_connector *connector = ptr;
+
+       drm_connector_cleanup(connector);
+}
+
+/**
+ * drmm_connector_init - Init a preallocated connector
+ * @dev: DRM device
+ * @connector: the connector to init
+ * @funcs: callbacks for this connector
+ * @connector_type: user visible type of the connector
+ * @ddc: optional pointer to the associated ddc adapter
+ *
+ * Initialises a preallocated connector. Connectors should be
+ * subclassed as part of driver connector objects.
+ *
+ * Cleanup is automatically handled with a call to
+ * drm_connector_cleanup() in a DRM-managed action.
+ *
+ * The connector structure should be allocated with drmm_kzalloc().
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_connector_init(struct drm_device *dev,
+                       struct drm_connector *connector,
+                       const struct drm_connector_funcs *funcs,
+                       int connector_type,
+                       struct i2c_adapter *ddc)
 {
        int ret;
 
-       ret = drm_connector_init(dev, connector, funcs, connector_type);
+       if (drm_WARN_ON(dev, funcs && funcs->destroy))
+               return -EINVAL;
+
+       ret = __drm_connector_init(dev, connector, funcs, connector_type, NULL);
        if (ret)
                return ret;
 
-       /* provide ddc symlink in sysfs */
-       connector->ddc = ddc;
+       ret = drmm_add_action_or_reset(dev, drm_connector_cleanup_action,
+                                      connector);
+       if (ret)
+               return ret;
 
-       return ret;
+       return 0;
 }
-EXPORT_SYMBOL(drm_connector_init_with_ddc);
+EXPORT_SYMBOL(drmm_connector_init);
 
 /**
  * drm_connector_attach_edid_property - attach edid property.
@@ -517,6 +594,9 @@ EXPORT_SYMBOL(drm_connector_cleanup);
  * e.g. DP MST connectors. All other connectors will be registered automatically
  * when calling drm_dev_register().
  *
+ * When the connector is no longer available, callers must call
+ * drm_connector_unregister().
+ *
  * Returns:
  * Zero on success, error code on failure.
  */
@@ -573,9 +653,8 @@ EXPORT_SYMBOL(drm_connector_register);
  * @connector: the connector to unregister
  *
  * Unregister userspace interfaces for a connector. Only call this for
- * connectors which have registered explicitly by calling drm_dev_register(),
- * since connectors are unregistered automatically when drm_dev_unregister() is
- * called.
+ * connectors which have been registered explicitly by calling
+ * drm_connector_register().
  */
 void drm_connector_unregister(struct drm_connector *connector)
 {
index cad2a7e5166ff3c172c67890e3d3b9e9dcfba7a8..df9bf3c9206e717bdb7409ee0c99574df947ed0b 100644 (file)
@@ -343,9 +343,10 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *
  * The @primary and @cursor planes are only relevant for legacy uAPI, see
  * &drm_crtc.primary and &drm_crtc.cursor.
  *
- * Note: consider using drmm_crtc_alloc_with_planes() instead of
- * drm_crtc_init_with_planes() to let the DRM managed resource infrastructure
- * take care of cleanup and deallocation.
+ * Note: consider using drmm_crtc_alloc_with_planes() or
+ * drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes()
+ * to let the DRM managed resource infrastructure take care of cleanup
+ * and deallocation.
  *
  * Returns:
  * Zero on success, error code on failure.
@@ -370,14 +371,88 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
 }
 EXPORT_SYMBOL(drm_crtc_init_with_planes);
 
-static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
-                                               void *ptr)
+static void drmm_crtc_init_with_planes_cleanup(struct drm_device *dev,
+                                              void *ptr)
 {
        struct drm_crtc *crtc = ptr;
 
        drm_crtc_cleanup(crtc);
 }
 
+__printf(6, 0)
+static int __drmm_crtc_init_with_planes(struct drm_device *dev,
+                                       struct drm_crtc *crtc,
+                                       struct drm_plane *primary,
+                                       struct drm_plane *cursor,
+                                       const struct drm_crtc_funcs *funcs,
+                                       const char *name,
+                                       va_list args)
+{
+       int ret;
+
+       drm_WARN_ON(dev, funcs && funcs->destroy);
+
+       ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
+                                         name, args);
+       if (ret)
+               return ret;
+
+       ret = drmm_add_action_or_reset(dev, drmm_crtc_init_with_planes_cleanup,
+                                      crtc);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+/**
+ * drmm_crtc_init_with_planes - Initialise a new CRTC object with
+ *    specified primary and cursor planes.
+ * @dev: DRM device
+ * @crtc: CRTC object to init
+ * @primary: Primary plane for CRTC
+ * @cursor: Cursor plane for CRTC
+ * @funcs: callbacks for the new CRTC
+ * @name: printf style format string for the CRTC name, or NULL for default name
+ *
+ * Inits a new object created as base part of a driver crtc object. Drivers
+ * should use this function instead of drm_crtc_init(), which is only provided
+ * for backwards compatibility with drivers which do not yet support universal
+ * planes). For really simple hardware which has only 1 plane look at
+ * drm_simple_display_pipe_init() instead.
+ *
+ * Cleanup is automatically handled through registering
+ * drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should
+ * be allocated with drmm_kzalloc().
+ *
+ * The @drm_crtc_funcs.destroy hook must be NULL.
+ *
+ * The @primary and @cursor planes are only relevant for legacy uAPI, see
+ * &drm_crtc.primary and &drm_crtc.cursor.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
+                              struct drm_plane *primary,
+                              struct drm_plane *cursor,
+                              const struct drm_crtc_funcs *funcs,
+                              const char *name, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, name);
+       ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
+                                          name, ap);
+       va_end(ap);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL(drmm_crtc_init_with_planes);
+
 void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
                                    size_t size, size_t offset,
                                    struct drm_plane *primary,
@@ -400,17 +475,12 @@ void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
        crtc = container + offset;
 
        va_start(ap, name);
-       ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
-                                         name, ap);
+       ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
+                                          name, ap);
        va_end(ap);
        if (ret)
                return ERR_PTR(ret);
 
-       ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
-                                      crtc);
-       if (ret)
-               return ERR_PTR(ret);
-
        return container;
 }
 EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
index 8a6d54515f920089ae45ce3e341d615e723e0de0..457448cc60f70e40418aebde128e74c1aed6d5b3 100644 (file)
@@ -45,7 +45,6 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_vblank.h>
 
index bbc25e3b7220a2ffe68b8288d2af56279b1ae208..90a5e26eafa837ca05c0d084fc845b1d077a0d3e 100644 (file)
@@ -5165,6 +5165,51 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
        mode->clock = clock;
 }
 
+static void drm_calculate_luminance_range(struct drm_connector *connector)
+{
+       struct hdr_static_metadata *hdr_metadata = &connector->hdr_sink_metadata.hdmi_type1;
+       struct drm_luminance_range_info *luminance_range =
+               &connector->display_info.luminance_range;
+       static const u8 pre_computed_values[] = {
+               50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
+               71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98
+       };
+       u32 max_avg, min_cll, max, min, q, r;
+
+       if (!(hdr_metadata->metadata_type & BIT(HDMI_STATIC_METADATA_TYPE1)))
+               return;
+
+       max_avg = hdr_metadata->max_fall;
+       min_cll = hdr_metadata->min_cll;
+
+       /*
+        * From the specification (CTA-861-G), for calculating the maximum
+        * luminance we need to use:
+        *      Luminance = 50*2**(CV/32)
+        * Where CV is a one-byte value.
+        * For calculating this expression we may need float point precision;
+        * to avoid this complexity level, we take advantage that CV is divided
+        * by a constant. From the Euclids division algorithm, we know that CV
+        * can be written as: CV = 32*q + r. Next, we replace CV in the
+        * Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just
+        * need to pre-compute the value of r/32. For pre-computing the values
+        * We just used the following Ruby line:
+        *      (0...32).each {|cv| puts (50*2**(cv/32.0)).round}
+        * The results of the above expressions can be verified at
+        * pre_computed_values.
+        */
+       q = max_avg >> 5;
+       r = max_avg % 32;
+       max = (1 << q) * pre_computed_values[r];
+
+       /* min luminance: maxLum * (CV/255)^2 / 100 */
+       q = DIV_ROUND_CLOSEST(min_cll, 255);
+       min = max * DIV_ROUND_CLOSEST((q * q), 100);
+
+       luminance_range->min_luminance = min;
+       luminance_range->max_luminance = max;
+}
+
 static uint8_t eotf_supported(const u8 *edid_ext)
 {
        return edid_ext[2] &
@@ -5196,8 +5241,12 @@ drm_parse_hdr_metadata_block(struct drm_connector *connector, const u8 *db)
                connector->hdr_sink_metadata.hdmi_type1.max_cll = db[4];
        if (len >= 5)
                connector->hdr_sink_metadata.hdmi_type1.max_fall = db[5];
-       if (len >= 6)
+       if (len >= 6) {
                connector->hdr_sink_metadata.hdmi_type1.min_cll = db[6];
+
+               /* Calculate only when all values are available */
+               drm_calculate_luminance_range(connector);
+       }
 }
 
 static void
@@ -6101,6 +6150,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
 
        info->non_desktop = 0;
        memset(&info->monitor_range, 0, sizeof(info->monitor_range));
+       memset(&info->luminance_range, 0, sizeof(info->luminance_range));
 
        info->mso_stream_count = 0;
        info->mso_pixel_overlap = 0;
index a940024c808711a2ced024c4ff917f3b6ac2374a..1143bc7f325227ee252f6d593ffea55d0daa9761 100644 (file)
@@ -27,6 +27,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_managed.h>
+#include <drm/drm_print.h>
 
 #include "drm_crtc_internal.h"
 
@@ -148,9 +149,9 @@ out_put:
  * the encoder structure. The encoder structure should not be allocated with
  * devm_kzalloc().
  *
- * Note: consider using drmm_encoder_alloc() instead of drm_encoder_init() to
- * let the DRM managed resource infrastructure take care of cleanup and
- * deallocation.
+ * Note: consider using drmm_encoder_alloc() or drmm_encoder_init()
+ * instead of drm_encoder_init() to let the DRM managed resource
+ * infrastructure take care of cleanup and deallocation.
  *
  * Returns:
  * Zero on success, error code on failure.
@@ -212,6 +213,30 @@ static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr)
        drm_encoder_cleanup(encoder);
 }
 
+__printf(5, 0)
+static int __drmm_encoder_init(struct drm_device *dev,
+                              struct drm_encoder *encoder,
+                              const struct drm_encoder_funcs *funcs,
+                              int encoder_type,
+                              const char *name,
+                              va_list args)
+{
+       int ret;
+
+       if (drm_WARN_ON(dev, funcs && funcs->destroy))
+               return -EINVAL;
+
+       ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, args);
+       if (ret)
+               return ret;
+
+       ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
                           const struct drm_encoder_funcs *funcs,
                           int encoder_type, const char *name, ...)
@@ -221,9 +246,6 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
        va_list ap;
        int ret;
 
-       if (WARN_ON(funcs && funcs->destroy))
-               return ERR_PTR(-EINVAL);
-
        container = drmm_kzalloc(dev, size, GFP_KERNEL);
        if (!container)
                return ERR_PTR(-ENOMEM);
@@ -231,19 +253,50 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
        encoder = container + offset;
 
        va_start(ap, name);
-       ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
+       ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
        va_end(ap);
        if (ret)
                return ERR_PTR(ret);
 
-       ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
-       if (ret)
-               return ERR_PTR(ret);
-
        return container;
 }
 EXPORT_SYMBOL(__drmm_encoder_alloc);
 
+/**
+ * drmm_encoder_init - Initialize a preallocated encoder
+ * @dev: drm device
+ * @encoder: the encoder to init
+ * @funcs: callbacks for this encoder (optional)
+ * @encoder_type: user visible type of the encoder
+ * @name: printf style format string for the encoder name, or NULL for default name
+ *
+ * Initializes a preallocated encoder. Encoder should be subclassed as
+ * part of driver encoder objects. Cleanup is automatically handled
+ * through registering drm_encoder_cleanup() with drmm_add_action(). The
+ * encoder structure should be allocated with drmm_kzalloc().
+ *
+ * The @drm_encoder_funcs.destroy hook must be NULL.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drmm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder,
+                     const struct drm_encoder_funcs *funcs,
+                     int encoder_type, const char *name, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, name);
+       ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
+       va_end(ap);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL(drmm_encoder_init);
+
 static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
 {
        struct drm_connector *connector;
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
deleted file mode 100644 (file)
index 69c5727..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * drm kms/fb cma (contiguous memory allocator) helper functions
- *
- * Copyright (C) 2012 Analog Devices Inc.
- *   Author: Lars-Peter Clausen <lars@metafoo.de>
- *
- * Based on udl_fbdev.c
- *  Copyright (C) 2012 Red Hat
- */
-
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane.h>
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-
-/**
- * DOC: framebuffer cma helper functions
- *
- * Provides helper functions for creating a cma (contiguous memory allocator)
- * backed framebuffer.
- *
- * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
- * callback function to create a cma backed framebuffer.
- */
-
-/**
- * drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
- * @fb: The framebuffer
- * @plane: Which plane
- *
- * Return the CMA GEM object for given framebuffer.
- *
- * This function will usually be called from the CRTC callback functions.
- */
-struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
-                                                 unsigned int plane)
-{
-       struct drm_gem_object *gem;
-
-       gem = drm_gem_fb_get_obj(fb, plane);
-       if (!gem)
-               return NULL;
-
-       return to_drm_gem_cma_obj(gem);
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
-
-/**
- * drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel
- * formats where values are grouped in blocks this will get you the beginning of
- * the block
- * @fb: The framebuffer
- * @state: Which state of drm plane
- * @plane: Which plane
- * Return the CMA GEM address for given framebuffer.
- *
- * This function will usually be called from the PLANE callback functions.
- */
-dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
-                                  struct drm_plane_state *state,
-                                  unsigned int plane)
-{
-       struct drm_gem_cma_object *obj;
-       dma_addr_t paddr;
-       u8 h_div = 1, v_div = 1;
-       u32 block_w = drm_format_info_block_width(fb->format, plane);
-       u32 block_h = drm_format_info_block_height(fb->format, plane);
-       u32 block_size = fb->format->char_per_block[plane];
-       u32 sample_x;
-       u32 sample_y;
-       u32 block_start_y;
-       u32 num_hblocks;
-
-       obj = drm_fb_cma_get_gem_obj(fb, plane);
-       if (!obj)
-               return 0;
-
-       paddr = obj->paddr + fb->offsets[plane];
-
-       if (plane > 0) {
-               h_div = fb->format->hsub;
-               v_div = fb->format->vsub;
-       }
-
-       sample_x = (state->src_x >> 16) / h_div;
-       sample_y = (state->src_y >> 16) / v_div;
-       block_start_y = (sample_y / block_h) * block_h;
-       num_hblocks = sample_x / block_w;
-
-       paddr += fb->pitches[plane] * block_start_y;
-       paddr += block_size * num_hblocks;
-
-       return paddr;
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
-
-/**
- * drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing
- *     memory
- * @drm: DRM device
- * @old_state: Old plane state
- * @state: New plane state
- *
- * This function can be used by drivers that use damage clips and have
- * CMA GEM objects backed by non-coherent memory. Calling this function
- * in a plane's .atomic_update ensures that all the data in the backing
- * memory have been written to RAM.
- */
-void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
-                                 struct drm_plane_state *old_state,
-                                 struct drm_plane_state *state)
-{
-       const struct drm_format_info *finfo = state->fb->format;
-       struct drm_atomic_helper_damage_iter iter;
-       const struct drm_gem_cma_object *cma_obj;
-       unsigned int offset, i;
-       struct drm_rect clip;
-       dma_addr_t daddr;
-       size_t nb_bytes;
-
-       for (i = 0; i < finfo->num_planes; i++) {
-               cma_obj = drm_fb_cma_get_gem_obj(state->fb, i);
-               if (!cma_obj->map_noncoherent)
-                       continue;
-
-               daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
-               drm_atomic_helper_damage_iter_init(&iter, old_state, state);
-
-               drm_atomic_for_each_plane_damage(&iter, &clip) {
-                       /* Ignore x1/x2 values, invalidate complete lines */
-                       offset = clip.y1 * state->fb->pitches[i];
-
-                       nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
-                       dma_sync_single_for_device(drm->dev, daddr + offset,
-                                                  nb_bytes, DMA_TO_DEVICE);
-               }
-       }
-}
-EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent);
diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c
new file mode 100644 (file)
index 0000000..3b535ad
--- /dev/null
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * drm kms/fb dma helper functions
+ *
+ * Copyright (C) 2012 Analog Devices Inc.
+ *   Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Based on udl_fbdev.c
+ *  Copyright (C) 2012 Red Hat
+ */
+
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_fb_dma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_plane.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+
+/**
+ * DOC: framebuffer dma helper functions
+ *
+ * Provides helper functions for creating a DMA-contiguous framebuffer.
+ *
+ * Depending on the platform, the buffers may be physically non-contiguous and
+ * mapped through an IOMMU or a similar mechanism, or allocated from
+ * physically-contiguous memory (using, for instance, CMA or a pool of memory
+ * reserved at early boot). This is handled behind the scenes by the DMA mapping
+ * API.
+ *
+ * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
+ * callback function to create a DMA-contiguous framebuffer.
+ */
+
+/**
+ * drm_fb_dma_get_gem_obj() - Get DMA GEM object for framebuffer
+ * @fb: The framebuffer
+ * @plane: Which plane
+ *
+ * Return the DMA GEM object for given framebuffer.
+ *
+ * This function will usually be called from the CRTC callback functions.
+ */
+struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
+                                                 unsigned int plane)
+{
+       struct drm_gem_object *gem;
+
+       gem = drm_gem_fb_get_obj(fb, plane);
+       if (!gem)
+               return NULL;
+
+       return to_drm_gem_dma_obj(gem);
+}
+EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj);
+
+/**
+ * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel
+ * formats where values are grouped in blocks this will get you the beginning of
+ * the block
+ * @fb: The framebuffer
+ * @state: Which state of drm plane
+ * @plane: Which plane
+ * Return the DMA GEM address for given framebuffer.
+ *
+ * This function will usually be called from the PLANE callback functions.
+ */
+dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
+                                  struct drm_plane_state *state,
+                                  unsigned int plane)
+{
+       struct drm_gem_dma_object *obj;
+       dma_addr_t dma_addr;
+       u8 h_div = 1, v_div = 1;
+       u32 block_w = drm_format_info_block_width(fb->format, plane);
+       u32 block_h = drm_format_info_block_height(fb->format, plane);
+       u32 block_size = fb->format->char_per_block[plane];
+       u32 sample_x;
+       u32 sample_y;
+       u32 block_start_y;
+       u32 num_hblocks;
+
+       obj = drm_fb_dma_get_gem_obj(fb, plane);
+       if (!obj)
+               return 0;
+
+       dma_addr = obj->dma_addr + fb->offsets[plane];
+
+       if (plane > 0) {
+               h_div = fb->format->hsub;
+               v_div = fb->format->vsub;
+       }
+
+       sample_x = (state->src_x >> 16) / h_div;
+       sample_y = (state->src_y >> 16) / v_div;
+       block_start_y = (sample_y / block_h) * block_h;
+       num_hblocks = sample_x / block_w;
+
+       dma_addr += fb->pitches[plane] * block_start_y;
+       dma_addr += block_size * num_hblocks;
+
+       return dma_addr;
+}
+EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
+
+/**
+ * drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing
+ *     memory
+ * @drm: DRM device
+ * @old_state: Old plane state
+ * @state: New plane state
+ *
+ * This function can be used by drivers that use damage clips and have
+ * DMA GEM objects backed by non-coherent memory. Calling this function
+ * in a plane's .atomic_update ensures that all the data in the backing
+ * memory have been written to RAM.
+ */
+void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
+                                 struct drm_plane_state *old_state,
+                                 struct drm_plane_state *state)
+{
+       const struct drm_format_info *finfo = state->fb->format;
+       struct drm_atomic_helper_damage_iter iter;
+       const struct drm_gem_dma_object *dma_obj;
+       unsigned int offset, i;
+       struct drm_rect clip;
+       dma_addr_t daddr;
+       size_t nb_bytes;
+
+       for (i = 0; i < finfo->num_planes; i++) {
+               dma_obj = drm_fb_dma_get_gem_obj(state->fb, i);
+               if (!dma_obj->map_noncoherent)
+                       continue;
+
+               daddr = drm_fb_dma_get_gem_addr(state->fb, state, i);
+               drm_atomic_helper_damage_iter_init(&iter, old_state, state);
+
+               drm_atomic_for_each_plane_damage(&iter, &clip) {
+                       /* Ignore x1/x2 values, invalidate complete lines */
+                       offset = clip.y1 * state->fb->pitches[i];
+
+                       nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
+                       dma_sync_single_for_device(drm->dev, daddr + offset,
+                                                  nb_bytes, DMA_TO_DEVICE);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
index 2d4cee6a10ffffe7fee950e1e97dfcc96b762726..71edb80fe0fb90611553215d930f76466f51b609 100644 (file)
@@ -377,12 +377,31 @@ static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper,
                                           struct iosys_map *dst)
 {
        struct drm_framebuffer *fb = fb_helper->fb;
-       unsigned int cpp = fb->format->cpp[0];
-       size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
-       void *src = fb_helper->fbdev->screen_buffer + offset;
-       size_t len = (clip->x2 - clip->x1) * cpp;
+       size_t offset = clip->y1 * fb->pitches[0];
+       size_t len = clip->x2 - clip->x1;
        unsigned int y;
+       void *src;
 
+       switch (drm_format_info_bpp(fb->format, 0)) {
+       case 1:
+               offset += clip->x1 / 8;
+               len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
+               break;
+       case 2:
+               offset += clip->x1 / 4;
+               len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
+               break;
+       case 4:
+               offset += clip->x1 / 2;
+               len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
+               break;
+       default:
+               offset += clip->x1 * fb->format->cpp[0];
+               len *= fb->format->cpp[0];
+               break;
+       }
+
+       src = fb_helper->fbdev->screen_buffer + offset;
        iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
 
        for (y = clip->y1; y < clip->y2; y++) {
@@ -1274,19 +1293,23 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
 }
 
 static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
-                                        u8 depth)
+                                        const struct drm_format_info *format)
 {
-       switch (depth) {
-       case 8:
+       u8 depth = format->depth;
+
+       if (format->is_color_indexed) {
                var->red.offset = 0;
                var->green.offset = 0;
                var->blue.offset = 0;
-               var->red.length = 8; /* 8bit DAC */
-               var->green.length = 8;
-               var->blue.length = 8;
+               var->red.length = depth;
+               var->green.length = depth;
+               var->blue.length = depth;
                var->transp.offset = 0;
                var->transp.length = 0;
-               break;
+               return;
+       }
+
+       switch (depth) {
        case 15:
                var->red.offset = 10;
                var->green.offset = 5;
@@ -1341,7 +1364,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 {
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_framebuffer *fb = fb_helper->fb;
+       const struct drm_format_info *format = fb->format;
        struct drm_device *dev = fb_helper->dev;
+       unsigned int bpp;
 
        if (in_dbg_master())
                return -EINVAL;
@@ -1351,22 +1376,33 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                var->pixclock = 0;
        }
 
-       if ((drm_format_info_block_width(fb->format, 0) > 1) ||
-           (drm_format_info_block_height(fb->format, 0) > 1))
-               return -EINVAL;
+       switch (format->format) {
+       case DRM_FORMAT_C1:
+       case DRM_FORMAT_C2:
+       case DRM_FORMAT_C4:
+               /* supported format with sub-byte pixels */
+               break;
+
+       default:
+               if ((drm_format_info_block_width(format, 0) > 1) ||
+                   (drm_format_info_block_height(format, 0) > 1))
+                       return -EINVAL;
+               break;
+       }
 
        /*
         * Changes struct fb_var_screeninfo are currently not pushed back
         * to KMS, hence fail if different settings are requested.
         */
-       if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
+       bpp = drm_format_info_bpp(format, 0);
+       if (var->bits_per_pixel > bpp ||
            var->xres > fb->width || var->yres > fb->height ||
            var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
                drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
                          "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
                          var->xres, var->yres, var->bits_per_pixel,
                          var->xres_virtual, var->yres_virtual,
-                         fb->width, fb->height, fb->format->cpp[0] * 8);
+                         fb->width, fb->height, bpp);
                return -EINVAL;
        }
 
@@ -1381,13 +1417,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
            !var->blue.length    && !var->transp.length   &&
            !var->red.msb_right  && !var->green.msb_right &&
            !var->blue.msb_right && !var->transp.msb_right) {
-               drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
+               drm_fb_helper_fill_pixel_fmt(var, format);
        }
 
        /*
         * Likewise, bits_per_pixel should be rounded up to a supported value.
         */
-       var->bits_per_pixel = fb->format->cpp[0] * 8;
+       var->bits_per_pixel = bpp;
 
        /*
         * drm fbdev emulation doesn't support changing the pixel format at all,
@@ -1723,11 +1759,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 }
 
 static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
-                                  uint32_t depth)
+                                  bool is_color_indexed)
 {
        info->fix.type = FB_TYPE_PACKED_PIXELS;
-       info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
-               FB_VISUAL_TRUECOLOR;
+       info->fix.visual = is_color_indexed ? FB_VISUAL_PSEUDOCOLOR
+                                           : FB_VISUAL_TRUECOLOR;
        info->fix.mmio_start = 0;
        info->fix.mmio_len = 0;
        info->fix.type_aux = 0;
@@ -1744,19 +1780,31 @@ static void drm_fb_helper_fill_var(struct fb_info *info,
                                   uint32_t fb_width, uint32_t fb_height)
 {
        struct drm_framebuffer *fb = fb_helper->fb;
+       const struct drm_format_info *format = fb->format;
+
+       switch (format->format) {
+       case DRM_FORMAT_C1:
+       case DRM_FORMAT_C2:
+       case DRM_FORMAT_C4:
+               /* supported format with sub-byte pixels */
+               break;
+
+       default:
+               WARN_ON((drm_format_info_block_width(format, 0) > 1) ||
+                       (drm_format_info_block_height(format, 0) > 1));
+               break;
+       }
 
-       WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) ||
-               (drm_format_info_block_height(fb->format, 0) > 1));
        info->pseudo_palette = fb_helper->pseudo_palette;
        info->var.xres_virtual = fb->width;
        info->var.yres_virtual = fb->height;
-       info->var.bits_per_pixel = fb->format->cpp[0] * 8;
+       info->var.bits_per_pixel = drm_format_info_bpp(format, 0);
        info->var.accel_flags = FB_ACCELF_TEXT;
        info->var.xoffset = 0;
        info->var.yoffset = 0;
        info->var.activate = FB_ACTIVATE_NOW;
 
-       drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
+       drm_fb_helper_fill_pixel_fmt(&info->var, format);
 
        info->var.xres = fb_width;
        info->var.yres = fb_height;
@@ -1781,7 +1829,8 @@ void drm_fb_helper_fill_info(struct fb_info *info,
 {
        struct drm_framebuffer *fb = fb_helper->fb;
 
-       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
+       drm_fb_helper_fill_fix(info, fb->pitches[0],
+                              fb->format->is_color_indexed);
        drm_fb_helper_fill_var(info, fb_helper,
                               sizes->fb_width, sizes->fb_height);
 
index dc7d2e5b16c82219b702442a9675c8528a377a6a..a8b4d918e9a3f4993ecdd438d2cb73d3d79f63db 100644 (file)
 #include "drm_internal.h"
 #include "drm_legacy.h"
 
-#if defined(CONFIG_MMU) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
-#include <uapi/asm/mman.h>
-#include <drm/drm_vma_manager.h>
-#endif
-
 /* from BKL pushdown */
 DEFINE_MUTEX(drm_global_mutex);
 
@@ -131,7 +126,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
  *     };
  *
  * For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for
- * CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this
+ * DMA based drivers there is the DEFINE_DRM_GEM_DMA_FOPS() macro to make this
  * simpler.
  *
  * The driver's &file_operations must be stored in &drm_driver.fops.
@@ -912,139 +907,3 @@ struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags)
        return file;
 }
 EXPORT_SYMBOL_FOR_TESTS_ONLY(mock_drm_getfile);
-
-#ifdef CONFIG_MMU
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-/*
- * drm_addr_inflate() attempts to construct an aligned area by inflating
- * the area size and skipping the unaligned start of the area.
- * adapted from shmem_get_unmapped_area()
- */
-static unsigned long drm_addr_inflate(unsigned long addr,
-                                     unsigned long len,
-                                     unsigned long pgoff,
-                                     unsigned long flags,
-                                     unsigned long huge_size)
-{
-       unsigned long offset, inflated_len;
-       unsigned long inflated_addr;
-       unsigned long inflated_offset;
-
-       offset = (pgoff << PAGE_SHIFT) & (huge_size - 1);
-       if (offset && offset + len < 2 * huge_size)
-               return addr;
-       if ((addr & (huge_size - 1)) == offset)
-               return addr;
-
-       inflated_len = len + huge_size - PAGE_SIZE;
-       if (inflated_len > TASK_SIZE)
-               return addr;
-       if (inflated_len < len)
-               return addr;
-
-       inflated_addr = current->mm->get_unmapped_area(NULL, 0, inflated_len,
-                                                      0, flags);
-       if (IS_ERR_VALUE(inflated_addr))
-               return addr;
-       if (inflated_addr & ~PAGE_MASK)
-               return addr;
-
-       inflated_offset = inflated_addr & (huge_size - 1);
-       inflated_addr += offset - inflated_offset;
-       if (inflated_offset > offset)
-               inflated_addr += huge_size;
-
-       if (inflated_addr > TASK_SIZE - len)
-               return addr;
-
-       return inflated_addr;
-}
-
-/**
- * drm_get_unmapped_area() - Get an unused user-space virtual memory area
- * suitable for huge page table entries.
- * @file: The struct file representing the address space being mmap()'d.
- * @uaddr: Start address suggested by user-space.
- * @len: Length of the area.
- * @pgoff: The page offset into the address space.
- * @flags: mmap flags
- * @mgr: The address space manager used by the drm driver. This argument can
- * probably be removed at some point when all drivers use the same
- * address space manager.
- *
- * This function attempts to find an unused user-space virtual memory area
- * that can accommodate the size we want to map, and that is properly
- * aligned to facilitate huge page table entries matching actual
- * huge pages or huge page aligned memory in buffer objects. Buffer objects
- * are assumed to start at huge page boundary pfns (io memory) or be
- * populated by huge pages aligned to the start of the buffer object
- * (system- or coherent memory). Adapted from shmem_get_unmapped_area.
- *
- * Return: aligned user-space address.
- */
-unsigned long drm_get_unmapped_area(struct file *file,
-                                   unsigned long uaddr, unsigned long len,
-                                   unsigned long pgoff, unsigned long flags,
-                                   struct drm_vma_offset_manager *mgr)
-{
-       unsigned long addr;
-       unsigned long inflated_addr;
-       struct drm_vma_offset_node *node;
-
-       if (len > TASK_SIZE)
-               return -ENOMEM;
-
-       /*
-        * @pgoff is the file page-offset the huge page boundaries of
-        * which typically aligns to physical address huge page boundaries.
-        * That's not true for DRM, however, where physical address huge
-        * page boundaries instead are aligned with the offset from
-        * buffer object start. So adjust @pgoff to be the offset from
-        * buffer object start.
-        */
-       drm_vma_offset_lock_lookup(mgr);
-       node = drm_vma_offset_lookup_locked(mgr, pgoff, 1);
-       if (node)
-               pgoff -= node->vm_node.start;
-       drm_vma_offset_unlock_lookup(mgr);
-
-       addr = current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags);
-       if (IS_ERR_VALUE(addr))
-               return addr;
-       if (addr & ~PAGE_MASK)
-               return addr;
-       if (addr > TASK_SIZE - len)
-               return addr;
-
-       if (len < HPAGE_PMD_SIZE)
-               return addr;
-       if (flags & MAP_FIXED)
-               return addr;
-       /*
-        * Our priority is to support MAP_SHARED mapped hugely;
-        * and support MAP_PRIVATE mapped hugely too, until it is COWed.
-        * But if caller specified an address hint, respect that as before.
-        */
-       if (uaddr)
-               return addr;
-
-       inflated_addr = drm_addr_inflate(addr, len, pgoff, flags,
-                                        HPAGE_PMD_SIZE);
-
-       if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) &&
-           len >= HPAGE_PUD_SIZE)
-               inflated_addr = drm_addr_inflate(inflated_addr, len, pgoff,
-                                                flags, HPAGE_PUD_SIZE);
-       return inflated_addr;
-}
-#else /* CONFIG_TRANSPARENT_HUGEPAGE */
-unsigned long drm_get_unmapped_area(struct file *file,
-                                   unsigned long uaddr, unsigned long len,
-                                   unsigned long pgoff, unsigned long flags,
-                                   struct drm_vma_offset_manager *mgr)
-{
-       return current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags);
-}
-#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
-EXPORT_SYMBOL_GPL(drm_get_unmapped_area);
-#endif /* CONFIG_MMU */
index a3ccd8bc966fd8164abeb8f4ee8443c55568699e..56642816fdff0d998cf6ff814a099dad0a064e3a 100644 (file)
@@ -8,9 +8,10 @@
  * (at your option) any later version.
  */
 
+#include <linux/io.h>
+#include <linux/iosys-map.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/io.h>
 
 #include <drm/drm_device.h>
 #include <drm/drm_format_helper.h>
@@ -40,11 +41,11 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info
 }
 EXPORT_SYMBOL(drm_fb_clip_offset);
 
-/* TODO: Make this functon work with multi-plane formats. */
-static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
-                      const void *vaddr, const struct drm_framebuffer *fb,
-                      const struct drm_rect *clip, bool vaddr_cached_hint,
-                      void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
+/* TODO: Make this function work with multi-plane formats. */
+static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
+                        const void *vaddr, const struct drm_framebuffer *fb,
+                        const struct drm_rect *clip, bool vaddr_cached_hint,
+                        void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
 {
        unsigned long linepixels = drm_rect_width(clip);
        unsigned long lines = drm_rect_height(clip);
@@ -54,7 +55,7 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix
        const void *sbuf;
 
        /*
-        * Some source buffers, such as CMA memory, use write-combine
+        * Some source buffers, such as DMA memory, use write-combine
         * caching, so reads are uncached. Speed up access by fetching
         * one line at a time.
         */
@@ -83,11 +84,11 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix
        return 0;
 }
 
-/* TODO: Make this functon work with multi-plane formats. */
-static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
-                           const void *vaddr, const struct drm_framebuffer *fb,
-                           const struct drm_rect *clip, bool vaddr_cached_hint,
-                           void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
+/* TODO: Make this function work with multi-plane formats. */
+static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
+                             const void *vaddr, const struct drm_framebuffer *fb,
+                             const struct drm_rect *clip, bool vaddr_cached_hint,
+                             void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
 {
        unsigned long linepixels = drm_rect_width(clip);
        unsigned long lines = drm_rect_height(clip);
@@ -128,65 +129,82 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned
        return 0;
 }
 
-/**
- * drm_fb_memcpy - Copy clip buffer
- * @dst: Destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: Source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
- *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
- */
-void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr,
-                  const struct drm_framebuffer *fb, const struct drm_rect *clip)
+/* TODO: Make this function work with multi-plane formats. */
+static int drm_fb_xfrm(struct iosys_map *dst,
+                      const unsigned int *dst_pitch, const u8 *dst_pixsize,
+                      const struct iosys_map *src, const struct drm_framebuffer *fb,
+                      const struct drm_rect *clip, bool vaddr_cached_hint,
+                      void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
 {
-       unsigned int cpp = fb->format->cpp[0];
-       size_t len = (clip->x2 - clip->x1) * cpp;
-       unsigned int y, lines = clip->y2 - clip->y1;
+       static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+               0, 0, 0, 0
+       };
 
        if (!dst_pitch)
-               dst_pitch = len;
+               dst_pitch = default_dst_pitch;
 
-       vaddr += clip_offset(clip, fb->pitches[0], cpp);
-       for (y = 0; y < lines; y++) {
-               memcpy(dst, vaddr, len);
-               vaddr += fb->pitches[0];
-               dst += dst_pitch;
-       }
+       /* TODO: handle src in I/O memory here */
+       if (dst[0].is_iomem)
+               return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0],
+                                         src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line);
+       else
+               return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0],
+                                    src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line);
 }
-EXPORT_SYMBOL(drm_fb_memcpy);
 
 /**
- * drm_fb_memcpy_toio - Copy clip buffer
- * @dst: Destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: Source buffer
+ * drm_fb_memcpy - Copy clip buffer
+ * @dst: Array of destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
+ * This function copies parts of a framebuffer to display memory. Destination and
+ * framebuffer formats must match. No conversion takes place. The parameters @dst,
+ * @dst_pitch and @src refer to arrays. Each array must have at least as many entries
+ * as there are planes in @fb's format. Each entry stores the value for the format's
+ * respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
  */
-void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr,
-                       const struct drm_framebuffer *fb, const struct drm_rect *clip)
+void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
+                  const struct iosys_map *src, const struct drm_framebuffer *fb,
+                  const struct drm_rect *clip)
 {
-       unsigned int cpp = fb->format->cpp[0];
-       size_t len = (clip->x2 - clip->x1) * cpp;
-       unsigned int y, lines = clip->y2 - clip->y1;
+       static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+               0, 0, 0, 0
+       };
 
-       if (!dst_pitch)
-               dst_pitch = len;
+       const struct drm_format_info *format = fb->format;
+       unsigned int i, y, lines = drm_rect_height(clip);
 
-       vaddr += clip_offset(clip, fb->pitches[0], cpp);
-       for (y = 0; y < lines; y++) {
-               memcpy_toio(dst, vaddr, len);
-               vaddr += fb->pitches[0];
-               dst += dst_pitch;
+       if (!dst_pitch)
+               dst_pitch = default_dst_pitch;
+
+       for (i = 0; i < format->num_planes; ++i) {
+               unsigned int bpp_i = drm_format_info_bpp(format, i);
+               unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8);
+               size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8);
+               unsigned int dst_pitch_i = dst_pitch[i];
+               struct iosys_map dst_i = dst[i];
+               struct iosys_map src_i = src[i];
+
+               if (!dst_pitch_i)
+                       dst_pitch_i = len_i;
+
+               iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i));
+               for (y = 0; y < lines; y++) {
+                       /* TODO: handle src_i in I/O memory here */
+                       iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i);
+                       iosys_map_incr(&src_i, fb->pitches[i]);
+                       iosys_map_incr(&dst_i, dst_pitch_i);
+               }
        }
 }
-EXPORT_SYMBOL(drm_fb_memcpy_toio);
+EXPORT_SYMBOL(drm_fb_memcpy);
 
 static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
@@ -210,37 +228,47 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels
 
 /**
  * drm_fb_swab - Swap bytes into clip buffer
- * @dst: Destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: Source buffer
+ * @dst: Array of destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  * @cached: Source buffer is mapped cached (eg. not write-combined)
  *
- * If @cached is false a temporary buffer is used to cache one pixel line at a
- * time to speed up slow uncached reads.
+ * This function copies parts of a framebuffer to display memory and swaps per-pixel
+ * bytes during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index. If @cached is
+ * false a temporary buffer is used to cache one pixel line at a time to speed up
+ * slow uncached reads.
  *
- * This function does not apply clipping on dst, i.e. the destination
- * is at the top-left corner.
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
  */
-void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src,
-                const struct drm_framebuffer *fb, const struct drm_rect *clip,
-                bool cached)
+void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
+                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                const struct drm_rect *clip, bool cached)
 {
-       u8 cpp = fb->format->cpp[0];
+       const struct drm_format_info *format = fb->format;
+       u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8);
+       void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels);
 
        switch (cpp) {
        case 4:
-               drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab32_line);
+               swab_line = drm_fb_swab32_line;
                break;
        case 2:
-               drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab16_line);
+               swab_line = drm_fb_swab16_line;
                break;
        default:
                drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n",
-                             &fb->format->format);
-               break;
+                             &format->format);
+               return;
        }
+
+       drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, swab_line);
 }
 EXPORT_SYMBOL(drm_fb_swab);
 
@@ -261,32 +289,50 @@ static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigne
 
 /**
  * drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer
- * @dst: RGB332 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: XRGB8888 source buffer
+ * @dst: Array of RGB332 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for RGB332 devices that don't natively support XRGB8888.
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for RGB332 devices that don't support XRGB8888 natively.
  */
-void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *src,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip)
+void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip)
 {
-       drm_fb_xfrm(dst, dst_pitch, 1, src, fb, clip, false, drm_fb_xrgb8888_to_rgb332_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               1,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_rgb332_line);
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
 
 static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        u16 *dbuf16 = dbuf;
-       const u32 *sbuf32 = sbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
        u16 val16;
+       u32 pix;
 
        for (x = 0; x < pixels; x++) {
-               val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
-                       ((sbuf32[x] & 0x0000FC00) >> 5) |
-                       ((sbuf32[x] & 0x000000F8) >> 3);
+               pix = le32_to_cpu(sbuf32[x]);
+               val16 = ((pix & 0x00F80000) >> 8) |
+                       ((pix & 0x0000FC00) >> 5) |
+                       ((pix & 0x000000F8) >> 3);
                dbuf16[x] = val16;
        }
 }
@@ -295,146 +341,143 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
                                                unsigned int pixels)
 {
        u16 *dbuf16 = dbuf;
-       const u32 *sbuf32 = sbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
        u16 val16;
+       u32 pix;
 
        for (x = 0; x < pixels; x++) {
-               val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
-                       ((sbuf32[x] & 0x0000FC00) >> 5) |
-                       ((sbuf32[x] & 0x000000F8) >> 3);
+               pix = le32_to_cpu(sbuf32[x]);
+               val16 = ((pix & 0x00F80000) >> 8) |
+                       ((pix & 0x0000FC00) >> 5) |
+                       ((pix & 0x000000F8) >> 3);
                dbuf16[x] = swab16(val16);
        }
 }
 
 /**
  * drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
- * @dst: RGB565 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
+ * @dst: Array of RGB565 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffer
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  * @swab: Swap bytes
  *
- * Drivers can use this function for RGB565 devices that don't natively
- * support XRGB8888.
- */
-void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip,
-                              bool swab)
-{
-       if (swab)
-               drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
-                           drm_fb_xrgb8888_to_rgb565_swab_line);
-       else
-               drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
-                           drm_fb_xrgb8888_to_rgb565_line);
-}
-EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
-
-/**
- * drm_fb_xrgb8888_to_rgb565_toio - Convert XRGB8888 to RGB565 clip buffer
- * @dst: RGB565 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
- * @swab: Swap bytes
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
  *
- * Drivers can use this function for RGB565 devices that don't natively
- * support XRGB8888.
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for RGB565 devices that don't support XRGB8888 natively.
  */
-void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch,
-                                   const void *vaddr, const struct drm_framebuffer *fb,
-                                   const struct drm_rect *clip, bool swab)
+void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip, bool swab)
 {
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               2,
+       };
+
+       void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
+
        if (swab)
-               drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
-                                drm_fb_xrgb8888_to_rgb565_swab_line);
+               xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line;
        else
-               drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
-                                drm_fb_xrgb8888_to_rgb565_line);
+               xfrm_line = drm_fb_xrgb8888_to_rgb565_line;
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, xfrm_line);
 }
-EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio);
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
 
 static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        u8 *dbuf8 = dbuf;
-       const u32 *sbuf32 = sbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
+       u32 pix;
 
        for (x = 0; x < pixels; x++) {
-               *dbuf8++ = (sbuf32[x] & 0x000000FF) >>  0;
-               *dbuf8++ = (sbuf32[x] & 0x0000FF00) >>  8;
-               *dbuf8++ = (sbuf32[x] & 0x00FF0000) >> 16;
+               pix = le32_to_cpu(sbuf32[x]);
+               *dbuf8++ = (pix & 0x000000FF) >>  0;
+               *dbuf8++ = (pix & 0x0000FF00) >>  8;
+               *dbuf8++ = (pix & 0x00FF0000) >> 16;
        }
 }
 
 /**
  * drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer
- * @dst: RGB888 destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @src: XRGB8888 source buffer
+ * @dst: Array of RGB888 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for RGB888 devices that don't natively
- * support XRGB8888.
- */
-void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip)
-{
-       drm_fb_xfrm(dst, dst_pitch, 3, src, fb, clip, false, drm_fb_xrgb8888_to_rgb888_line);
-}
-EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
-
-/**
- * drm_fb_xrgb8888_to_rgb888_toio - Convert XRGB8888 to RGB888 clip buffer
- * @dst: RGB565 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
- * @fb: DRM framebuffer
- * @clip: Clip rectangle area to copy
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
  *
  * Drivers can use this function for RGB888 devices that don't natively
  * support XRGB8888.
  */
-void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
-                                   const void *vaddr, const struct drm_framebuffer *fb,
-                                   const struct drm_rect *clip)
+void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip)
 {
-       drm_fb_xfrm_toio(dst, dst_pitch, 3, vaddr, fb, clip, false,
-                        drm_fb_xrgb8888_to_rgb888_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               3,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_rgb888_line);
 }
-EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);
+EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
 
 static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
-       u32 *dbuf32 = dbuf;
-       const u16 *sbuf16 = sbuf;
+       __le32 *dbuf32 = dbuf;
+       const __le16 *sbuf16 = sbuf;
        unsigned int x;
 
-       for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) {
-               u32 val32 = ((*sbuf16 & 0xf800) << 8) |
-                           ((*sbuf16 & 0x07e0) << 5) |
-                           ((*sbuf16 & 0x001f) << 3);
-               *dbuf32 = 0xff000000 | val32 |
-                         ((val32 >> 3) & 0x00070007) |
-                         ((val32 >> 2) & 0x00000300);
+       for (x = 0; x < pixels; x++) {
+               u16 val16 = le16_to_cpu(sbuf16[x]);
+               u32 val32 = ((val16 & 0xf800) << 8) |
+                           ((val16 & 0x07e0) << 5) |
+                           ((val16 & 0x001f) << 3);
+               val32 = 0xff000000 | val32 |
+                       ((val32 >> 3) & 0x00070007) |
+                       ((val32 >> 2) & 0x00000300);
+               dbuf32[x] = cpu_to_le32(val32);
        }
 }
 
-static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
-                                          const void *vaddr, const struct drm_framebuffer *fb,
-                                          const struct drm_rect *clip)
+static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                     const struct iosys_map *src,
+                                     const struct drm_framebuffer *fb,
+                                     const struct drm_rect *clip)
 {
-       drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-                        drm_fb_rgb565_to_xrgb8888_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               4,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_rgb565_to_xrgb8888_line);
 }
 
 static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
-       u32 *dbuf32 = dbuf;
+       __le32 *dbuf32 = dbuf;
        const u8 *sbuf8 = sbuf;
        unsigned int x;
 
@@ -442,117 +485,158 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne
                u8 r = *sbuf8++;
                u8 g = *sbuf8++;
                u8 b = *sbuf8++;
-               *dbuf32++ = 0xff000000 | (r << 16) | (g << 8) | b;
+               u32 pix = 0xff000000 | (r << 16) | (g << 8) | b;
+               dbuf32[x] = cpu_to_le32(pix);
        }
 }
 
-static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
-                                          const void *vaddr, const struct drm_framebuffer *fb,
-                                          const struct drm_rect *clip)
+static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                     const struct iosys_map *src,
+                                     const struct drm_framebuffer *fb,
+                                     const struct drm_rect *clip)
 {
-       drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-                        drm_fb_rgb888_to_xrgb8888_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               4,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_rgb888_to_xrgb8888_line);
 }
 
 static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
-       u32 *dbuf32 = dbuf;
-       const u32 *sbuf32 = sbuf;
+       __le32 *dbuf32 = dbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
        u32 val32;
+       u32 pix;
 
        for (x = 0; x < pixels; x++) {
-               val32 = ((sbuf32[x] & 0x000000FF) << 2) |
-                       ((sbuf32[x] & 0x0000FF00) << 4) |
-                       ((sbuf32[x] & 0x00FF0000) << 6);
-               *dbuf32++ = val32 | ((val32 >> 8) & 0x00300C03);
+               pix = le32_to_cpu(sbuf32[x]);
+               val32 = ((pix & 0x000000FF) << 2) |
+                       ((pix & 0x0000FF00) << 4) |
+                       ((pix & 0x00FF0000) << 6);
+               pix = val32 | ((val32 >> 8) & 0x00300C03);
+               *dbuf32++ = cpu_to_le32(pix);
        }
 }
 
 /**
- * drm_fb_xrgb8888_to_xrgb2101010_toio - Convert XRGB8888 to XRGB2101010 clip
- * buffer
- * @dst: XRGB2101010 destination buffer (iomem)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
+ * drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer
+ * @dst: Array of XRGB2101010 destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drivers can use this function for XRGB2101010 devices that don't natively
- * support XRGB8888.
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
+ *
+ * Drivers can use this function for XRGB2101010 devices that don't support XRGB8888
+ * natively.
  */
-void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst,
-                                        unsigned int dst_pitch, const void *vaddr,
-                                        const struct drm_framebuffer *fb,
-                                        const struct drm_rect *clip)
+void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                   const struct iosys_map *src, const struct drm_framebuffer *fb,
+                                   const struct drm_rect *clip)
 {
-       drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
-                        drm_fb_xrgb8888_to_xrgb2101010_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               4,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_xrgb2101010_line);
 }
-EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
 
 static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
        u8 *dbuf8 = dbuf;
-       const u32 *sbuf32 = sbuf;
+       const __le32 *sbuf32 = sbuf;
        unsigned int x;
 
        for (x = 0; x < pixels; x++) {
-               u8 r = (*sbuf32 & 0x00ff0000) >> 16;
-               u8 g = (*sbuf32 & 0x0000ff00) >> 8;
-               u8 b =  *sbuf32 & 0x000000ff;
+               u32 pix = le32_to_cpu(sbuf32[x]);
+               u8 r = (pix & 0x00ff0000) >> 16;
+               u8 g = (pix & 0x0000ff00) >> 8;
+               u8 b =  pix & 0x000000ff;
 
                /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
                *dbuf8++ = (3 * r + 6 * g + b) / 10;
-               sbuf32++;
        }
 }
 
 /**
  * drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
- * @dst: 8-bit grayscale destination buffer
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
+ * @dst: Array of 8-bit grayscale destination buffers
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * Drm doesn't have native monochrome or grayscale support.
- * Such drivers can announce the commonly supported XR24 format to userspace
- * and use this function to convert to the native format.
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
  *
- * Monochrome drivers will use the most significant bit,
- * where 1 means foreground color and 0 background color.
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
  *
- * ITU BT.601 is used for the RGB -> luma (brightness) conversion.
+ * DRM doesn't have native monochrome or grayscale support. Drivers can use this
+ * function for grayscale devices that don't support XRGB8888 natively.Such
+ * drivers can announce the commonly supported XR24 format to userspace and use
+ * this function to convert to the native format. Monochrome drivers will use the
+ * most significant bit, where 1 means foreground color and 0 background color.
+ * ITU BT.601 is being used for the RGB -> luma (brightness) conversion.
  */
-void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr,
-                             const struct drm_framebuffer *fb, const struct drm_rect *clip)
+void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
+                             const struct iosys_map *src, const struct drm_framebuffer *fb,
+                             const struct drm_rect *clip)
 {
-       drm_fb_xfrm(dst, dst_pitch, 1, vaddr, fb, clip, false, drm_fb_xrgb8888_to_gray8_line);
+       static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
+               1,
+       };
+
+       drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
+                   drm_fb_xrgb8888_to_gray8_line);
 }
 EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
 
 /**
- * drm_fb_blit_toio - Copy parts of a framebuffer to display memory
- * @dst:       The display memory to copy to
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
+ * drm_fb_blit - Copy parts of a framebuffer to display memory
+ * @dst:       Array of display-memory addresses to copy to
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
  * @dst_format:        FOURCC code of the display's color format
- * @vmap:      The framebuffer memory to copy from
+ * @src:       The framebuffer memory to copy from
  * @fb:                The framebuffer to copy from
  * @clip:      Clip rectangle area to copy
  *
  * This function copies parts of a framebuffer to display memory. If the
  * formats of the display and the framebuffer mismatch, the blit function
- * will attempt to convert between them.
+ * will attempt to convert between them during the process. The parameters @dst,
+ * @dst_pitch and @src refer to arrays. Each array must have at least as many
+ * entries as there are planes in @dst_format's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner).
  *
  * Returns:
  * 0 on success, or
  * -EINVAL if the color-format conversion failed, or
  * a negative error code otherwise.
  */
-int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format,
-                    const void *vmap, const struct drm_framebuffer *fb,
-                    const struct drm_rect *clip)
+int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
+               const struct iosys_map *src, const struct drm_framebuffer *fb,
+               const struct drm_rect *clip)
 {
        uint32_t fb_format = fb->format->format;
 
@@ -567,30 +651,30 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
                dst_format = DRM_FORMAT_XRGB2101010;
 
        if (dst_format == fb_format) {
-               drm_fb_memcpy_toio(dst, dst_pitch, vmap, fb, clip);
+               drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
                return 0;
 
        } else if (dst_format == DRM_FORMAT_RGB565) {
                if (fb_format == DRM_FORMAT_XRGB8888) {
-                       drm_fb_xrgb8888_to_rgb565_toio(dst, dst_pitch, vmap, fb, clip, false);
+                       drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
                        return 0;
                }
        } else if (dst_format == DRM_FORMAT_RGB888) {
                if (fb_format == DRM_FORMAT_XRGB8888) {
-                       drm_fb_xrgb8888_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip);
+                       drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
                        return 0;
                }
        } else if (dst_format == DRM_FORMAT_XRGB8888) {
                if (fb_format == DRM_FORMAT_RGB888) {
-                       drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
+                       drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip);
                        return 0;
                } else if (fb_format == DRM_FORMAT_RGB565) {
-                       drm_fb_rgb565_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
+                       drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip);
                        return 0;
                }
        } else if (dst_format == DRM_FORMAT_XRGB2101010) {
                if (fb_format == DRM_FORMAT_XRGB8888) {
-                       drm_fb_xrgb8888_to_xrgb2101010_toio(dst, dst_pitch, vmap, fb, clip);
+                       drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
                        return 0;
                }
        }
@@ -600,8 +684,7 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
 
        return -EINVAL;
 }
-EXPORT_SYMBOL(drm_fb_blit_toio);
-
+EXPORT_SYMBOL(drm_fb_blit);
 
 static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels)
 {
@@ -622,49 +705,67 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int
 
 /**
  * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome
- * @dst: monochrome destination buffer (0=black, 1=white)
- * @dst_pitch: Number of bytes between two consecutive scanlines within dst
- * @vaddr: XRGB8888 source buffer
+ * @dst: Array of monochrome destination buffers (0=black, 1=white)
+ * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
+ *             within @dst; can be NULL if scanlines are stored next to each other.
+ * @src: Array of XRGB8888 source buffers
  * @fb: DRM framebuffer
  * @clip: Clip rectangle area to copy
  *
- * DRM doesn't have native monochrome support.
- * Such drivers can announce the commonly supported XR24 format to userspace
- * and use this function to convert to the native format.
+ * This function copies parts of a framebuffer to display memory and converts the
+ * color format during the process. Destination and framebuffer formats must match. The
+ * parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
+ * least as many entries as there are planes in @fb's format. Each entry stores the
+ * value for the format's respective color plane at the same index.
+ *
+ * This function does not apply clipping on @dst (i.e. the destination is at the
+ * top-left corner). The first pixel (upper left corner of the clip rectangle) will
+ * be converted and copied to the first bit (LSB) in the first byte of the monochrome
+ * destination buffer. If the caller requires that the first pixel in a byte must
+ * be located at an x-coordinate that is a multiple of 8, then the caller must take
+ * care itself of supplying a suitable clip rectangle.
+ *
+ * DRM doesn't have native monochrome support. Drivers can use this function for
+ * monochrome devices that don't support XRGB8888 natively. Such drivers can
+ * announce the commonly supported XR24 format to userspace and use this function
+ * to convert to the native format.
  *
  * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
  * then the result is converted from grayscale to monochrome.
- *
- * The first pixel (upper left corner of the clip rectangle) will be converted
- * and copied to the first bit (LSB) in the first byte of the monochrome
- * destination buffer.
- * If the caller requires that the first pixel in a byte must be located at an
- * x-coordinate that is a multiple of 8, then the caller must take care itself
- * of supplying a suitable clip rectangle.
  */
-void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr,
-                            const struct drm_framebuffer *fb, const struct drm_rect *clip)
+void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
+                            const struct iosys_map *src, const struct drm_framebuffer *fb,
+                            const struct drm_rect *clip)
 {
+       static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
+               0, 0, 0, 0
+       };
        unsigned int linepixels = drm_rect_width(clip);
        unsigned int lines = drm_rect_height(clip);
        unsigned int cpp = fb->format->cpp[0];
        unsigned int len_src32 = linepixels * cpp;
        struct drm_device *dev = fb->dev;
+       void *vaddr = src[0].vaddr;
+       unsigned int dst_pitch_0;
        unsigned int y;
-       u8 *mono = dst, *gray8;
+       u8 *mono = dst[0].vaddr, *gray8;
        u32 *src32;
 
        if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888))
                return;
 
+       if (!dst_pitch)
+               dst_pitch = default_dst_pitch;
+       dst_pitch_0 = dst_pitch[0];
+
        /*
         * The mono destination buffer contains 1 bit per pixel
         */
-       if (!dst_pitch)
-               dst_pitch = DIV_ROUND_UP(linepixels, 8);
+       if (!dst_pitch_0)
+               dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
 
        /*
-        * The cma memory is write-combined so reads are uncached.
+        * The dma memory is write-combined so reads are uncached.
         * Speed up by fetching one line at a time.
         *
         * Also, format conversion from XR24 to monochrome are done
@@ -686,7 +787,7 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd
                drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
                drm_fb_gray8_to_mono_line(mono, gray8, linepixels);
                vaddr += fb->pitches[0];
-               mono += dst_pitch;
+               mono += dst_pitch_0;
        }
 
        kfree(src32);
index 07741b678798b0f1293d7c324896dd209cc9fce0..e09331bb3bc73f21385b47a1c723f69e3abaad91 100644 (file)
@@ -43,6 +43,21 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
        uint32_t fmt = DRM_FORMAT_INVALID;
 
        switch (bpp) {
+       case 1:
+               if (depth == 1)
+                       fmt = DRM_FORMAT_C1;
+               break;
+
+       case 2:
+               if (depth == 2)
+                       fmt = DRM_FORMAT_C2;
+               break;
+
+       case 4:
+               if (depth == 4)
+                       fmt = DRM_FORMAT_C4;
+               break;
+
        case 8:
                if (depth == 8)
                        fmt = DRM_FORMAT_C8;
@@ -132,7 +147,26 @@ EXPORT_SYMBOL(drm_driver_legacy_fb_format);
 const struct drm_format_info *__drm_format_info(u32 format)
 {
        static const struct drm_format_info formats[] = {
-               { .format = DRM_FORMAT_C8,              .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_C1,              .depth = 1,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
+               { .format = DRM_FORMAT_C2,              .depth = 2,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
+               { .format = DRM_FORMAT_C4,              .depth = 4,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
+               { .format = DRM_FORMAT_C8,              .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
+               { .format = DRM_FORMAT_D1,              .depth = 1,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_D2,              .depth = 2,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_D4,              .depth = 4,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_D8,              .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_R1,              .depth = 1,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_R2,              .depth = 2,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
+               { .format = DRM_FORMAT_R4,              .depth = 4,  .num_planes = 1,
+                 .char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
                { .format = DRM_FORMAT_R8,              .depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
                { .format = DRM_FORMAT_R10,             .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
                { .format = DRM_FORMAT_R12,             .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
@@ -370,6 +404,25 @@ unsigned int drm_format_info_block_height(const struct drm_format_info *info,
 }
 EXPORT_SYMBOL(drm_format_info_block_height);
 
+/**
+ * drm_format_info_bpp - number of bits per pixel
+ * @info: pixel format info
+ * @plane: plane index
+ *
+ * Returns:
+ * The actual number of bits per pixel, depending on the plane index.
+ */
+unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane)
+{
+       if (!info || plane < 0 || plane >= info->num_planes)
+               return 0;
+
+       return info->char_per_block[plane] * 8 /
+              (drm_format_info_block_width(info, plane) *
+               drm_format_info_block_height(info, plane));
+}
+EXPORT_SYMBOL(drm_format_info_bpp);
+
 /**
  * drm_format_info_min_pitch - computes the minimum required pitch in bytes
  * @info: pixel format info
index 4562a8b865792456afa0ff18b7454c2a9fce8f95..185b04762e2c82d55ecdd3fb252c6f0371025d24 100644 (file)
@@ -530,7 +530,7 @@ int drm_mode_getfb(struct drm_device *dev,
        r->height = fb->height;
        r->width = fb->width;
        r->depth = fb->format->depth;
-       r->bpp = fb->format->cpp[0] * 8;
+       r->bpp = drm_format_info_bpp(fb->format, 0);
        r->pitch = fb->pitches[0];
 
        /* GET_FB() is an unprivileged ioctl so we must not return a
@@ -935,7 +935,7 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
  * the id and get back -EINVAL. Obviously no concern at driver unload time.
  *
  * Also, the framebuffer will not be removed from the lookup idr - for
- * user-created framebuffers this will happen in in the rmfb ioctl. For
+ * user-created framebuffers this will happen in the rmfb ioctl. For
  * driver-private objects (e.g. for fbdev) drivers need to explicitly call
  * drm_framebuffer_unregister_private.
  */
diff --git a/drivers/gpu/drm/drm_gem_cma_helper.c b/drivers/gpu/drm/drm_gem_cma_helper.c
deleted file mode 100644 (file)
index 42abee9..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * drm gem CMA (contiguous memory allocator) helper functions
- *
- * Copyright (C) 2012 Sascha Hauer, Pengutronix
- *
- * Based on Samsung Exynos code
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/dma-buf.h>
-#include <linux/dma-mapping.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <drm/drm.h>
-#include <drm/drm_device.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_vma_manager.h>
-
-/**
- * DOC: cma helpers
- *
- * The DRM GEM/CMA helpers are a means to provide buffer objects that are
- * presented to the device as a contiguous chunk of memory. This is useful
- * for devices that do not support scatter-gather DMA (either directly or
- * by using an intimately attached IOMMU).
- *
- * Despite the name, the DRM GEM/CMA helpers are not hardwired to use the
- * Contiguous Memory Allocator (CMA).
- *
- * For devices that access the memory bus through an (external) IOMMU then
- * the buffer objects are allocated using a traditional page-based
- * allocator and may be scattered through physical memory. However they
- * are contiguous in the IOVA space so appear contiguous to devices using
- * them.
- *
- * For other devices then the helpers rely on CMA to provide buffer
- * objects that are physically contiguous in memory.
- *
- * For GEM callback helpers in struct &drm_gem_object functions, see likewise
- * named functions with an _object_ infix (e.g., drm_gem_cma_object_vmap() wraps
- * drm_gem_cma_vmap()). These helpers perform the necessary type conversion.
- */
-
-static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
-       .free = drm_gem_cma_object_free,
-       .print_info = drm_gem_cma_object_print_info,
-       .get_sg_table = drm_gem_cma_object_get_sg_table,
-       .vmap = drm_gem_cma_object_vmap,
-       .mmap = drm_gem_cma_object_mmap,
-       .vm_ops = &drm_gem_cma_vm_ops,
-};
-
-/**
- * __drm_gem_cma_create - Create a GEM CMA object without allocating memory
- * @drm: DRM device
- * @size: size of the object to allocate
- * @private: true if used for internal purposes
- *
- * This function creates and initializes a GEM CMA object of the given size,
- * but doesn't allocate any memory to back the object.
- *
- * Returns:
- * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-static struct drm_gem_cma_object *
-__drm_gem_cma_create(struct drm_device *drm, size_t size, bool private)
-{
-       struct drm_gem_cma_object *cma_obj;
-       struct drm_gem_object *gem_obj;
-       int ret = 0;
-
-       if (drm->driver->gem_create_object) {
-               gem_obj = drm->driver->gem_create_object(drm, size);
-               if (IS_ERR(gem_obj))
-                       return ERR_CAST(gem_obj);
-               cma_obj = to_drm_gem_cma_obj(gem_obj);
-       } else {
-               cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
-               if (!cma_obj)
-                       return ERR_PTR(-ENOMEM);
-               gem_obj = &cma_obj->base;
-       }
-
-       if (!gem_obj->funcs)
-               gem_obj->funcs = &drm_gem_cma_default_funcs;
-
-       if (private) {
-               drm_gem_private_object_init(drm, gem_obj, size);
-
-               /* Always use writecombine for dma-buf mappings */
-               cma_obj->map_noncoherent = false;
-       } else {
-               ret = drm_gem_object_init(drm, gem_obj, size);
-       }
-       if (ret)
-               goto error;
-
-       ret = drm_gem_create_mmap_offset(gem_obj);
-       if (ret) {
-               drm_gem_object_release(gem_obj);
-               goto error;
-       }
-
-       return cma_obj;
-
-error:
-       kfree(cma_obj);
-       return ERR_PTR(ret);
-}
-
-/**
- * drm_gem_cma_create - allocate an object with the given size
- * @drm: DRM device
- * @size: size of the object to allocate
- *
- * This function creates a CMA GEM object and allocates memory as backing store.
- * The allocated memory will occupy a contiguous chunk of bus address space.
- *
- * For devices that are directly connected to the memory bus then the allocated
- * memory will be physically contiguous. For devices that access through an
- * IOMMU, then the allocated memory is not expected to be physically contiguous
- * because having contiguous IOVAs is sufficient to meet a devices DMA
- * requirements.
- *
- * Returns:
- * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
-                                             size_t size)
-{
-       struct drm_gem_cma_object *cma_obj;
-       int ret;
-
-       size = round_up(size, PAGE_SIZE);
-
-       cma_obj = __drm_gem_cma_create(drm, size, false);
-       if (IS_ERR(cma_obj))
-               return cma_obj;
-
-       if (cma_obj->map_noncoherent) {
-               cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
-                                                      &cma_obj->paddr,
-                                                      DMA_TO_DEVICE,
-                                                      GFP_KERNEL | __GFP_NOWARN);
-       } else {
-               cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
-                                             GFP_KERNEL | __GFP_NOWARN);
-       }
-       if (!cma_obj->vaddr) {
-               drm_dbg(drm, "failed to allocate buffer with size %zu\n",
-                        size);
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       return cma_obj;
-
-error:
-       drm_gem_object_put(&cma_obj->base);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_create);
-
-/**
- * drm_gem_cma_create_with_handle - allocate an object with the given size and
- *     return a GEM handle to it
- * @file_priv: DRM file-private structure to register the handle for
- * @drm: DRM device
- * @size: size of the object to allocate
- * @handle: return location for the GEM handle
- *
- * This function creates a CMA GEM object, allocating a chunk of memory as
- * backing store. The GEM object is then added to the list of object associated
- * with the given file and a handle to it is returned.
- *
- * The allocated memory will occupy a contiguous chunk of bus address space.
- * See drm_gem_cma_create() for more details.
- *
- * Returns:
- * A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
- * error code on failure.
- */
-static struct drm_gem_cma_object *
-drm_gem_cma_create_with_handle(struct drm_file *file_priv,
-                              struct drm_device *drm, size_t size,
-                              uint32_t *handle)
-{
-       struct drm_gem_cma_object *cma_obj;
-       struct drm_gem_object *gem_obj;
-       int ret;
-
-       cma_obj = drm_gem_cma_create(drm, size);
-       if (IS_ERR(cma_obj))
-               return cma_obj;
-
-       gem_obj = &cma_obj->base;
-
-       /*
-        * allocate a id of idr table where the obj is registered
-        * and handle has the id what user can see.
-        */
-       ret = drm_gem_handle_create(file_priv, gem_obj, handle);
-       /* drop reference from allocate - handle holds it now. */
-       drm_gem_object_put(gem_obj);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return cma_obj;
-}
-
-/**
- * drm_gem_cma_free - free resources associated with a CMA GEM object
- * @cma_obj: CMA GEM object to free
- *
- * This function frees the backing memory of the CMA GEM object, cleans up the
- * GEM object state and frees the memory used to store the object itself.
- * If the buffer is imported and the virtual address is set, it is released.
- */
-void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj)
-{
-       struct drm_gem_object *gem_obj = &cma_obj->base;
-       struct iosys_map map = IOSYS_MAP_INIT_VADDR(cma_obj->vaddr);
-
-       if (gem_obj->import_attach) {
-               if (cma_obj->vaddr)
-                       dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);
-               drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
-       } else if (cma_obj->vaddr) {
-               if (cma_obj->map_noncoherent)
-                       dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size,
-                                            cma_obj->vaddr, cma_obj->paddr,
-                                            DMA_TO_DEVICE);
-               else
-                       dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
-                                   cma_obj->vaddr, cma_obj->paddr);
-       }
-
-       drm_gem_object_release(gem_obj);
-
-       kfree(cma_obj);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_free);
-
-/**
- * drm_gem_cma_dumb_create_internal - create a dumb buffer object
- * @file_priv: DRM file-private structure to create the dumb buffer for
- * @drm: DRM device
- * @args: IOCTL data
- *
- * This aligns the pitch and size arguments to the minimum required. This is
- * an internal helper that can be wrapped by a driver to account for hardware
- * with more specific alignment requirements. It should not be used directly
- * as their &drm_driver.dumb_create callback.
- *
- * Returns:
- * 0 on success or a negative error code on failure.
- */
-int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv,
-                                    struct drm_device *drm,
-                                    struct drm_mode_create_dumb *args)
-{
-       unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-       struct drm_gem_cma_object *cma_obj;
-
-       if (args->pitch < min_pitch)
-               args->pitch = min_pitch;
-
-       if (args->size < args->pitch * args->height)
-               args->size = args->pitch * args->height;
-
-       cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
-                                                &args->handle);
-       return PTR_ERR_OR_ZERO(cma_obj);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal);
-
-/**
- * drm_gem_cma_dumb_create - create a dumb buffer object
- * @file_priv: DRM file-private structure to create the dumb buffer for
- * @drm: DRM device
- * @args: IOCTL data
- *
- * This function computes the pitch of the dumb buffer and rounds it up to an
- * integer number of bytes per pixel. Drivers for hardware that doesn't have
- * any additional restrictions on the pitch can directly use this function as
- * their &drm_driver.dumb_create callback.
- *
- * For hardware with additional restrictions, drivers can adjust the fields
- * set up by userspace and pass the IOCTL data along to the
- * drm_gem_cma_dumb_create_internal() function.
- *
- * Returns:
- * 0 on success or a negative error code on failure.
- */
-int drm_gem_cma_dumb_create(struct drm_file *file_priv,
-                           struct drm_device *drm,
-                           struct drm_mode_create_dumb *args)
-{
-       struct drm_gem_cma_object *cma_obj;
-
-       args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
-       args->size = args->pitch * args->height;
-
-       cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
-                                                &args->handle);
-       return PTR_ERR_OR_ZERO(cma_obj);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
-
-const struct vm_operations_struct drm_gem_cma_vm_ops = {
-       .open = drm_gem_vm_open,
-       .close = drm_gem_vm_close,
-};
-EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
-
-#ifndef CONFIG_MMU
-/**
- * drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases
- * @filp: file object
- * @addr: memory address
- * @len: buffer size
- * @pgoff: page offset
- * @flags: memory flags
- *
- * This function is used in noMMU platforms to propose address mapping
- * for a given buffer.
- * It's intended to be used as a direct handler for the struct
- * &file_operations.get_unmapped_area operation.
- *
- * Returns:
- * mapping address on success or a negative error code on failure.
- */
-unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
-                                           unsigned long addr,
-                                           unsigned long len,
-                                           unsigned long pgoff,
-                                           unsigned long flags)
-{
-       struct drm_gem_cma_object *cma_obj;
-       struct drm_gem_object *obj = NULL;
-       struct drm_file *priv = filp->private_data;
-       struct drm_device *dev = priv->minor->dev;
-       struct drm_vma_offset_node *node;
-
-       if (drm_dev_is_unplugged(dev))
-               return -ENODEV;
-
-       drm_vma_offset_lock_lookup(dev->vma_offset_manager);
-       node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
-                                                 pgoff,
-                                                 len >> PAGE_SHIFT);
-       if (likely(node)) {
-               obj = container_of(node, struct drm_gem_object, vma_node);
-               /*
-                * When the object is being freed, after it hits 0-refcnt it
-                * proceeds to tear down the object. In the process it will
-                * attempt to remove the VMA offset and so acquire this
-                * mgr->vm_lock.  Therefore if we find an object with a 0-refcnt
-                * that matches our range, we know it is in the process of being
-                * destroyed and will be freed as soon as we release the lock -
-                * so we have to check for the 0-refcnted object and treat it as
-                * invalid.
-                */
-               if (!kref_get_unless_zero(&obj->refcount))
-                       obj = NULL;
-       }
-
-       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
-
-       if (!obj)
-               return -EINVAL;
-
-       if (!drm_vma_node_is_allowed(node, priv)) {
-               drm_gem_object_put(obj);
-               return -EACCES;
-       }
-
-       cma_obj = to_drm_gem_cma_obj(obj);
-
-       drm_gem_object_put(obj);
-
-       return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL;
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area);
-#endif
-
-/**
- * drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs
- * @cma_obj: CMA GEM object
- * @p: DRM printer
- * @indent: Tab indentation level
- *
- * This function prints paddr and vaddr for use in e.g. debugfs output.
- */
-void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj,
-                           struct drm_printer *p, unsigned int indent)
-{
-       drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr);
-       drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr);
-}
-EXPORT_SYMBOL(drm_gem_cma_print_info);
-
-/**
- * drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned
- *     pages for a CMA GEM object
- * @cma_obj: CMA GEM object
- *
- * This function exports a scatter/gather table by calling the standard
- * DMA mapping API.
- *
- * Returns:
- * A pointer to the scatter/gather table of pinned pages or NULL on failure.
- */
-struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj)
-{
-       struct drm_gem_object *obj = &cma_obj->base;
-       struct sg_table *sgt;
-       int ret;
-
-       sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
-       if (!sgt)
-               return ERR_PTR(-ENOMEM);
-
-       ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr,
-                             cma_obj->paddr, obj->size);
-       if (ret < 0)
-               goto out;
-
-       return sgt;
-
-out:
-       kfree(sgt);
-       return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table);
-
-/**
- * drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another
- *     driver's scatter/gather table of pinned pages
- * @dev: device to import into
- * @attach: DMA-BUF attachment
- * @sgt: scatter/gather table of pinned pages
- *
- * This function imports a scatter/gather table exported via DMA-BUF by
- * another driver. Imported buffers must be physically contiguous in memory
- * (i.e. the scatter/gather table must contain a single entry). Drivers that
- * use the CMA helpers should set this as their
- * &drm_driver.gem_prime_import_sg_table callback.
- *
- * Returns:
- * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
- * error code on failure.
- */
-struct drm_gem_object *
-drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
-                                 struct dma_buf_attachment *attach,
-                                 struct sg_table *sgt)
-{
-       struct drm_gem_cma_object *cma_obj;
-
-       /* check if the entries in the sg_table are contiguous */
-       if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size)
-               return ERR_PTR(-EINVAL);
-
-       /* Create a CMA GEM buffer. */
-       cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, true);
-       if (IS_ERR(cma_obj))
-               return ERR_CAST(cma_obj);
-
-       cma_obj->paddr = sg_dma_address(sgt->sgl);
-       cma_obj->sgt = sgt;
-
-       DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size);
-
-       return &cma_obj->base;
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table);
-
-/**
- * drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual
- *     address space
- * @cma_obj: CMA GEM object
- * @map: Returns the kernel virtual address of the CMA GEM object's backing
- *       store.
- *
- * This function maps a buffer into the kernel's virtual address space.
- * Since the CMA buffers are already mapped into the kernel virtual address
- * space this simply returns the cached virtual address.
- *
- * Returns:
- * 0 on success, or a negative error code otherwise.
- */
-int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj,
-                    struct iosys_map *map)
-{
-       iosys_map_set_vaddr(map, cma_obj->vaddr);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_vmap);
-
-/**
- * drm_gem_cma_mmap - memory-map an exported CMA GEM object
- * @cma_obj: CMA GEM object
- * @vma: VMA for the area to be mapped
- *
- * This function maps a buffer into a userspace process's address space.
- * In addition to the usual GEM VMA setup it immediately faults in the entire
- * object instead of using on-demand faulting.
- *
- * Returns:
- * 0 on success or a negative error code on failure.
- */
-int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma)
-{
-       struct drm_gem_object *obj = &cma_obj->base;
-       int ret;
-
-       /*
-        * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
-        * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
-        * the whole buffer.
-        */
-       vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
-       vma->vm_flags &= ~VM_PFNMAP;
-       vma->vm_flags |= VM_DONTEXPAND;
-
-       if (cma_obj->map_noncoherent) {
-               vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-
-               ret = dma_mmap_pages(cma_obj->base.dev->dev,
-                                    vma, vma->vm_end - vma->vm_start,
-                                    virt_to_page(cma_obj->vaddr));
-       } else {
-               ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
-                                 cma_obj->paddr, vma->vm_end - vma->vm_start);
-       }
-       if (ret)
-               drm_gem_vm_close(vma);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
-
-/**
- * drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
- *     scatter/gather table and get the virtual address of the buffer
- * @dev: DRM device
- * @attach: DMA-BUF attachment
- * @sgt: Scatter/gather table of pinned pages
- *
- * This function imports a scatter/gather table using
- * drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
- * virtual address. This ensures that a CMA GEM object always has its virtual
- * address set. This address is released when the object is freed.
- *
- * This function can be used as the &drm_driver.gem_prime_import_sg_table
- * callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set
- * the necessary DRM driver operations.
- *
- * Returns:
- * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
- * error code on failure.
- */
-struct drm_gem_object *
-drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
-                                      struct dma_buf_attachment *attach,
-                                      struct sg_table *sgt)
-{
-       struct drm_gem_cma_object *cma_obj;
-       struct drm_gem_object *obj;
-       struct iosys_map map;
-       int ret;
-
-       ret = dma_buf_vmap(attach->dmabuf, &map);
-       if (ret) {
-               DRM_ERROR("Failed to vmap PRIME buffer\n");
-               return ERR_PTR(ret);
-       }
-
-       obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
-       if (IS_ERR(obj)) {
-               dma_buf_vunmap(attach->dmabuf, &map);
-               return obj;
-       }
-
-       cma_obj = to_drm_gem_cma_obj(obj);
-       cma_obj->vaddr = map.vaddr;
-
-       return obj;
-}
-EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);
-
-MODULE_DESCRIPTION("DRM CMA memory-management helpers");
-MODULE_IMPORT_NS(DMA_BUF);
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c
new file mode 100644 (file)
index 0000000..f6901ff
--- /dev/null
@@ -0,0 +1,605 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * drm gem DMA helper functions
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * Based on Samsung Exynos code
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/dma-mapping.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <drm/drm.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_vma_manager.h>
+
+/**
+ * DOC: dma helpers
+ *
+ * The DRM GEM/DMA helpers are a means to provide buffer objects that are
+ * presented to the device as a contiguous chunk of memory. This is useful
+ * for devices that do not support scatter-gather DMA (either directly or
+ * by using an intimately attached IOMMU).
+ *
+ * For devices that access the memory bus through an (external) IOMMU then
+ * the buffer objects are allocated using a traditional page-based
+ * allocator and may be scattered through physical memory. However they
+ * are contiguous in the IOVA space so appear contiguous to devices using
+ * them.
+ *
+ * For other devices then the helpers rely on CMA to provide buffer
+ * objects that are physically contiguous in memory.
+ *
+ * For GEM callback helpers in struct &drm_gem_object functions, see likewise
+ * named functions with an _object_ infix (e.g., drm_gem_dma_object_vmap() wraps
+ * drm_gem_dma_vmap()). These helpers perform the necessary type conversion.
+ */
+
+static const struct drm_gem_object_funcs drm_gem_dma_default_funcs = {
+       .free = drm_gem_dma_object_free,
+       .print_info = drm_gem_dma_object_print_info,
+       .get_sg_table = drm_gem_dma_object_get_sg_table,
+       .vmap = drm_gem_dma_object_vmap,
+       .mmap = drm_gem_dma_object_mmap,
+       .vm_ops = &drm_gem_dma_vm_ops,
+};
+
+/**
+ * __drm_gem_dma_create - Create a GEM DMA object without allocating memory
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ * @private: true if used for internal purposes
+ *
+ * This function creates and initializes a GEM DMA object of the given size,
+ * but doesn't allocate any memory to back the object.
+ *
+ * Returns:
+ * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+static struct drm_gem_dma_object *
+__drm_gem_dma_create(struct drm_device *drm, size_t size, bool private)
+{
+       struct drm_gem_dma_object *dma_obj;
+       struct drm_gem_object *gem_obj;
+       int ret = 0;
+
+       if (drm->driver->gem_create_object) {
+               gem_obj = drm->driver->gem_create_object(drm, size);
+               if (IS_ERR(gem_obj))
+                       return ERR_CAST(gem_obj);
+               dma_obj = to_drm_gem_dma_obj(gem_obj);
+       } else {
+               dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);
+               if (!dma_obj)
+                       return ERR_PTR(-ENOMEM);
+               gem_obj = &dma_obj->base;
+       }
+
+       if (!gem_obj->funcs)
+               gem_obj->funcs = &drm_gem_dma_default_funcs;
+
+       if (private) {
+               drm_gem_private_object_init(drm, gem_obj, size);
+
+               /* Always use writecombine for dma-buf mappings */
+               dma_obj->map_noncoherent = false;
+       } else {
+               ret = drm_gem_object_init(drm, gem_obj, size);
+       }
+       if (ret)
+               goto error;
+
+       ret = drm_gem_create_mmap_offset(gem_obj);
+       if (ret) {
+               drm_gem_object_release(gem_obj);
+               goto error;
+       }
+
+       return dma_obj;
+
+error:
+       kfree(dma_obj);
+       return ERR_PTR(ret);
+}
+
+/**
+ * drm_gem_dma_create - allocate an object with the given size
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ *
+ * This function creates a DMA GEM object and allocates memory as backing store.
+ * The allocated memory will occupy a contiguous chunk of bus address space.
+ *
+ * For devices that are directly connected to the memory bus then the allocated
+ * memory will be physically contiguous. For devices that access through an
+ * IOMMU, then the allocated memory is not expected to be physically contiguous
+ * because having contiguous IOVAs is sufficient to meet a devices DMA
+ * requirements.
+ *
+ * Returns:
+ * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
+                                             size_t size)
+{
+       struct drm_gem_dma_object *dma_obj;
+       int ret;
+
+       size = round_up(size, PAGE_SIZE);
+
+       dma_obj = __drm_gem_dma_create(drm, size, false);
+       if (IS_ERR(dma_obj))
+               return dma_obj;
+
+       if (dma_obj->map_noncoherent) {
+               dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
+                                                      &dma_obj->dma_addr,
+                                                      DMA_TO_DEVICE,
+                                                      GFP_KERNEL | __GFP_NOWARN);
+       } else {
+               dma_obj->vaddr = dma_alloc_wc(drm->dev, size,
+                                             &dma_obj->dma_addr,
+                                             GFP_KERNEL | __GFP_NOWARN);
+       }
+       if (!dma_obj->vaddr) {
+               drm_dbg(drm, "failed to allocate buffer with size %zu\n",
+                        size);
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       return dma_obj;
+
+error:
+       drm_gem_object_put(&dma_obj->base);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_create);
+
+/**
+ * drm_gem_dma_create_with_handle - allocate an object with the given size and
+ *     return a GEM handle to it
+ * @file_priv: DRM file-private structure to register the handle for
+ * @drm: DRM device
+ * @size: size of the object to allocate
+ * @handle: return location for the GEM handle
+ *
+ * This function creates a DMA GEM object, allocating a chunk of memory as
+ * backing store. The GEM object is then added to the list of object associated
+ * with the given file and a handle to it is returned.
+ *
+ * The allocated memory will occupy a contiguous chunk of bus address space.
+ * See drm_gem_dma_create() for more details.
+ *
+ * Returns:
+ * A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
+ * error code on failure.
+ */
+static struct drm_gem_dma_object *
+drm_gem_dma_create_with_handle(struct drm_file *file_priv,
+                              struct drm_device *drm, size_t size,
+                              uint32_t *handle)
+{
+       struct drm_gem_dma_object *dma_obj;
+       struct drm_gem_object *gem_obj;
+       int ret;
+
+       dma_obj = drm_gem_dma_create(drm, size);
+       if (IS_ERR(dma_obj))
+               return dma_obj;
+
+       gem_obj = &dma_obj->base;
+
+       /*
+        * allocate a id of idr table where the obj is registered
+        * and handle has the id what user can see.
+        */
+       ret = drm_gem_handle_create(file_priv, gem_obj, handle);
+       /* drop reference from allocate - handle holds it now. */
+       drm_gem_object_put(gem_obj);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return dma_obj;
+}
+
+/**
+ * drm_gem_dma_free - free resources associated with a DMA GEM object
+ * @dma_obj: DMA GEM object to free
+ *
+ * This function frees the backing memory of the DMA GEM object, cleans up the
+ * GEM object state and frees the memory used to store the object itself.
+ * If the buffer is imported and the virtual address is set, it is released.
+ */
+void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj)
+{
+       struct drm_gem_object *gem_obj = &dma_obj->base;
+       struct iosys_map map = IOSYS_MAP_INIT_VADDR(dma_obj->vaddr);
+
+       if (gem_obj->import_attach) {
+               if (dma_obj->vaddr)
+                       dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);
+               drm_prime_gem_destroy(gem_obj, dma_obj->sgt);
+       } else if (dma_obj->vaddr) {
+               if (dma_obj->map_noncoherent)
+                       dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size,
+                                            dma_obj->vaddr, dma_obj->dma_addr,
+                                            DMA_TO_DEVICE);
+               else
+                       dma_free_wc(gem_obj->dev->dev, dma_obj->base.size,
+                                   dma_obj->vaddr, dma_obj->dma_addr);
+       }
+
+       drm_gem_object_release(gem_obj);
+
+       kfree(dma_obj);
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_free);
+
+/**
+ * drm_gem_dma_dumb_create_internal - create a dumb buffer object
+ * @file_priv: DRM file-private structure to create the dumb buffer for
+ * @drm: DRM device
+ * @args: IOCTL data
+ *
+ * This aligns the pitch and size arguments to the minimum required. This is
+ * an internal helper that can be wrapped by a driver to account for hardware
+ * with more specific alignment requirements. It should not be used directly
+ * as their &drm_driver.dumb_create callback.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv,
+                                    struct drm_device *drm,
+                                    struct drm_mode_create_dumb *args)
+{
+       unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+       struct drm_gem_dma_object *dma_obj;
+
+       if (args->pitch < min_pitch)
+               args->pitch = min_pitch;
+
+       if (args->size < args->pitch * args->height)
+               args->size = args->pitch * args->height;
+
+       dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size,
+                                                &args->handle);
+       return PTR_ERR_OR_ZERO(dma_obj);
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create_internal);
+
+/**
+ * drm_gem_dma_dumb_create - create a dumb buffer object
+ * @file_priv: DRM file-private structure to create the dumb buffer for
+ * @drm: DRM device
+ * @args: IOCTL data
+ *
+ * This function computes the pitch of the dumb buffer and rounds it up to an
+ * integer number of bytes per pixel. Drivers for hardware that doesn't have
+ * any additional restrictions on the pitch can directly use this function as
+ * their &drm_driver.dumb_create callback.
+ *
+ * For hardware with additional restrictions, drivers can adjust the fields
+ * set up by userspace and pass the IOCTL data along to the
+ * drm_gem_dma_dumb_create_internal() function.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_dma_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *drm,
+                           struct drm_mode_create_dumb *args)
+{
+       struct drm_gem_dma_object *dma_obj;
+
+       args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+       args->size = args->pitch * args->height;
+
+       dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size,
+                                                &args->handle);
+       return PTR_ERR_OR_ZERO(dma_obj);
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create);
+
+const struct vm_operations_struct drm_gem_dma_vm_ops = {
+       .open = drm_gem_vm_open,
+       .close = drm_gem_vm_close,
+};
+EXPORT_SYMBOL_GPL(drm_gem_dma_vm_ops);
+
+#ifndef CONFIG_MMU
+/**
+ * drm_gem_dma_get_unmapped_area - propose address for mapping in noMMU cases
+ * @filp: file object
+ * @addr: memory address
+ * @len: buffer size
+ * @pgoff: page offset
+ * @flags: memory flags
+ *
+ * This function is used in noMMU platforms to propose address mapping
+ * for a given buffer.
+ * It's intended to be used as a direct handler for the struct
+ * &file_operations.get_unmapped_area operation.
+ *
+ * Returns:
+ * mapping address on success or a negative error code on failure.
+ */
+unsigned long drm_gem_dma_get_unmapped_area(struct file *filp,
+                                           unsigned long addr,
+                                           unsigned long len,
+                                           unsigned long pgoff,
+                                           unsigned long flags)
+{
+       struct drm_gem_dma_object *dma_obj;
+       struct drm_gem_object *obj = NULL;
+       struct drm_file *priv = filp->private_data;
+       struct drm_device *dev = priv->minor->dev;
+       struct drm_vma_offset_node *node;
+
+       if (drm_dev_is_unplugged(dev))
+               return -ENODEV;
+
+       drm_vma_offset_lock_lookup(dev->vma_offset_manager);
+       node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
+                                                 pgoff,
+                                                 len >> PAGE_SHIFT);
+       if (likely(node)) {
+               obj = container_of(node, struct drm_gem_object, vma_node);
+               /*
+                * When the object is being freed, after it hits 0-refcnt it
+                * proceeds to tear down the object. In the process it will
+                * attempt to remove the VMA offset and so acquire this
+                * mgr->vm_lock.  Therefore if we find an object with a 0-refcnt
+                * that matches our range, we know it is in the process of being
+                * destroyed and will be freed as soon as we release the lock -
+                * so we have to check for the 0-refcnted object and treat it as
+                * invalid.
+                */
+               if (!kref_get_unless_zero(&obj->refcount))
+                       obj = NULL;
+       }
+
+       drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
+
+       if (!obj)
+               return -EINVAL;
+
+       if (!drm_vma_node_is_allowed(node, priv)) {
+               drm_gem_object_put(obj);
+               return -EACCES;
+       }
+
+       dma_obj = to_drm_gem_dma_obj(obj);
+
+       drm_gem_object_put(obj);
+
+       return dma_obj->vaddr ? (unsigned long)dma_obj->vaddr : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_get_unmapped_area);
+#endif
+
+/**
+ * drm_gem_dma_print_info() - Print &drm_gem_dma_object info for debugfs
+ * @dma_obj: DMA GEM object
+ * @p: DRM printer
+ * @indent: Tab indentation level
+ *
+ * This function prints dma_addr and vaddr for use in e.g. debugfs output.
+ */
+void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj,
+                           struct drm_printer *p, unsigned int indent)
+{
+       drm_printf_indent(p, indent, "dma_addr=%pad\n", &dma_obj->dma_addr);
+       drm_printf_indent(p, indent, "vaddr=%p\n", dma_obj->vaddr);
+}
+EXPORT_SYMBOL(drm_gem_dma_print_info);
+
+/**
+ * drm_gem_dma_get_sg_table - provide a scatter/gather table of pinned
+ *     pages for a DMA GEM object
+ * @dma_obj: DMA GEM object
+ *
+ * This function exports a scatter/gather table by calling the standard
+ * DMA mapping API.
+ *
+ * Returns:
+ * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ */
+struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj)
+{
+       struct drm_gem_object *obj = &dma_obj->base;
+       struct sg_table *sgt;
+       int ret;
+
+       sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);
+       if (!sgt)
+               return ERR_PTR(-ENOMEM);
+
+       ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr,
+                             dma_obj->dma_addr, obj->size);
+       if (ret < 0)
+               goto out;
+
+       return sgt;
+
+out:
+       kfree(sgt);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_get_sg_table);
+
+/**
+ * drm_gem_dma_prime_import_sg_table - produce a DMA GEM object from another
+ *     driver's scatter/gather table of pinned pages
+ * @dev: device to import into
+ * @attach: DMA-BUF attachment
+ * @sgt: scatter/gather table of pinned pages
+ *
+ * This function imports a scatter/gather table exported via DMA-BUF by
+ * another driver. Imported buffers must be physically contiguous in memory
+ * (i.e. the scatter/gather table must contain a single entry). Drivers that
+ * use the DMA helpers should set this as their
+ * &drm_driver.gem_prime_import_sg_table callback.
+ *
+ * Returns:
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_object *
+drm_gem_dma_prime_import_sg_table(struct drm_device *dev,
+                                 struct dma_buf_attachment *attach,
+                                 struct sg_table *sgt)
+{
+       struct drm_gem_dma_object *dma_obj;
+
+       /* check if the entries in the sg_table are contiguous */
+       if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size)
+               return ERR_PTR(-EINVAL);
+
+       /* Create a DMA GEM buffer. */
+       dma_obj = __drm_gem_dma_create(dev, attach->dmabuf->size, true);
+       if (IS_ERR(dma_obj))
+               return ERR_CAST(dma_obj);
+
+       dma_obj->dma_addr = sg_dma_address(sgt->sgl);
+       dma_obj->sgt = sgt;
+
+       DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
+                       attach->dmabuf->size);
+
+       return &dma_obj->base;
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_prime_import_sg_table);
+
+/**
+ * drm_gem_dma_vmap - map a DMA GEM object into the kernel's virtual
+ *     address space
+ * @dma_obj: DMA GEM object
+ * @map: Returns the kernel virtual address of the DMA GEM object's backing
+ *       store.
+ *
+ * This function maps a buffer into the kernel's virtual address space.
+ * Since the DMA buffers are already mapped into the kernel virtual address
+ * space this simply returns the cached virtual address.
+ *
+ * Returns:
+ * 0 on success, or a negative error code otherwise.
+ */
+int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj,
+                    struct iosys_map *map)
+{
+       iosys_map_set_vaddr(map, dma_obj->vaddr);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_vmap);
+
+/**
+ * drm_gem_dma_mmap - memory-map an exported DMA GEM object
+ * @dma_obj: DMA GEM object
+ * @vma: VMA for the area to be mapped
+ *
+ * This function maps a buffer into a userspace process's address space.
+ * In addition to the usual GEM VMA setup it immediately faults in the entire
+ * object instead of using on-demand faulting.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma)
+{
+       struct drm_gem_object *obj = &dma_obj->base;
+       int ret;
+
+       /*
+        * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
+        * vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
+        * the whole buffer.
+        */
+       vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
+       vma->vm_flags &= ~VM_PFNMAP;
+       vma->vm_flags |= VM_DONTEXPAND;
+
+       if (dma_obj->map_noncoherent) {
+               vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+               ret = dma_mmap_pages(dma_obj->base.dev->dev,
+                                    vma, vma->vm_end - vma->vm_start,
+                                    virt_to_page(dma_obj->vaddr));
+       } else {
+               ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr,
+                                 dma_obj->dma_addr,
+                                 vma->vm_end - vma->vm_start);
+       }
+       if (ret)
+               drm_gem_vm_close(vma);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(drm_gem_dma_mmap);
+
+/**
+ * drm_gem_dma_prime_import_sg_table_vmap - PRIME import another driver's
+ *     scatter/gather table and get the virtual address of the buffer
+ * @dev: DRM device
+ * @attach: DMA-BUF attachment
+ * @sgt: Scatter/gather table of pinned pages
+ *
+ * This function imports a scatter/gather table using
+ * drm_gem_dma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
+ * virtual address. This ensures that a DMA GEM object always has its virtual
+ * address set. This address is released when the object is freed.
+ *
+ * This function can be used as the &drm_driver.gem_prime_import_sg_table
+ * callback. The &DRM_GEM_DMA_DRIVER_OPS_VMAP macro provides a shortcut to set
+ * the necessary DRM driver operations.
+ *
+ * Returns:
+ * A pointer to a newly created GEM object or an ERR_PTR-encoded negative
+ * error code on failure.
+ */
+struct drm_gem_object *
+drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev,
+                                      struct dma_buf_attachment *attach,
+                                      struct sg_table *sgt)
+{
+       struct drm_gem_dma_object *dma_obj;
+       struct drm_gem_object *obj;
+       struct iosys_map map;
+       int ret;
+
+       ret = dma_buf_vmap(attach->dmabuf, &map);
+       if (ret) {
+               DRM_ERROR("Failed to vmap PRIME buffer\n");
+               return ERR_PTR(ret);
+       }
+
+       obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
+       if (IS_ERR(obj)) {
+               dma_buf_vunmap(attach->dmabuf, &map);
+               return obj;
+       }
+
+       dma_obj = to_drm_gem_dma_obj(obj);
+       dma_obj->vaddr = map.vaddr;
+
+       return obj;
+}
+EXPORT_SYMBOL(drm_gem_dma_prime_import_sg_table_vmap);
+
+MODULE_DESCRIPTION("DRM DMA memory-management helpers");
+MODULE_IMPORT_NS(DMA_BUF);
+MODULE_LICENSE("GPL");
index 61339a9cd01011927b702f8648dc2f8ef49dd990..880a4975507fc14c07cb8fa5b1ed3d79a33bd205 100644 (file)
@@ -490,6 +490,8 @@ void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_directi
 }
 EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);
 
+// TODO Drop this function and replace by drm_format_info_bpp() once all
+// DRM_FORMAT_* provide proper block info in drivers/gpu/drm/drm_fourcc.c
 static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
                                  const struct drm_mode_fb_cmd2 *mode_cmd)
 {
@@ -497,11 +499,6 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
 
        info = drm_get_format_info(dev, mode_cmd);
 
-       /* use whatever a driver has set */
-       if (info->cpp[0])
-               return info->cpp[0] * 8;
-
-       /* guess otherwise */
        switch (info->format) {
        case DRM_FORMAT_YUV420_8BIT:
                return 12;
@@ -510,11 +507,8 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
        case DRM_FORMAT_VUY101010:
                return 30;
        default:
-               break;
+               return drm_format_info_bpp(info, 0);
        }
-
-       /* all attempts failed */
-       return 0;
 }
 
 static int drm_gem_afbc_min_size(struct drm_device *dev,
index 904fc893c905bf7986f1d7d9b59d2ec0ec24577e..35138f8a375c3cb509f8b718f73b575654249039 100644 (file)
@@ -663,7 +663,7 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info);
  * drm_gem_shmem_get_pages_sgt() instead.
  *
  * Returns:
- * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ * A pointer to the scatter/gather table of pinned pages or error pointer on failure.
  */
 struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem)
 {
index d607043716d38b1f104e810bef3d9f5a788a0087..125160b534bef9b76f9ce1b8dead0cc2e297dac6 100644 (file)
@@ -226,9 +226,9 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
         * A failing ttm_bo_init will call ttm_buffer_object_destroy
         * to release gbo->bo.base and kfree gbo.
         */
-       ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device,
-                         &gbo->placement, pg_align, false, NULL, NULL,
-                         ttm_buffer_object_destroy);
+       ret = ttm_bo_init_validate(bdev, &gbo->bo, ttm_bo_type_device,
+                                  &gbo->placement, pg_align, false, NULL, NULL,
+                                  ttm_buffer_object_destroy);
        if (ret)
                return ERR_PTR(ret);
 
index 8faad23dc1d81b4109d1e5534e735d6936d10b94..ca2a6e6101dc8bf8375edb9e33aa0edf8c6189f1 100644 (file)
@@ -472,7 +472,13 @@ EXPORT_SYMBOL(drm_invalid_op);
  */
 static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
 {
-       int len;
+       size_t len;
+
+       /* don't attempt to copy a NULL pointer */
+       if (WARN_ONCE(!value, "BUG: the value to copy was not set!")) {
+               *buf_len = 0;
+               return 0;
+       }
 
        /* don't overflow userbuf */
        len = strlen(value);
index 2f61f53d472f129000433ce862d9c7e3981668d5..84abc3920b5730c67143decb6fc1c1a5e29f44e0 100644 (file)
@@ -205,7 +205,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
        struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
        struct iosys_map map[DRM_FORMAT_MAX_PLANES];
        struct iosys_map data[DRM_FORMAT_MAX_PLANES];
-       void *src;
+       struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
        int ret;
 
        ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
@@ -215,17 +215,16 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
        ret = drm_gem_fb_vmap(fb, map, data);
        if (ret)
                goto out_drm_gem_fb_end_cpu_access;
-       src = data[0].vaddr; /* TODO: Use mapping abstraction properly */
 
        switch (fb->format->format) {
        case DRM_FORMAT_RGB565:
                if (swap)
-                       drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach);
+                       drm_fb_swab(&dst_map, NULL, data, fb, clip, !gem->import_attach);
                else
-                       drm_fb_memcpy(dst, 0, src, fb, clip);
+                       drm_fb_memcpy(&dst_map, NULL, data, fb, clip);
                break;
        case DRM_FORMAT_XRGB8888:
-               drm_fb_xrgb8888_to_rgb565(dst, 0, src, fb, clip, swap);
+               drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, data, fb, clip, swap);
                break;
        default:
                drm_err_once(fb->dev, "Format is not supported: %p4cc\n",
@@ -1136,7 +1135,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
        /*
         * Even though it's not the SPI device that does DMA (the master does),
         * the dma mask is necessary for the dma_alloc_wc() in the GEM code
-        * (e.g., drm_gem_cma_create()). The dma_addr returned will be a physical
+        * (e.g., drm_gem_dma_create()). The dma_addr returned will be a physical
         * address which might be different from the bus address, but this is
         * not a problem since the address will not be used.
         * The virtual address is used in the transfer and the SPI core
index c40bde96cfdf05dfa8d6d39a74a738854867c0c5..3ec02748d56fe032bab48947cd1097098b974204 100644 (file)
@@ -346,6 +346,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
 {
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
 
+       mipi_dsi_detach(dsi);
        mipi_dsi_device_unregister(dsi);
 
        return 0;
@@ -1236,7 +1237,9 @@ static int mipi_dsi_drv_remove(struct device *dev)
        struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
        struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
 
-       return drv->remove(dsi);
+       drv->remove(dsi);
+
+       return 0;
 }
 
 static void mipi_dsi_drv_shutdown(struct device *dev)
index 59b34f07cfce7d444a72b57de98da904ced08506..688c8afe0bf174af2430659b5c3b49ef825c0dc3 100644 (file)
@@ -412,8 +412,8 @@ int drmm_mode_config_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
        INIT_LIST_HEAD(&dev->mode_config.plane_list);
        INIT_LIST_HEAD(&dev->mode_config.privobj_list);
-       idr_init(&dev->mode_config.object_idr);
-       idr_init(&dev->mode_config.tile_idr);
+       idr_init_base(&dev->mode_config.object_idr, 1);
+       idr_init_base(&dev->mode_config.tile_idr, 1);
        ida_init(&dev->mode_config.connector_ida);
        spin_lock_init(&dev->mode_config.connector_list_lock);
 
index 0f08319453b233048f6baf149346151cf50e49cd..bd609a9788481cfc15013ae097d75aef42f4f721 100644 (file)
@@ -108,6 +108,12 @@ static const uint32_t safe_modeset_formats[] = {
        DRM_FORMAT_ARGB8888,
 };
 
+static const struct drm_plane_funcs primary_plane_funcs = {
+       .update_plane = drm_plane_helper_update_primary,
+       .disable_plane = drm_plane_helper_disable_primary,
+       .destroy = drm_plane_helper_destroy,
+};
+
 static struct drm_plane *create_primary_plane(struct drm_device *dev)
 {
        struct drm_plane *primary;
@@ -127,7 +133,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
 
        /* possible_crtc's will be filled in later by crtc_init */
        ret = drm_universal_plane_init(dev, primary, 0,
-                                      &drm_primary_helper_funcs,
+                                      &primary_plane_funcs,
                                       safe_modeset_formats,
                                       ARRAY_SIZE(safe_modeset_formats),
                                       NULL,
index 838b32b70bce6be624783408ec5a0a3141bc8b54..c7785967f5bf7d5e2e65695b0be5628d09d01ca0 100644 (file)
@@ -145,13 +145,36 @@ static int drm_plane_helper_check_update(struct drm_plane *plane,
        return 0;
 }
 
-static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
-                                    struct drm_framebuffer *fb,
-                                    int crtc_x, int crtc_y,
-                                    unsigned int crtc_w, unsigned int crtc_h,
-                                    uint32_t src_x, uint32_t src_y,
-                                    uint32_t src_w, uint32_t src_h,
-                                    struct drm_modeset_acquire_ctx *ctx)
+/**
+ * drm_plane_helper_update_primary - Helper for updating primary planes
+ * @plane: plane to update
+ * @crtc: the plane's new CRTC
+ * @fb: the plane's new framebuffer
+ * @crtc_x: x coordinate within CRTC
+ * @crtc_y: y coordinate within CRTC
+ * @crtc_w: width coordinate within CRTC
+ * @crtc_h: height coordinate within CRTC
+ * @src_x: x coordinate within source
+ * @src_y: y coordinate within source
+ * @src_w: width coordinate within source
+ * @src_h: height coordinate within source
+ * @ctx: modeset locking context
+ *
+ * This helper validates the given parameters and updates the primary plane.
+ *
+ * This function is only useful for non-atomic modesetting. Don't use
+ * it in new drivers.
+ *
+ * Returns:
+ * Zero on success, or an errno code otherwise.
+ */
+int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc,
+                                   struct drm_framebuffer *fb,
+                                   int crtc_x, int crtc_y,
+                                   unsigned int crtc_w, unsigned int crtc_h,
+                                   uint32_t src_x, uint32_t src_y,
+                                   uint32_t src_w, uint32_t src_h,
+                                   struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_mode_set set = {
                .crtc = crtc,
@@ -179,8 +202,8 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c
        ret = drm_plane_helper_check_update(plane, crtc, fb,
                                            &src, &dest,
                                            DRM_MODE_ROTATE_0,
-                                           DRM_PLANE_HELPER_NO_SCALING,
-                                           DRM_PLANE_HELPER_NO_SCALING,
+                                           DRM_PLANE_NO_SCALING,
+                                           DRM_PLANE_NO_SCALING,
                                            false, false, &visible);
        if (ret)
                return ret;
@@ -218,31 +241,40 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c
        kfree(connector_list);
        return ret;
 }
+EXPORT_SYMBOL(drm_plane_helper_update_primary);
 
-static int drm_primary_helper_disable(struct drm_plane *plane,
-                                     struct drm_modeset_acquire_ctx *ctx)
+/**
+ * drm_plane_helper_disable_primary - Helper for disabling primary planes
+ * @plane: plane to disable
+ * @ctx: modeset locking context
+ *
+ * This helper returns an error when trying to disable the primary
+ * plane.
+ *
+ * This function is only useful for non-atomic modesetting. Don't use
+ * it in new drivers.
+ *
+ * Returns:
+ * An errno code.
+ */
+int drm_plane_helper_disable_primary(struct drm_plane *plane,
+                                    struct drm_modeset_acquire_ctx *ctx)
 {
        return -EINVAL;
 }
+EXPORT_SYMBOL(drm_plane_helper_disable_primary);
 
 /**
- * drm_primary_helper_destroy() - Helper for primary plane destruction
+ * drm_plane_helper_destroy() - Helper for primary plane destruction
  * @plane: plane to destroy
  *
  * Provides a default plane destroy handler for primary planes.  This handler
  * is called during CRTC destruction.  We disable the primary plane, remove
  * it from the DRM plane list, and deallocate the plane structure.
  */
-void drm_primary_helper_destroy(struct drm_plane *plane)
+void drm_plane_helper_destroy(struct drm_plane *plane)
 {
        drm_plane_cleanup(plane);
        kfree(plane);
 }
-EXPORT_SYMBOL(drm_primary_helper_destroy);
-
-const struct drm_plane_funcs drm_primary_helper_funcs = {
-       .update_plane = drm_primary_helper_update,
-       .disable_plane = drm_primary_helper_disable,
-       .destroy = drm_primary_helper_destroy,
-};
-EXPORT_SYMBOL(drm_primary_helper_funcs);
+EXPORT_SYMBOL(drm_plane_helper_destroy);
index 36633590ebf39940e44fc67e42947879d0cd1bcb..e9f782119d3db4f27dfec6cad15716c0564f49c2 100644 (file)
@@ -12,7 +12,6 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_managed.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 
@@ -223,8 +222,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
                                                   &pipe->crtc);
 
        ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  false, false);
        if (ret)
                return ret;
index 66e5f1e3404417d56c466c3a7d2711f088aa76e6..7c3aa77186d3431d7020db4dec70332c0cfccb5d 100644 (file)
@@ -9,7 +9,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_crtc.h"
index e95e96c565baac10268174e291d29f8f25b8e317..5ca71ef87325906ded46d6c25e19e146cb3bf945 100644 (file)
@@ -3,7 +3,7 @@ config DRM_FSL_DCU
        tristate "DRM Support for Freescale DCU"
        depends on DRM && OF && ARM && COMMON_CLK
        select BACKLIGHT_CLASS_DEVICE
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_PANEL
        select REGMAP_MMIO
index 7a503bf08d0fa347745ecd4450fde8e366e754e3..b4acc3422ba4501b6c678a99e5620a8efa1ec26c 100644 (file)
@@ -20,9 +20,8 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_modeset_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -150,13 +149,13 @@ static void fsl_dcu_unload(struct drm_device *dev)
        dev->dev_private = NULL;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(fsl_dcu_drm_fops);
 
 static const struct drm_driver fsl_dcu_drm_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .load                   = fsl_dcu_load,
        .unload                 = fsl_dcu_unload,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops                   = &fsl_dcu_drm_fops,
        .name                   = "fsl-dcu-drm",
        .desc                   = "Freescale DCU DRM",
index d763f53f480c5782d3cb33d9a718b6fd3bacb678..5b47000738e423c54858f9c03c98373c8c308e52 100644 (file)
@@ -6,7 +6,6 @@
  */
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
 
index 0cd527f0c1465bb94656a7fd9916be804ada0128..794a87d16f88dc512839f9b32e3bdc32d9693fa7 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 
@@ -84,7 +84,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
        struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
                                                                           plane);
        struct drm_framebuffer *fb = plane->state->fb;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
        int index;
 
@@ -95,7 +95,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
        if (index < 0)
                return;
 
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
 
        switch (fb->format->format) {
        case DRM_FORMAT_RGB565:
@@ -136,7 +136,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
                     DCU_LAYER_POSY(new_state->crtc_y) |
                     DCU_LAYER_POSX(new_state->crtc_x));
        regmap_write(fsl_dev->regmap,
-                    DCU_CTRLDESCLN(index, 3), gem->paddr);
+                    DCU_CTRLDESCLN(index, 3), gem->dma_addr);
        regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
                     DCU_LAYER_EN |
                     DCU_LAYER_TRANS(0xff) |
@@ -171,16 +171,10 @@ static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
        .atomic_update = fsl_dcu_drm_plane_atomic_update,
 };
 
-static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
-{
-       drm_plane_cleanup(plane);
-       kfree(plane);
-}
-
 static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-       .destroy = fsl_dcu_drm_plane_destroy,
+       .destroy = drm_plane_helper_destroy,
        .disable_plane = drm_atomic_helper_disable_plane,
        .reset = drm_atomic_helper_plane_reset,
        .update_plane = drm_atomic_helper_update_plane,
index 9a5ea06a1a8e531511e2f6c4fe386af5d4b0c017..531c1781a8fb466f3a0e8bcfc9cb707ea8966b66 100644 (file)
@@ -9,8 +9,6 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 
-#include <drm/drm_plane_helper.h>
-
 #include "framebuffer.h"
 #include "gem.h"
 #include "gma_display.h"
index 4873f9799f412e047345bc9470238afc1c40bd23..7c6dc2bcd14a6e7b835bf293e3ca71363ef77692 100644 (file)
@@ -59,6 +59,7 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format
        unsigned int bits_per_pixel = 8 / block_width;
        unsigned int x, y, width, height;
        u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */
+       struct iosys_map dst_map, vmap;
        size_t len;
        void *buf;
 
@@ -74,7 +75,9 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format
        if (!buf)
                return 0;
 
-       drm_fb_xrgb8888_to_gray8(buf, 0, src, fb, rect);
+       iosys_map_set_vaddr(&dst_map, buf);
+       iosys_map_set_vaddr(&vmap, src);
+       drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, rect);
        pix8 = buf;
 
        for (y = 0; y < height; y++) {
@@ -105,7 +108,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
        unsigned int bits_per_pixel = 8 / block_width;
        u8 r, g, b, pix, *block = dst; /* Assign to silence compiler warning */
        unsigned int x, y, width;
-       u32 *pix32;
+       __le32 *sbuf32;
+       u32 pix32;
        size_t len;
 
        /* Start on a byte boundary */
@@ -114,8 +118,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
        len = drm_format_info_min_pitch(format, 0, width) * drm_rect_height(rect);
 
        for (y = rect->y1; y < rect->y2; y++) {
-               pix32 = src + (y * fb->pitches[0]);
-               pix32 += rect->x1;
+               sbuf32 = src + (y * fb->pitches[0]);
+               sbuf32 += rect->x1;
 
                for (x = 0; x < width; x++) {
                        unsigned int pixpos = x % block_width; /* within byte from the left */
@@ -126,9 +130,10 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
                                *block = 0;
                        }
 
-                       r = *pix32 >> 16;
-                       g = *pix32 >> 8;
-                       b = *pix32++;
+                       pix32 = le32_to_cpu(*sbuf32++);
+                       r = pix32 >> 16;
+                       g = pix32 >> 8;
+                       b = pix32;
 
                        switch (format->format) {
                        case GUD_DRM_FORMAT_XRGB1111:
@@ -154,6 +159,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
        u8 compression = gdrm->compression;
        struct iosys_map map[DRM_FORMAT_MAX_PLANES];
        struct iosys_map map_data[DRM_FORMAT_MAX_PLANES];
+       struct iosys_map dst;
        void *vaddr, *buf;
        size_t pitch, len;
        int ret = 0;
@@ -177,6 +183,7 @@ retry:
                buf = gdrm->compress_buf;
        else
                buf = gdrm->bulk_buf;
+       iosys_map_set_vaddr(&dst, buf);
 
        /*
         * Imported buffers are assumed to be write-combined and thus uncached
@@ -190,23 +197,24 @@ retry:
                                goto end_cpu_access;
                        }
                } else if (format->format == DRM_FORMAT_R8) {
-                       drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, rect);
+                       drm_fb_xrgb8888_to_gray8(&dst, NULL, map_data, fb, rect);
                } else if (format->format == DRM_FORMAT_RGB332) {
-                       drm_fb_xrgb8888_to_rgb332(buf, 0, vaddr, fb, rect);
+                       drm_fb_xrgb8888_to_rgb332(&dst, NULL, map_data, fb, rect);
                } else if (format->format == DRM_FORMAT_RGB565) {
-                       drm_fb_xrgb8888_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian());
+                       drm_fb_xrgb8888_to_rgb565(&dst, NULL, map_data, fb, rect,
+                                                 gud_is_big_endian());
                } else if (format->format == DRM_FORMAT_RGB888) {
-                       drm_fb_xrgb8888_to_rgb888(buf, 0, vaddr, fb, rect);
+                       drm_fb_xrgb8888_to_rgb888(&dst, NULL, map_data, fb, rect);
                } else {
                        len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect);
                }
        } else if (gud_is_big_endian() && format->cpp[0] > 1) {
-               drm_fb_swab(buf, 0, vaddr, fb, rect, !import_attach);
+               drm_fb_swab(&dst, NULL, map_data, fb, rect, !import_attach);
        } else if (compression && !import_attach && pitch == fb->pitches[0]) {
                /* can compress directly from the framebuffer */
                buf = vaddr + rect->y1 * pitch;
        } else {
-               drm_fb_memcpy(buf, 0, vaddr, fb, rect);
+               drm_fb_memcpy(&dst, NULL, map_data, fb, rect);
        }
 
        memset(req, 0, sizeof(*req));
index b770f7662830836b1c7b79ff9cff728938b54563..c5265675bf0ceb9894ec97f93df56d83b53d359e 100644 (file)
@@ -3,7 +3,7 @@ config DRM_HISI_KIRIN
        tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
        depends on DRM && OF && ARM64
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DSI
        help
          Choose this option if you have a hisilicon Kirin chipsets(hi6220).
index 61c29c2834e6500e1764e910f1c8d31d5fdb1298..871f79a6b17ef5af2008f02426fcd7bb92f2fb23 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 #include <drm/drm_gem_framebuffer_helper.h>
@@ -549,13 +548,13 @@ static const struct drm_crtc_funcs ade_crtc_funcs = {
 static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
                         u32 ch, u32 y, u32 in_h, u32 fmt)
 {
-       struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, 0);
        u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
        u32 stride = fb->pitches[0];
-       u32 addr = (u32)obj->paddr + y * stride;
+       u32 addr = (u32) obj->dma_addr + y * stride;
 
        DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
-                        ch + 1, y, in_h, stride, (u32)obj->paddr);
+                        ch + 1, y, in_h, stride, (u32) obj->dma_addr);
        DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%p4cc)\n",
                         addr, fb->width, fb->height, fmt,
                         &fb->format->format);
@@ -920,12 +919,12 @@ static const struct drm_mode_config_funcs ade_mode_config_funcs = {
 
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ade_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ade_fops);
 
 static const struct drm_driver ade_driver = {
        .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops = &ade_fops,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .name = "kirin",
        .desc = "Hisilicon Kirin620 SoC DRM Driver",
        .date = "20150718",
index 2af51df6dca76393ea72eb61f572ba5ad7345cd7..73ee7f25f7346f3caf5a7e7b5882dbaae0a1a9f4 100644 (file)
@@ -19,9 +19,8 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_of.h>
index b8e64dd8d3a6068cf5cf7ea53b2f465f38ceae18..28e732f94bf2f4d4160b46c42f41d68bd8fa6b35 100644 (file)
 #include "hyperv_drm.h"
 
 static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb,
-                                   const struct iosys_map *map,
+                                   const struct iosys_map *vmap,
                                    struct drm_rect *rect)
 {
        struct hyperv_drm_device *hv = to_hv(fb->dev);
-       void __iomem *dst = hv->vram;
-       void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
+       struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(hv->vram);
        int idx;
 
        if (!drm_dev_enter(&hv->dev, &idx))
                return -ENODEV;
 
-       dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect);
-       drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect);
+       iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, rect));
+       drm_fb_memcpy(&dst, fb->pitches, vmap, fb, rect);
 
        drm_dev_exit(idx);
 
index 592e5adfed8baebd91dd57a952752459aeabbe7f..0f35f2facdfc8291638639db09fa029c53b5ed77 100644 (file)
@@ -7,7 +7,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "intel_atomic.h"
 #include "intel_atomic_plane.h"
@@ -326,8 +325,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
                return ret;
 
        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-                                               DRM_PLANE_HELPER_NO_SCALING,
-                                               DRM_PLANE_HELPER_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
                                                i9xx_plane_has_windowing(plane));
        if (ret)
                return ret;
index 40da7910f8457321f5f7ec2c9ece288173c03344..b94973b5633f2ffd5f3651cbb662e7abdb5ce661 100644 (file)
@@ -32,7 +32,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "i915_drv.h"
 #include "i915_reg.h"
index efe8591619e3fd8aca9726bc47cb7e2098ca4b49..dd876dbbaa394d2f4a1c56d500ae1d91e63af46d 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "gt/intel_rps.h"
 
index 4442aa355f86842948b46c0343f6977695251851..6792a9056f46fcfd63b3f3bab1a7d67be312d305 100644 (file)
@@ -9,7 +9,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank_work.h>
 
 #include "i915_irq.h"
index c2797ad2d313c7598e69f2eba70d2249af3c54cf..16ac560eab4986ca55c598cccd95194563a485bb 100644 (file)
@@ -8,7 +8,6 @@
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_damage_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_fourcc.h>
 
 #include "intel_atomic.h"
@@ -144,8 +143,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        }
 
        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-                                               DRM_PLANE_HELPER_NO_SCALING,
-                                               DRM_PLANE_HELPER_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
                                                true);
        if (ret)
                return ret;
index fc5d94862ef320ae018c51d1583f8aa605b18c21..bf80b57ca63a93036d14212e4989a5f466d97da1 100644 (file)
@@ -41,7 +41,6 @@
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_privacy_screen_consumer.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_rect.h>
index c92d5bb2326a39cc103759b4d79f92ef7fa5f3cc..83af95bce98dd0f83dddce04c49d2aa338e64ba6 100644 (file)
@@ -278,6 +278,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi
 {
        struct drm_i915_private *i915 = to_i915(connector->base.dev);
        struct intel_panel *panel = &connector->panel;
+       struct drm_luminance_range_info *luminance_range =
+               &connector->base.display_info.luminance_range;
        int ret;
 
        if (panel->backlight.edp.intel.sdr_uses_aux) {
@@ -293,8 +295,17 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi
                }
        }
 
-       panel->backlight.max = 512;
-       panel->backlight.min = 0;
+       if (luminance_range->max_luminance) {
+               panel->backlight.max = luminance_range->max_luminance;
+               panel->backlight.min = luminance_range->min_luminance;
+       } else {
+               panel->backlight.max = 512;
+               panel->backlight.min = 0;
+       }
+
+       drm_dbg_kms(&i915->drm, "Using backlight range %d..%d\n", panel->backlight.min,
+                   panel->backlight.max);
+
        panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe);
        panel->backlight.enabled = panel->backlight.level != 0;
 
index 2713faad06252549a0098bff127da1e4cb357d40..7649c50b54452cbb05532497583aac99eb78a577 100644 (file)
@@ -39,7 +39,6 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 
 #include "i915_drv.h"
@@ -1355,8 +1354,8 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state,
 {
        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       int min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+       int min_scale = DRM_PLANE_NO_SCALING;
+       int max_scale = DRM_PLANE_NO_SCALING;
        int ret;
 
        if (g4x_fb_scalable(plane_state->hw.fb)) {
@@ -1426,8 +1425,8 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
                return ret;
 
        ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
-                                               DRM_PLANE_HELPER_NO_SCALING,
-                                               DRM_PLANE_HELPER_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
+                                               DRM_PLANE_NO_SCALING,
                                                true);
        if (ret)
                return ret;
index c11e15a93164d28450e4f5ad5d189577ee780211..4d6a27757065c3c3f7e7756108506e36fbdadacb 100644 (file)
@@ -7,7 +7,6 @@
 #include <drm/drm_blend.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "i915_drv.h"
 #include "intel_atomic_plane.h"
@@ -1856,8 +1855,8 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state,
        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        const struct drm_framebuffer *fb = plane_state->hw.fb;
-       int min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+       int min_scale = DRM_PLANE_NO_SCALING;
+       int max_scale = DRM_PLANE_NO_SCALING;
        int ret;
 
        ret = skl_plane_check_fb(crtc_state, plane_state);
index f131dc065f477a135760fc823c65e123fea063f1..5a5cf332d8a541eb2a5e11d357c52f901cd13719 100644 (file)
@@ -1242,9 +1242,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem,
         * Similarly, in delayed_destroy, we can't call ttm_bo_put()
         * until successful initialization.
         */
-       ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), size,
-                                  bo_type, &i915_sys_placement,
-                                  page_size >> PAGE_SHIFT,
+       ret = ttm_bo_init_reserved(&i915->bdev, i915_gem_to_ttm(obj), bo_type,
+                                  &i915_sys_placement, page_size >> PAGE_SHIFT,
                                   &ctx, NULL, NULL, i915_ttm_bo_destroy);
        if (ret)
                return i915_ttm_err_to_gem(ret);
index 73cebc6aa65072040408a7291b335451e1956873..783a6ca41a61732556e02c318f817c2e3d61d309 100644 (file)
@@ -65,7 +65,7 @@
 
 /*
  * Interrupt statistic for PMU. Increments the counter only if the
- * interrupt originated from the the GPU so interrupts from a device which
+ * interrupt originated from the GPU so interrupts from a device which
  * shares the interrupt line are not accounted.
  */
 static inline void pmu_irq_stats(struct drm_i915_private *i915,
index f06babdb3a8cd2cc757a30dfd15329e431e369f8..ef7553b494eac9f7437fdf3cdce9a65f93219d32 100644 (file)
@@ -32,7 +32,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "display/intel_atomic.h"
 #include "display/intel_atomic_plane.h"
index bb9738c7c825d5e46328e6e754028e505787bc45..975de4ff7313cb9dbd5e206f7f327d1aa4a3faf2 100644 (file)
@@ -3,7 +3,7 @@ config DRM_IMX
        tristate "DRM Support for Freescale i.MX"
        select DRM_KMS_HELPER
        select VIDEOMODE_HELPERS
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM || COMPILE_TEST)
        depends on IMX_IPUV3_CORE
index 5c2b2277afbf54510aad9ece357ef09b517a9013..3ffc061d392bbaee2a2d044c8308c74f5168fd45 100644 (file)
@@ -2,7 +2,7 @@ config DRM_IMX_DCSS
        tristate "i.MX8MQ DCSS"
        select IMX_IRQSTEER
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VIDEOMODE_HELPERS
        depends on DRM && ARCH_MXC && ARM64
        help
index 8cf3352d88582380e82e69cf9b10b1cc91829a2f..b4f82ebca53258efa66324a567e0e8936ec2e3d4 100644 (file)
@@ -8,7 +8,7 @@
 #include <drm/drm_bridge_connector.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
@@ -17,7 +17,7 @@
 #include "dcss-dev.h"
 #include "dcss-kms.h"
 
-DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops);
+DEFINE_DRM_GEM_DMA_FOPS(dcss_cma_fops);
 
 static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = {
        .fb_create = drm_gem_fb_create,
@@ -28,7 +28,7 @@ static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = {
 
 static const struct drm_driver dcss_kms_driver = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops                   = &dcss_cma_fops,
        .name                   = "imx-dcss",
        .desc                   = "i.MX8MQ Display Subsystem",
index c29f343f33e5d13a43f1e8f8c444fb7d714bd55e..ab6d32bad756d080e1c56d7574403febceff94f4 100644 (file)
@@ -6,10 +6,10 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "dcss-dev.h"
 #include "dcss-kms.h"
@@ -147,7 +147,7 @@ static int dcss_plane_atomic_check(struct drm_plane *plane,
        struct dcss_dev *dcss = plane->dev->dev_private;
        struct drm_framebuffer *fb = new_plane_state->fb;
        bool is_primary_plane = plane->type == DRM_PLANE_TYPE_PRIMARY;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct drm_crtc_state *crtc_state;
        int hdisplay, vdisplay;
        int min, max;
@@ -156,8 +156,8 @@ static int dcss_plane_atomic_check(struct drm_plane *plane,
        if (!fb || !new_plane_state->crtc)
                return 0;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       WARN_ON(!cma_obj);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+       WARN_ON(!dma_obj);
 
        crtc_state = drm_atomic_get_existing_crtc_state(state,
                                                        new_plane_state->crtc);
@@ -218,26 +218,26 @@ static void dcss_plane_atomic_set_base(struct dcss_plane *dcss_plane)
        struct dcss_dev *dcss = plane->dev->dev_private;
        struct drm_framebuffer *fb = state->fb;
        const struct drm_format_info *format = fb->format;
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
        unsigned long p1_ba = 0, p2_ba = 0;
 
        if (!format->is_yuv ||
            format->format == DRM_FORMAT_NV12 ||
            format->format == DRM_FORMAT_NV21)
-               p1_ba = cma_obj->paddr + fb->offsets[0] +
+               p1_ba = dma_obj->dma_addr + fb->offsets[0] +
                        fb->pitches[0] * (state->src.y1 >> 16) +
                        format->char_per_block[0] * (state->src.x1 >> 16);
        else if (format->format == DRM_FORMAT_UYVY ||
                 format->format == DRM_FORMAT_VYUY ||
                 format->format == DRM_FORMAT_YUYV ||
                 format->format == DRM_FORMAT_YVYU)
-               p1_ba = cma_obj->paddr + fb->offsets[0] +
+               p1_ba = dma_obj->dma_addr + fb->offsets[0] +
                        fb->pitches[0] * (state->src.y1 >> 16) +
                        2 * format->char_per_block[0] * (state->src.x1 >> 17);
 
        if (format->format == DRM_FORMAT_NV12 ||
            format->format == DRM_FORMAT_NV21)
-               p2_ba = cma_obj->paddr + fb->offsets[1] +
+               p2_ba = dma_obj->dma_addr + fb->offsets[1] +
                        (((fb->pitches[1] >> 1) * (state->src.y1 >> 17) +
                        (state->src.x1 >> 17)) << 1);
 
index a57812ec36b193f1c1d82e6478752c3b135ee1ca..8dd8b0f912af68aa60e475a2a122abd21ff1fc10 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_of.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
@@ -34,7 +32,7 @@
 static int legacyfb_depth = 16;
 module_param(legacyfb_depth, int, 0444);
 
-DEFINE_DRM_GEM_CMA_FOPS(imx_drm_driver_fops);
+DEFINE_DRM_GEM_DMA_FOPS(imx_drm_driver_fops);
 
 void imx_drm_connector_destroy(struct drm_connector *connector)
 {
@@ -154,7 +152,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
 
        args->width = ALIGN(width, 8);
 
-       ret = drm_gem_cma_dumb_create(file_priv, drm, args);
+       ret = drm_gem_dma_dumb_create(file_priv, drm, args);
        if (ret)
                return ret;
 
@@ -164,7 +162,7 @@ static int imx_drm_dumb_create(struct drm_file *file_priv,
 
 static const struct drm_driver imx_drm_driver = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(imx_drm_dumb_create),
        .ioctls                 = imx_drm_ioctls,
        .num_ioctls             = ARRAY_SIZE(imx_drm_ioctls),
        .fops                   = &imx_drm_driver_fops,
index c3e1a3f14d30cd00de6bdb9352a9d29f90c853ac..e721bebda2bddaf0a7b19187c306d04dadf140fb 100644 (file)
@@ -32,7 +32,7 @@ extern struct platform_driver ipu_drm_driver;
 
 void imx_drm_mode_config_init(struct drm_device *drm);
 
-struct drm_gem_cma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
+struct drm_gem_dma_object *imx_drm_fb_get_obj(struct drm_framebuffer *fb);
 
 int imx_drm_encoder_parse_of(struct drm_device *drm,
        struct drm_encoder *encoder, struct device_node *np);
index f7863d6dea80484497ef091efacd39d320b3f817..5f26090b0c9850a541d563d0648e103a50f72816 100644 (file)
@@ -18,8 +18,7 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
index ea5f594955dfe70cc43085c3a4b4241cf315bcc6..dba4f7d81d69359e0553bdf41b9052cb35dd3ae9 100644 (file)
@@ -8,13 +8,12 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
-#include <drm/drm_plane_helper.h>
 
 #include <video/imx-ipu-v3.h>
 
@@ -126,14 +125,14 @@ static inline unsigned long
 drm_plane_state_to_eba(struct drm_plane_state *state, int plane)
 {
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        int x = state->src.x1 >> 16;
        int y = state->src.y1 >> 16;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, plane);
-       BUG_ON(!cma_obj);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, plane);
+       BUG_ON(!dma_obj);
 
-       return cma_obj->paddr + fb->offsets[plane] + fb->pitches[plane] * y +
+       return dma_obj->dma_addr + fb->offsets[plane] + fb->pitches[plane] * y +
               fb->format->cpp[plane] * x;
 }
 
@@ -141,18 +140,18 @@ static inline unsigned long
 drm_plane_state_to_ubo(struct drm_plane_state *state)
 {
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        unsigned long eba = drm_plane_state_to_eba(state, 0);
        int x = state->src.x1 >> 16;
        int y = state->src.y1 >> 16;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
-       BUG_ON(!cma_obj);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 1);
+       BUG_ON(!dma_obj);
 
        x /= fb->format->hsub;
        y /= fb->format->vsub;
 
-       return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
+       return dma_obj->dma_addr + fb->offsets[1] + fb->pitches[1] * y +
               fb->format->cpp[1] * x - eba;
 }
 
@@ -160,18 +159,18 @@ static inline unsigned long
 drm_plane_state_to_vbo(struct drm_plane_state *state)
 {
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        unsigned long eba = drm_plane_state_to_eba(state, 0);
        int x = state->src.x1 >> 16;
        int y = state->src.y1 >> 16;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
-       BUG_ON(!cma_obj);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 2);
+       BUG_ON(!dma_obj);
 
        x /= fb->format->hsub;
        y /= fb->format->vsub;
 
-       return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
+       return dma_obj->dma_addr + fb->offsets[2] + fb->pitches[2] * y +
               fb->format->cpp[2] * x - eba;
 }
 
@@ -393,8 +392,8 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
                return -EINVAL;
 
        ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  can_position, true);
        if (ret)
                return ret;
index 090830bcbde7f32572333057d85b70889dd80a10..a53f475d33df32214da166cd2449cf8591c537b4 100644 (file)
@@ -8,7 +8,7 @@ config DRM_INGENIC
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the Ingenic SoCs.
index eb8208bfe5ab3ff957572d5746b22621341cbb20..ab0515d2c420a20964d56547c56dbea2f179df18 100644 (file)
@@ -30,8 +30,8 @@
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_encoder.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
@@ -41,7 +41,6 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
@@ -482,8 +481,8 @@ static int ingenic_drm_plane_atomic_check(struct drm_plane *plane,
                return PTR_ERR(priv_state);
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  priv->soc_info->has_osd,
                                                  true);
        if (ret)
@@ -670,12 +669,12 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane,
 
        if (newstate && newstate->fb) {
                if (priv->soc_info->map_noncoherent)
-                       drm_fb_cma_sync_non_coherent(&priv->drm, oldstate, newstate);
+                       drm_fb_dma_sync_non_coherent(&priv->drm, oldstate, newstate);
 
                crtc_state = newstate->crtc->state;
                plane_id = !!(priv->soc_info->has_osd && plane != &priv->f0);
 
-               addr = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
+               addr = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0);
                width = newstate->src_w >> 16;
                height = newstate->src_h >> 16;
                cpp = newstate->fb->format->cpp[0];
@@ -915,7 +914,7 @@ static struct drm_gem_object *
 ingenic_drm_gem_create_object(struct drm_device *drm, size_t size)
 {
        struct ingenic_drm *priv = drm_device_get_priv(drm);
-       struct drm_gem_cma_object *obj;
+       struct drm_gem_dma_object *obj;
 
        obj = kzalloc(sizeof(*obj), GFP_KERNEL);
        if (!obj)
@@ -948,7 +947,7 @@ static void ingenic_drm_destroy_state(struct drm_private_obj *obj,
        kfree(priv_state);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ingenic_drm_fops);
 
 static const struct drm_driver ingenic_drm_driver_data = {
        .driver_features        = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
@@ -961,7 +960,7 @@ static const struct drm_driver ingenic_drm_driver_data = {
 
        .fops                   = &ingenic_drm_fops,
        .gem_create_object      = ingenic_drm_gem_create_object,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 };
 
 static const struct drm_plane_funcs ingenic_drm_primary_plane_funcs = {
@@ -1464,21 +1463,22 @@ static int ingenic_drm_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int __maybe_unused ingenic_drm_suspend(struct device *dev)
+static int ingenic_drm_suspend(struct device *dev)
 {
        struct ingenic_drm *priv = dev_get_drvdata(dev);
 
        return drm_mode_config_helper_suspend(&priv->drm);
 }
 
-static int __maybe_unused ingenic_drm_resume(struct device *dev)
+static int ingenic_drm_resume(struct device *dev)
 {
        struct ingenic_drm *priv = dev_get_drvdata(dev);
 
        return drm_mode_config_helper_resume(&priv->drm);
 }
 
-static SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, ingenic_drm_suspend, ingenic_drm_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops,
+                               ingenic_drm_suspend, ingenic_drm_resume);
 
 static const u32 jz4740_formats[] = {
        DRM_FORMAT_XRGB1555,
@@ -1541,6 +1541,32 @@ static const struct jz_soc_info jz4725b_soc_info = {
        .num_formats_f0 = ARRAY_SIZE(jz4725b_formats_f0),
 };
 
+static const struct jz_soc_info jz4760_soc_info = {
+       .needs_dev_clk = false,
+       .has_osd = true,
+       .map_noncoherent = false,
+       .max_width = 1280,
+       .max_height = 720,
+       .max_burst = JZ_LCD_CTRL_BURST_32,
+       .formats_f1 = jz4770_formats_f1,
+       .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
+       .formats_f0 = jz4770_formats_f0,
+       .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
+};
+
+static const struct jz_soc_info jz4760b_soc_info = {
+       .needs_dev_clk = false,
+       .has_osd = true,
+       .map_noncoherent = false,
+       .max_width = 1280,
+       .max_height = 720,
+       .max_burst = JZ_LCD_CTRL_BURST_64,
+       .formats_f1 = jz4770_formats_f1,
+       .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
+       .formats_f0 = jz4770_formats_f0,
+       .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
+};
+
 static const struct jz_soc_info jz4770_soc_info = {
        .needs_dev_clk = false,
        .has_osd = true,
@@ -1572,6 +1598,8 @@ static const struct jz_soc_info jz4780_soc_info = {
 static const struct of_device_id ingenic_drm_of_match[] = {
        { .compatible = "ingenic,jz4740-lcd", .data = &jz4740_soc_info },
        { .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
+       { .compatible = "ingenic,jz4760-lcd", .data = &jz4760_soc_info },
+       { .compatible = "ingenic,jz4760b-lcd", .data = &jz4760b_soc_info },
        { .compatible = "ingenic,jz4770-lcd", .data = &jz4770_soc_info },
        { .compatible = "ingenic,jz4780-lcd", .data = &jz4780_soc_info },
        { /* sentinel */ },
@@ -1581,7 +1609,7 @@ MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
 static struct platform_driver ingenic_drm_driver = {
        .driver = {
                .name = "ingenic-drm",
-               .pm = pm_ptr(&ingenic_drm_pm_ops),
+               .pm = pm_sleep_ptr(&ingenic_drm_pm_ops),
                .of_match_table = of_match_ptr(ingenic_drm_of_match),
        },
        .probe = ingenic_drm_probe,
@@ -1616,4 +1644,4 @@ module_exit(ingenic_drm_exit);
 
 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index 32a50935aa6ddd99c8e72d2942a4b821a6fe136f..7a43505011a571c862dafcc41d55c5529dac01d0 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_property.h>
 #include <drm/drm_vblank.h>
 
@@ -363,15 +362,15 @@ static void ingenic_ipu_plane_atomic_update(struct drm_plane *plane,
        }
 
        if (ingenic_drm_map_noncoherent(ipu->master))
-               drm_fb_cma_sync_non_coherent(ipu->drm, oldstate, newstate);
+               drm_fb_dma_sync_non_coherent(ipu->drm, oldstate, newstate);
 
        /* New addresses will be committed in vblank handler... */
-       ipu->addr_y = drm_fb_cma_get_gem_addr(newstate->fb, newstate, 0);
+       ipu->addr_y = drm_fb_dma_get_gem_addr(newstate->fb, newstate, 0);
        if (finfo->num_planes > 1)
-               ipu->addr_u = drm_fb_cma_get_gem_addr(newstate->fb, newstate,
+               ipu->addr_u = drm_fb_dma_get_gem_addr(newstate->fb, newstate,
                                                      1);
        if (finfo->num_planes > 2)
-               ipu->addr_v = drm_fb_cma_get_gem_addr(newstate->fb, newstate,
+               ipu->addr_v = drm_fb_dma_get_gem_addr(newstate->fb, newstate,
                                                      2);
 
        if (!needs_modeset)
@@ -697,10 +696,12 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane *plane,
 {
        struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane);
        struct drm_crtc_state *crtc_state;
+       bool mode_changed;
 
        if (property != ipu->sharpness_prop)
                return -EINVAL;
 
+       mode_changed = val != ipu->sharpness;
        ipu->sharpness = val;
 
        if (state->crtc) {
@@ -708,7 +709,7 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane *plane,
                if (WARN_ON(!crtc_state))
                        return -EINVAL;
 
-               crtc_state->mode_changed = true;
+               crtc_state->mode_changed |= mode_changed;
        }
 
        return 0;
index 5fdd43dad507a1b71cdc698d840b072bcf96e112..fd011367db1d41599c4bdcad4b1164e1fc75834d 100644 (file)
@@ -3,7 +3,7 @@ config DRM_KMB_DISPLAY
        depends on DRM
        depends on ARCH_KEEMBAY || COMPILE_TEST
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DSI
        help
        Choose this option if you have Intel's KeemBay SOC which integrates
index 76fef0880504ead8eb4709e11c7623875eb1f844..2382ccb3ee99dd21abd30c5ee71dfa615aec631b 100644 (file)
@@ -16,7 +16,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -433,14 +433,14 @@ static void kmb_irq_uninstall(struct drm_device *drm)
        free_irq(kmb->irq_lcd, drm);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver kmb_driver = {
        .driver_features = DRIVER_GEM |
            DRIVER_MODESET | DRIVER_ATOMIC,
        /* GEM Operations */
        .fops = &fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .name = "kmb-drm",
        .desc = "KEEMBAY DISPLAY DRIVER",
        .date = DRIVER_DATE,
index 89d055a089a62e1cf1ba38ec1fbaa2b3277047b7..a42f63f6f95737d7a1a6fd0eb3bf12e9acd1b925 100644 (file)
@@ -8,13 +8,12 @@
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
-#include <drm/drm_plane_helper.h>
 
 #include "kmb_drv.h"
 #include "kmb_plane.h"
@@ -136,8 +135,8 @@ static int kmb_plane_atomic_check(struct drm_plane *plane,
                                                   new_plane_state->crtc);
        return drm_atomic_helper_check_plane_state(new_plane_state,
                                                   crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   can_position, true);
 }
 
@@ -404,7 +403,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
        kmb_write_lcd(kmb, LCD_LAYERn_DMA_LINE_WIDTH(plane_id),
                      (width * fb->format->cpp[0]));
 
-       addr[Y_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
+       addr[Y_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
        kmb_write_lcd(kmb, LCD_LAYERn_DMA_START_ADDR(plane_id),
                      addr[Y_PLANE] + fb->offsets[0]);
        val = get_pixel_format(fb->format->format);
@@ -416,7 +415,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
                kmb_write_lcd(kmb, LCD_LAYERn_DMA_CB_LINE_WIDTH(plane_id),
                              (width * fb->format->cpp[0]));
 
-               addr[U_PLANE] = drm_fb_cma_get_gem_addr(fb, new_plane_state,
+               addr[U_PLANE] = drm_fb_dma_get_gem_addr(fb, new_plane_state,
                                                        U_PLANE);
                /* check if Cb/Cr is swapped*/
                if (num_planes == 3 && (val & LCD_LAYER_CRCB_ORDER))
@@ -437,7 +436,7 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
                                      LCD_LAYERn_DMA_CR_LINE_WIDTH(plane_id),
                                      ((width) * fb->format->cpp[0]));
 
-                       addr[V_PLANE] = drm_fb_cma_get_gem_addr(fb,
+                       addr[V_PLANE] = drm_fb_dma_get_gem_addr(fb,
                                                                new_plane_state,
                                                                V_PLANE);
 
index 300b2be07385bb9b39ceaf9b58b4a2b84ad23fb0..fa7a883688094c8176b6222f79eed6b761e5466b 100644 (file)
@@ -3,7 +3,7 @@ config DRM_LOGICVC
        depends on DRM
        depends on OF || COMPILE_TEST
        select DRM_KMS_HELPER
-       select DRM_KMS_CMA_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_KMS_DMA_HELPER
+       select DRM_GEM_DMA_HELPER
        help
          DRM display driver for the logiCVC programmable logic block from Xylon
index c94bb9bb456bc92801482f82c6b560db22350ef1..43a675d03808fbff4249a6aa915726f7e2443282 100644 (file)
@@ -12,7 +12,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_vblank.h>
 
index 65a050176c3370b7e6254a6387ea41a602a67240..cc9a4e965f779865999ee977f7e2b6816d5430bc 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_print.h>
 
 #include "logicvc_crtc.h"
@@ -29,9 +29,9 @@
 #include "logicvc_of.h"
 #include "logicvc_regs.h"
 
-DEFINE_DRM_GEM_CMA_FOPS(logicvc_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(logicvc_drm_fops);
 
-static int logicvc_drm_gem_cma_dumb_create(struct drm_file *file_priv,
+static int logicvc_drm_gem_dma_dumb_create(struct drm_file *file_priv,
                                           struct drm_device *drm_dev,
                                           struct drm_mode_create_dumb *args)
 {
@@ -40,7 +40,7 @@ static int logicvc_drm_gem_cma_dumb_create(struct drm_file *file_priv,
        /* Stride is always fixed to its configuration value. */
        args->pitch = logicvc->config.row_stride * DIV_ROUND_UP(args->bpp, 8);
 
-       return drm_gem_cma_dumb_create_internal(file_priv, drm_dev, args);
+       return drm_gem_dma_dumb_create_internal(file_priv, drm_dev, args);
 }
 
 static struct drm_driver logicvc_drm_driver = {
@@ -54,7 +54,7 @@ static struct drm_driver logicvc_drm_driver = {
        .major                          = 1,
        .minor                          = 0,
 
-       DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(logicvc_drm_gem_cma_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(logicvc_drm_gem_dma_dumb_create),
 };
 
 static struct regmap_config logicvc_drm_regmap_config = {
index c73592f6c406796da2d57c58a56cf9b10ee299b3..815cebb4c4ca168c212b85c08cd4c1799248f0e5 100644 (file)
@@ -12,7 +12,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_encoder.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
index 441e3cfce4cf9a07b4f9c664357a3313847577d1..464000aea765378894002fdb02dab16d197c27b1 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 
 #include "logicvc_crtc.h"
@@ -117,8 +116,8 @@ static int logicvc_plane_atomic_check(struct drm_plane *drm_plane,
                }
        }
 
-       min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       max_scale = DRM_PLANE_HELPER_NO_SCALING;
+       min_scale = DRM_PLANE_NO_SCALING;
+       max_scale = DRM_PLANE_NO_SCALING;
 
        can_position = (drm_plane->type == DRM_PLANE_TYPE_OVERLAY &&
                        layer->index != (logicvc->config.layers_count - 1) &&
@@ -158,7 +157,7 @@ static void logicvc_plane_atomic_update(struct drm_plane *drm_plane,
                     new_state->crtc_h - 1);
 
        if (logicvc->caps->layer_address) {
-               phys_addr_t fb_addr = drm_fb_cma_get_gem_addr(fb, new_state, 0);
+               phys_addr_t fb_addr = drm_fb_dma_get_gem_addr(fb, new_state, 0);
 
                regmap_write(logicvc->regmap, LOGICVC_LAYER_ADDRESS_REG(index),
                             fb_addr);
@@ -281,7 +280,7 @@ int logicvc_layer_buffer_find_setup(struct logicvc_drm *logicvc,
                return -ENOMEM;
        }
 
-       fb_addr = drm_fb_cma_get_gem_addr(fb, state, 0);
+       fb_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
        if (fb_addr < logicvc->reserved_mem_base) {
                drm_err(drm_dev,
                        "Framebuffer memory below reserved memory base!\n");
index 11940704f6449af9d79f4de4ab40a637ebc62e4b..d8207ffda1af9e32f49ce974631fd80deaca83b0 100644 (file)
@@ -10,9 +10,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drm_panel.h>
index d0bf1bc8da3fec56c9d0367238b4698ef2710dc4..4f3d68e11bc123a1bf35661446ea8ba974b9a159 100644 (file)
@@ -10,7 +10,7 @@ config DRM_MCDE
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the ST-Ericsson MCDE
index 4df477540d07430d0bad5acf39d5a894cfaad0f6..52043a12a2e8e5ae2f0d6d279b2314ba31c98b5b 100644 (file)
 #include <linux/media-bus-format.h>
 
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_mipi_dsi.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_bridge.h>
@@ -165,7 +165,7 @@ static int mcde_display_check(struct drm_simple_display_pipe *pipe,
        struct drm_framebuffer *fb = pstate->fb;
 
        if (fb) {
-               u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
+               u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0);
 
                /* FB base address must be dword aligned. */
                if (offset & 3) {
@@ -1424,7 +1424,7 @@ static void mcde_display_update(struct drm_simple_display_pipe *pipe,
         * from the DRM core before the display is enabled.
         */
        if (fb) {
-               mcde_set_extsrc(mcde, drm_fb_cma_get_gem_addr(fb, pstate, 0));
+               mcde_set_extsrc(mcde, drm_fb_dma_get_gem_addr(fb, pstate, 0));
                dev_info_once(mcde->dev, "first update of display contents\n");
                /*
                 * Usually the flow is already active, unless we are in
index e601baa87e55ce82d5d4882409607f44a4e71667..1c4482ad507d9ff4a5a0c367dc03235f3d418c0e 100644 (file)
@@ -37,7 +37,7 @@
  * (effectively using channels 0..3) for concurrent use.
  *
  * In the current DRM/KMS setup, we use one external source, one overlay,
- * one FIFO and one formatter which we connect to the simple CMA framebuffer
+ * one FIFO and one formatter which we connect to the simple DMA framebuffer
  * helpers. We then provide a bridge to the DSI port, and on the DSI port
  * bridge we connect hang a panel bridge or other bridge. This may be subject
  * to change as we exploit more of the hardware capabilities.
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_of.h>
@@ -198,7 +198,7 @@ static int mcde_modeset_init(struct drm_device *drm)
        return 0;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(drm_fops);
 
 static const struct drm_driver mcde_drm_driver = {
        .driver_features =
@@ -212,7 +212,7 @@ static const struct drm_driver mcde_drm_driver = {
        .major = 1,
        .minor = 0,
        .patchlevel = 0,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 };
 
 static int mcde_drm_bind(struct device *dev)
index 2976d21e9a34a3e77563bb4d9291e8b0935f34a5..6d7d0e207082bdf1886436d5a1b5f5180d593c7b 100644 (file)
@@ -7,7 +7,7 @@ config DRM_MEDIATEK
        depends on HAVE_ARM_SMCCC
        depends on OF
        depends on MTK_MMSYS
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_MIPI_DSI
        select DRM_PANEL
index 42cc7052b0509d102f0fce3674e4f3937483bec9..112615817dcbe9116b94ea195e2f930ed4b1d0b7 100644 (file)
@@ -15,7 +15,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
index 0e4c77724b0550b5352cd33f0857e206f7a18fa8..5f02f8d0e4fcfde1ce1dbc867d70f76ea80805a5 100644 (file)
@@ -20,7 +20,7 @@
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
index 139d7724c6d02f44f8c3606c3f6e84c414656ac3..47e96b0289f98ebc345548f92877c6a7e68f45f6 100644 (file)
@@ -8,7 +8,7 @@
 #include <drm/drm.h>
 #include <drm/drm_device.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_prime.h>
 
 #include "mtk_drm_drv.h"
@@ -22,7 +22,7 @@ static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = {
        .vmap = mtk_drm_gem_prime_vmap,
        .vunmap = mtk_drm_gem_prime_vunmap,
        .mmap = mtk_drm_gem_object_mmap,
-       .vm_ops = &drm_gem_cma_vm_ops,
+       .vm_ops = &drm_gem_dma_vm_ops,
 };
 
 static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev,
index 5c0d9ce699317295ae38957e182fa494a6aa4474..2f5e007dd38001eb8634ed724a52979a299cdde7 100644 (file)
@@ -11,7 +11,6 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "mtk_drm_crtc.h"
 #include "mtk_drm_ddp_comp.h"
@@ -108,8 +107,8 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
                crtc_state = new_plane_state->crtc->state;
 
        return drm_atomic_helper_check_plane_state(plane->state, crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   true, true);
 }
 
@@ -202,8 +201,8 @@ static int mtk_plane_atomic_check(struct drm_plane *plane,
 
        return drm_atomic_helper_check_plane_state(new_plane_state,
                                                   crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   true, true);
 }
 
index 6c70fc3214af276d29ea16325ae7e695560fa9e9..823909da87dbf36a6ad0405b976bae8e08b9a201 100644 (file)
@@ -4,7 +4,7 @@ config DRM_MESON
        depends on DRM && OF && (ARM || ARM64)
        depends on ARCH_MESON || COMPILE_TEST
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_DISPLAY_CONNECTOR
        select VIDEOMODE_HELPERS
        select REGMAP_MMIO
index bd4ca11d3ff536fbf8a297433dc35392cd560e7b..fcf0d493782cb7a4db582bd4406536574088492c 100644 (file)
@@ -19,7 +19,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_module.h>
@@ -87,16 +87,16 @@ static int meson_dumb_create(struct drm_file *file, struct drm_device *dev,
        args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), SZ_64);
        args->size = PAGE_ALIGN(args->pitch * args->height);
 
-       return drm_gem_cma_dumb_create_internal(file, dev, args);
+       return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver meson_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
 
-       /* CMA Ops */
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create),
+       /* DMA Ops */
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(meson_dumb_create),
 
        /* Misc */
        .fops                   = &fops,
index b4a0518c10282f44df338aca5a8d5be86448e6b9..7f98de38842bf932ca3388707ec3e2f2c38d97e3 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "meson_overlay.h"
 #include "meson_registers.h"
@@ -477,7 +476,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
                                                                           plane);
        struct drm_framebuffer *fb = new_state->fb;
        struct meson_drm *priv = meson_overlay->priv;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        unsigned long flags;
        bool interlace_mode;
 
@@ -651,8 +650,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
 
        switch (priv->viu.vd1_planes) {
        case 3:
-               gem = drm_fb_cma_get_gem_obj(fb, 2);
-               priv->viu.vd1_addr2 = gem->paddr + fb->offsets[2];
+               gem = drm_fb_dma_get_gem_obj(fb, 2);
+               priv->viu.vd1_addr2 = gem->dma_addr + fb->offsets[2];
                priv->viu.vd1_stride2 = fb->pitches[2];
                priv->viu.vd1_height2 =
                        drm_format_info_plane_height(fb->format,
@@ -663,8 +662,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
                         priv->viu.vd1_height2);
                fallthrough;
        case 2:
-               gem = drm_fb_cma_get_gem_obj(fb, 1);
-               priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1];
+               gem = drm_fb_dma_get_gem_obj(fb, 1);
+               priv->viu.vd1_addr1 = gem->dma_addr + fb->offsets[1];
                priv->viu.vd1_stride1 = fb->pitches[1];
                priv->viu.vd1_height1 =
                        drm_format_info_plane_height(fb->format,
@@ -675,8 +674,8 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
                         priv->viu.vd1_height1);
                fallthrough;
        case 1:
-               gem = drm_fb_cma_get_gem_obj(fb, 0);
-               priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0];
+               gem = drm_fb_dma_get_gem_obj(fb, 0);
+               priv->viu.vd1_addr0 = gem->dma_addr + fb->offsets[0];
                priv->viu.vd1_stride0 = fb->pitches[0];
                priv->viu.vd1_height0 =
                        drm_format_info_plane_height(fb->format,
index b9ac932af8d008fb75815186913a51485733c079..dfd6a9f33ddab02167860d681d68d07c12347c71 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "meson_plane.h"
 #include "meson_registers.h"
@@ -95,7 +94,7 @@ static int meson_plane_atomic_check(struct drm_plane *plane,
        return drm_atomic_helper_check_plane_state(new_plane_state,
                                                   crtc_state,
                                                   FRAC_16_16(1, 5),
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   false, true);
 }
 
@@ -140,7 +139,7 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
        struct drm_rect dest = drm_plane_state_dest(new_state);
        struct meson_drm *priv = meson_plane->priv;
        struct drm_framebuffer *fb = new_state->fb;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        unsigned long flags;
        int vsc_ini_rcv_num, vsc_ini_rpt_p0_num;
        int vsc_bot_rcv_num, vsc_bot_rpt_p0_num;
@@ -366,9 +365,9 @@ static void meson_plane_atomic_update(struct drm_plane *plane,
        }
 
        /* Update Canvas with buffer address */
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
 
-       priv->viu.osd1_addr = gem->paddr;
+       priv->viu.osd1_addr = gem->dma_addr;
        priv->viu.osd1_stride = fb->pitches[0];
        priv->viu.osd1_height = fb->height;
        priv->viu.osd1_width = fb->width;
index 89558549c3af02eb4838d5f1ed1f8acaf6d8b9c0..182e224c460dd370d30d57195156d7bf39e60d10 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 mgag200-y := \
+       mgag200_bmc.o \
        mgag200_drv.o \
        mgag200_g200.o \
        mgag200_g200eh.o \
@@ -10,7 +11,6 @@ mgag200-y := \
        mgag200_g200se.o \
        mgag200_g200wb.o \
        mgag200_i2c.o \
-       mgag200_mode.o \
-       mgag200_pll.o
+       mgag200_mode.o
 
 obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_bmc.c b/drivers/gpu/drm/mgag200/mgag200_bmc.c
new file mode 100644 (file)
index 0000000..2ba2e3c
--- /dev/null
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/delay.h>
+
+#include "mgag200_drv.h"
+
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
+{
+       u8 tmp;
+       int iter_max;
+
+       /*
+        * 1 - The first step is to inform the BMC of an upcoming mode
+        * change. We are putting the misc<0> to output.
+        */
+
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x10;
+       WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
+
+       /* we are putting a 1 on the misc<0> line */
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x10;
+       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+
+       /*
+        * 2- Second step to mask any further scan request. This is
+        * done by asserting the remfreqmsk bit (XSPAREREG<7>)
+        */
+
+       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x80;
+       WREG_DAC(MGA1064_SPAREREG, tmp);
+
+       /*
+        * 3a- The third step is to verify if there is an active scan.
+        * We are waiting for a 0 on remhsyncsts <XSPAREREG<0>).
+        */
+       iter_max = 300;
+       while (!(tmp & 0x1) && iter_max) {
+               WREG8(DAC_INDEX, MGA1064_SPAREREG);
+               tmp = RREG8(DAC_DATA);
+               udelay(1000);
+               iter_max--;
+       }
+
+       /*
+        * 3b- This step occurs only if the remove is actually
+        * scanning. We are waiting for the end of the frame which is
+        * a 1 on remvsyncsts (XSPAREREG<1>)
+        */
+       if (iter_max) {
+               iter_max = 300;
+               while ((tmp & 0x2) && iter_max) {
+                       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+                       tmp = RREG8(DAC_DATA);
+                       udelay(1000);
+                       iter_max--;
+               }
+       }
+}
+
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
+{
+       u8 tmp;
+
+       /* Ensure that the vrsten and hrsten are set */
+       WREG8(MGAREG_CRTCEXT_INDEX, 1);
+       tmp = RREG8(MGAREG_CRTCEXT_DATA);
+       WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
+
+       /* Assert rstlvl2 */
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+       tmp = RREG8(DAC_DATA);
+       tmp |= 0x8;
+       WREG8(DAC_DATA, tmp);
+
+       udelay(10);
+
+       /* Deassert rstlvl2 */
+       tmp &= ~0x08;
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
+       WREG8(DAC_DATA, tmp);
+
+       /* Remove mask of scan request */
+       WREG8(DAC_INDEX, MGA1064_SPAREREG);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~0x80;
+       WREG8(DAC_DATA, tmp);
+
+       /* Put back a 0 on the misc<0> line */
+       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~0x10;
+       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
+}
index 251a1bb648cc30903d494b4f631e3c67b050629d..4d38b8e18030c9649c2fd530d626c85c28cfb2d8 100644 (file)
@@ -155,15 +155,16 @@ int mgag200_device_preinit(struct mga_device *mdev)
        return 0;
 }
 
-int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
-                       const struct mgag200_device_info *info)
+int mgag200_device_init(struct mga_device *mdev,
+                       const struct mgag200_device_info *info,
+                       const struct mgag200_device_funcs *funcs)
 {
        struct drm_device *dev = &mdev->base;
        u8 crtcext3, misc;
        int ret;
 
        mdev->info = info;
-       mdev->type = type;
+       mdev->funcs = funcs;
 
        ret = drmm_mutex_init(dev, &mdev->rmmio_lock);
        if (ret)
@@ -226,29 +227,29 @@ mgag200_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        switch (type) {
        case G200_PCI:
        case G200_AGP:
-               mdev = mgag200_g200_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200_device_create(pdev, &mgag200_driver);
                break;
        case G200_SE_A:
        case G200_SE_B:
                mdev = mgag200_g200se_device_create(pdev, &mgag200_driver, type);
                break;
        case G200_WB:
-               mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200wb_device_create(pdev, &mgag200_driver);
                break;
        case G200_EV:
-               mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200ev_device_create(pdev, &mgag200_driver);
                break;
        case G200_EH:
-               mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200eh_device_create(pdev, &mgag200_driver);
                break;
        case G200_EH3:
-               mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200eh3_device_create(pdev, &mgag200_driver);
                break;
        case G200_ER:
-               mdev = mgag200_g200er_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200er_device_create(pdev, &mgag200_driver);
                break;
        case G200_EW3:
-               mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver, type);
+               mdev = mgag200_g200ew3_device_create(pdev, &mgag200_driver);
                break;
        default:
                dev_err(&pdev->dev, "Device type %d is unsupported\n", type);
index 301c4ab46539befd94f5f3ad4eaf7df7718cef70..f0c2349404b46edf2adf20a84ef82751c2ae0b16 100644 (file)
 
 #include <video/vga.h>
 
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_shmem_helper.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_plane.h>
 
 #include "mgag200_reg.h"
 
 #define MGA_MISC_OUT 0x1fc2
 #define MGA_MISC_IN 0x1fcc
 
+/*
+ * TODO: This is a pretty large set of default values for all kinds of
+ *       settings. It should be split and set in the various DRM helpers,
+ *       such as the CRTC reset or atomic_enable helpers. The PLL values
+ *       probably belong to each model's PLL code.
+ */
+#define MGAG200_DAC_DEFAULT(xvrefctrl, xpixclkctrl, xmiscctrl, xsyspllm, xsysplln, xsyspllp)   \
+       /* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,                         \
+       /* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,                         \
+       /* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,                         \
+       /* 0x18: */     (xvrefctrl),                                                            \
+       /* 0x19: */        0,                                                                   \
+       /* 0x1a: */     (xpixclkctrl),                                                          \
+       /* 0x1b: */     0xff, 0xbf, 0x20,                                                       \
+       /* 0x1e: */     (xmiscctrl),                                                            \
+       /* 0x1f: */     0x20,                                                                   \
+       /* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                         \
+       /* 0x28: */     0x00, 0x00, 0x00, 0x00,                                                 \
+       /* 0x2c: */     (xsyspllm),                                                             \
+       /* 0x2d: */     (xsysplln),                                                             \
+       /* 0x2e: */     (xsyspllp),                                                             \
+       /* 0x2f: */     0x40,                                                                   \
+       /* 0x30: */     0x00, 0xb0, 0x00, 0xc2, 0x34, 0x14, 0x02, 0x83,                         \
+       /* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3a,                         \
+       /* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,                         \
+       /* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0                          \
+
+#define MGAG200_LUT_SIZE 256
+
 #define MGAG200_MAX_FB_HEIGHT 4096
 #define MGAG200_MAX_FB_WIDTH 4096
 
 struct mga_device;
-struct mgag200_pll;
 
 /*
  * Stores parameters for programming the PLLs
@@ -146,20 +176,12 @@ struct mgag200_pll_values {
        unsigned int s;
 };
 
-struct mgag200_pll_funcs {
-       int (*compute)(struct mgag200_pll *pll, long clock, struct mgag200_pll_values *pllc);
-       void (*update)(struct mgag200_pll *pll, const struct mgag200_pll_values *pllc);
-};
-
-struct mgag200_pll {
-       struct mga_device *mdev;
-
-       const struct mgag200_pll_funcs *funcs;
-};
-
 struct mgag200_crtc_state {
        struct drm_crtc_state base;
 
+       /* Primary-plane format; required for modesetting and color mgmt. */
+       const struct drm_format_info *format;
+
        struct mgag200_pll_values pixpllc;
 };
 
@@ -188,8 +210,6 @@ enum mga_type {
        G200_EW3,
 };
 
-#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
-
 struct mgag200_device_info {
        u16 max_hdisplay;
        u16 max_vdisplay;
@@ -230,10 +250,39 @@ struct mgag200_device_info {
                .bug_no_startadd = (_bug_no_startadd), \
        }
 
+struct mgag200_device_funcs {
+       /*
+        * Disables an external reset source (i.e., BMC) before programming
+        * a new display mode.
+        */
+       void (*disable_vidrst)(struct mga_device *mdev);
+
+       /*
+        * Enables an external reset source (i.e., BMC) after programming
+        * a new display mode.
+        */
+       void (*enable_vidrst)(struct mga_device *mdev);
+
+       /*
+        * Validate that the given state can be programmed into PIXPLLC. On
+        * success, the calculated parameters should be stored in the CRTC's
+        * state in struct @mgag200_crtc_state.pixpllc.
+        */
+       int (*pixpllc_atomic_check)(struct drm_crtc *crtc, struct drm_atomic_state *new_state);
+
+       /*
+        * Program PIXPLLC from the CRTC state. The parameters should have been
+        * stored in struct @mgag200_crtc_state.pixpllc by the corresponding
+        * implementation of @pixpllc_atomic_check.
+        */
+       void (*pixpllc_atomic_update)(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+};
+
 struct mga_device {
        struct drm_device base;
 
        const struct mgag200_device_info *info;
+       const struct mgag200_device_funcs *funcs;
 
        struct resource                 *rmmio_res;
        void __iomem                    *rmmio;
@@ -243,12 +292,11 @@ struct mga_device {
        void __iomem                    *vram;
        resource_size_t                 vram_available;
 
-       enum mga_type                   type;
-
-       struct mgag200_pll pixpll;
+       struct drm_plane primary_plane;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;
        struct mga_i2c_chan i2c;
        struct drm_connector connector;
-       struct drm_simple_display_pipe display_pipe;
 };
 
 static inline struct mga_device *to_mga_device(struct drm_device *dev)
@@ -287,35 +335,113 @@ int mgag200_init_pci_options(struct pci_dev *pdev, u32 option, u32 option2);
 resource_size_t mgag200_probe_vram(void __iomem *mem, resource_size_t size);
 resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
 int mgag200_device_preinit(struct mga_device *mdev);
-int mgag200_device_init(struct mga_device *mdev, enum mga_type type,
-                       const struct mgag200_device_info *info);
+int mgag200_device_init(struct mga_device *mdev,
+                       const struct mgag200_device_info *info,
+                       const struct mgag200_device_funcs *funcs);
 
                                /* mgag200_<device type>.c */
-struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                             enum mga_type type);
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type);
-struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type);
-struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type);
-struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type);
-struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                                enum mga_type type);
-struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type);
-struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                                enum mga_type type);
+void mgag200_g200wb_init_registers(struct mga_device *mdev);
+void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv);
+void mgag200_g200eh_init_registers(struct mga_device *mdev);
+void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev,
+                                               const struct drm_driver *drv);
+struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
+                                                const struct drm_driver *drv);
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev,
+                                               const struct drm_driver *drv);
+struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
+                                                const struct drm_driver *drv);
 
-                               /* mgag200_mode.c */
-resource_size_t mgag200_device_probe_vram(struct mga_device *mdev);
-int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_fb_available);
+/*
+ * mgag200_mode.c
+ */
+
+struct drm_crtc;
+struct drm_crtc_state;
+struct drm_display_mode;
+struct drm_plane;
+struct drm_atomic_state;
+
+extern const uint32_t mgag200_primary_plane_formats[];
+extern const size_t   mgag200_primary_plane_formats_size;
+extern const uint64_t mgag200_primary_plane_fmtmods[];
+
+int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
+                                             struct drm_atomic_state *new_state);
+void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+                                               struct drm_atomic_state *old_state);
+void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+                                                struct drm_atomic_state *old_state);
+#define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \
+       DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \
+       .atomic_check = mgag200_primary_plane_helper_atomic_check, \
+       .atomic_update = mgag200_primary_plane_helper_atomic_update, \
+       .atomic_disable = mgag200_primary_plane_helper_atomic_disable
+
+#define MGAG200_PRIMARY_PLANE_FUNCS \
+       .update_plane = drm_atomic_helper_update_plane, \
+       .disable_plane = drm_atomic_helper_disable_plane, \
+       .destroy = drm_plane_cleanup, \
+       DRM_GEM_SHADOW_PLANE_FUNCS
+
+enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+                                                   const struct drm_display_mode *mode);
+int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state);
+void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state);
+
+#define MGAG200_CRTC_HELPER_FUNCS \
+       .mode_valid = mgag200_crtc_helper_mode_valid, \
+       .atomic_check = mgag200_crtc_helper_atomic_check, \
+       .atomic_flush = mgag200_crtc_helper_atomic_flush, \
+       .atomic_enable = mgag200_crtc_helper_atomic_enable, \
+       .atomic_disable = mgag200_crtc_helper_atomic_disable
+
+void mgag200_crtc_reset(struct drm_crtc *crtc);
+struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc);
+void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state);
+
+#define MGAG200_CRTC_FUNCS \
+       .reset = mgag200_crtc_reset, \
+       .destroy = drm_crtc_cleanup, \
+       .set_config = drm_atomic_helper_set_config, \
+       .page_flip = drm_atomic_helper_page_flip, \
+       .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \
+       .atomic_destroy_state = mgag200_crtc_atomic_destroy_state
+
+#define MGAG200_DAC_ENCODER_FUNCS \
+       .destroy = drm_encoder_cleanup
+
+int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector);
+
+#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \
+       .get_modes  = mgag200_vga_connector_helper_get_modes
+
+#define MGAG200_VGA_CONNECTOR_FUNCS \
+       .reset                  = drm_atomic_helper_connector_reset, \
+       .fill_modes             = drm_helper_probe_single_connector_modes, \
+       .destroy                = drm_connector_cleanup, \
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \
+       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state
+
+void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode);
+void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format);
+void mgag200_enable_display(struct mga_device *mdev);
+void mgag200_init_registers(struct mga_device *mdev);
+int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available);
+
+                               /* mgag200_bmc.c */
+void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
+void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
 
                                /* mgag200_i2c.c */
 int mgag200_i2c_init(struct mga_device *mdev, struct mga_i2c_chan *i2c);
 
-                               /* mgag200_pll.c */
-int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev);
-
 #endif                         /* __MGAG200_DRV_H__ */
index 674385921b7f29302e74698c558b18d74a99dd97..bf5d7fe525a3fd036f8c32460b6797fe905a72f9 100644 (file)
@@ -3,7 +3,11 @@
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -30,6 +34,235 @@ static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
        return mgag200_init_pci_options(pdev, option, 0x00008000);
 }
 
+static void mgag200_g200_init_registers(struct mgag200_g200_device *g200)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x00, 0xc9, 0x1f,
+                                   0x04, 0x2d, 0x19)
+       };
+
+       struct mga_device *mdev = &g200->base;
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); ++i) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i >= 0x30) && (i <= 0x37)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       mgag200_init_registers(mdev);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200_pixpllc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state)
+{
+       static const int post_div_max = 7;
+       static const int in_div_min = 1;
+       static const int in_div_max = 6;
+       static const int feed_div_min = 7;
+       static const int feed_div_max = 127;
+
+       struct drm_device *dev = crtc->dev;
+       struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev);
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       u8 testp, testm, testn;
+       u8 n = 0, m = 0, p, s;
+       long f_vco;
+       long computed;
+       long delta, tmp_delta;
+       long ref_clk = g200->ref_clk;
+       long p_clk_min = g200->pclk_min;
+       long p_clk_max = g200->pclk_max;
+
+       if (clock > p_clk_max) {
+               drm_err(dev, "Pixel Clock %ld too high\n", clock);
+               return -EINVAL;
+       }
+
+       if (clock < p_clk_min >> 3)
+               clock = p_clk_min >> 3;
+
+       f_vco = clock;
+       for (testp = 0;
+            testp <= post_div_max && f_vco < p_clk_min;
+            testp = (testp << 1) + 1, f_vco <<= 1)
+               ;
+       p = testp + 1;
+
+       delta = clock;
+
+       for (testm = in_div_min; testm <= in_div_max; testm++) {
+               for (testn = feed_div_min; testn <= feed_div_max; testn++) {
+                       computed = ref_clk * (testn + 1) / (testm + 1);
+                       if (computed < f_vco)
+                               tmp_delta = f_vco - computed;
+                       else
+                               tmp_delta = computed - f_vco;
+                       if (tmp_delta < delta) {
+                               delta = tmp_delta;
+                               m = testm + 1;
+                               n = testn + 1;
+                       }
+               }
+       }
+       f_vco = ref_clk * n / m;
+       if (f_vco < 100000)
+               s = 0;
+       else if (f_vco < 140000)
+               s = 1;
+       else if (f_vco < 180000)
+               s = 2;
+       else
+               s = 3;
+
+       drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
+                   clock, f_vco, m, n, p, s);
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+static void mgag200_g200_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                              struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = pixpllcm;
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200_crtc_helper_funcs = {
+       MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM Device
  */
@@ -160,8 +393,12 @@ out:
        pci_unmap_rom(pdev, rom);
 }
 
-struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                             enum mga_type type)
+static const struct mgag200_device_funcs mgag200_g200_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200_pixpllc_atomic_update,
+};
+
+struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
        struct mgag200_g200_device *g200;
        struct mga_device *mdev;
@@ -187,15 +424,24 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
 
        mgag200_g200_init_refclk(g200);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200_device_info,
+                                 &mgag200_g200_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200_init_registers(g200);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 1b9a2272874460f05d3584d9f887f3a8bde27b3c..fad62453a91db713947e1ef0d6b591cdb2a58b2d 100644 (file)
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+void mgag200_g200eh_init_registers(struct mga_device *mdev)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x00, 0xc9,
+                                   MGA1064_MISC_CTL_VGA8 | MGA1064_MISC_CTL_DAC_RAM_CS,
+                                   0x00, 0x00, 0x00)
+       };
+
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i >= 0x30) && (i <= 0x37)) ||
+                   ((i >= 0x44) && (i <= 0x4e)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       mgag200_init_registers(mdev);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200eh_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                              struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 800000;
+       static const unsigned int vcomin = 400000;
+       static const unsigned int pllreffreq = 33333;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       for (testp = 16; testp > 0; testp >>= 1) {
+               if (clock * testp > vcomax)
+                       continue;
+               if (clock * testp < vcomin)
+                       continue;
+
+               for (testm = 1; testm < 33; testm++) {
+                       for (testn = 17; testn < 257; testn++) {
+                               computed = (pllreffreq * testn) / (testm * testp);
+                               if (computed > clock)
+                                       tmpdelta = computed - clock;
+                               else
+                                       tmpdelta = clock - computed;
+                               if (tmpdelta < delta) {
+                                       delta = tmpdelta;
+                                       n = testn;
+                                       m = testm;
+                                       p = testp;
+                               }
+                       }
+               }
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+void mgag200_g200eh_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                         struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+       int i, j, tmpcount, vcount;
+       bool pll_locked = false;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       for (i = 0; i <= 32 && pll_locked == false; i++) {
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+               WREG8(DAC_DATA, tmp);
+
+               tmp = RREG8(MGAREG_MEM_MISC_READ);
+               tmp |= 0x3 << 2;
+               WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+               WREG8(DAC_DATA, tmp);
+
+               udelay(500);
+
+               WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
+               WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
+               WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
+
+               udelay(500);
+
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+               tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+               WREG8(DAC_DATA, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+               WREG8(DAC_DATA, tmp);
+
+               vcount = RREG8(MGAREG_VCOUNT);
+
+               for (j = 0; j < 30 && pll_locked == false; j++) {
+                       tmpcount = RREG8(MGAREG_VCOUNT);
+                       if (tmpcount < vcount)
+                               vcount = 0;
+                       if ((tmpcount - vcount) > 2)
+                               pll_locked = true;
+                       else
+                               udelay(5);
+               }
+       }
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200eh_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200eh_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200eh_crtc_helper_funcs = {
+       MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200eh_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200eh_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200eh_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200eh_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200eh_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200eh_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 37500, false, 1, 0, false);
 
-struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type)
+static const struct mgag200_device_funcs mgag200_g200eh_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200eh_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update,
+};
+
+struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -36,15 +296,24 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200eh_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200eh_device_info,
+                                 &mgag200_g200eh_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200eh_init_registers(mdev);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200eh_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 438cda1b14c900ec7cff63dc100af2f56232f018..0f7d8112cd49fcd88b6cd281f38757a8f2fed19a 100644 (file)
 
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200eh3_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                               struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 3000000;
+       static const unsigned int vcomin = 1500000;
+       static const unsigned int pllreffreq = 25000;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+       testp = 0;
+
+       for (testm = 150; testm >= 6; testm--) {
+               if (clock * testm > vcomax)
+                       continue;
+               if (clock * testm < vcomin)
+                       continue;
+               for (testn = 120; testn >= 60; testn--) {
+                       computed = (pllreffreq * testn) / testm;
+                       if (computed > clock)
+                               tmpdelta = computed - clock;
+                       else
+                               tmpdelta = clock - computed;
+                       if (tmpdelta < delta) {
+                               delta = tmpdelta;
+                               n = testn + 1;
+                               m = testm + 1;
+                               p = testp + 1;
+                       }
+                       if (delta == 0)
+                               break;
+               }
+               if (delta == 0)
+                       break;
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200eh3_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200eh3_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200eh3_crtc_helper_funcs = {
+       MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200eh3_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200eh3_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200eh3_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200eh3_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200eh3_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200eh3_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, false, 1, 0, false);
 
+static const struct mgag200_device_funcs mgag200_g200eh3_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200eh3_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200eh_pixpllc_atomic_update, // same as G200EH
+};
+
 struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
-                                                const struct drm_driver *drv,
-                                                enum mga_type type)
+                                                const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -37,15 +201,24 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200eh3_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200eh3_device_info,
+                                 &mgag200_g200eh3_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200eh_init_registers(mdev); // same as G200EH
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200eh3_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 0790d4e6463de5b12507b656c2c586b41980d600..bce267e0f7de3c02c21a06b4ac7f26ecc22f0e40 100644 (file)
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200er_init_registers(struct mga_device *mdev)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x00, 0xc9, 0x1f, 0x00, 0x00, 0x00)
+       };
+
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i >= 0x30) && (i <= 0x37)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       WREG_DAC(0x90, 0); /* G200ER specific */
+
+       mgag200_init_registers(mdev);
+
+       WREG_ECRT(0x24, 0x5); /* G200ER specific */
+}
+
+static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
+{
+       static const uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */
+       u32 memctl;
+
+       memctl = RREG32(MGAREG_MEMCTL);
+
+       memctl |= RESET_FLAG;
+       WREG32(MGAREG_MEMCTL, memctl);
+
+       udelay(1000);
+
+       memctl &= ~RESET_FLAG;
+       WREG32(MGAREG_MEMCTL, memctl);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200er_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                              struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 1488000;
+       static const unsigned int vcomin = 1056000;
+       static const unsigned int pllreffreq = 48000;
+       static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       int testr, testn, testm, testo;
+       unsigned int p, m, n, s;
+       unsigned int computed, vco;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       for (testr = 0; testr < 4; testr++) {
+               if (delta == 0)
+                       break;
+               for (testn = 5; testn < 129; testn++) {
+                       if (delta == 0)
+                               break;
+                       for (testm = 3; testm >= 0; testm--) {
+                               if (delta == 0)
+                                       break;
+                               for (testo = 5; testo < 33; testo++) {
+                                       vco = pllreffreq * (testn + 1) /
+                                               (testr + 1);
+                                       if (vco < vcomin)
+                                               continue;
+                                       if (vco > vcomax)
+                                               continue;
+                                       computed = vco / (m_div_val[testm] * (testo + 1));
+                                       if (computed > clock)
+                                               tmpdelta = computed - clock;
+                                       else
+                                               tmpdelta = clock - computed;
+                                       if (tmpdelta < delta) {
+                                               delta = tmpdelta;
+                                               m = (testm | (testo << 3)) + 1;
+                                               n = testn + 1;
+                                               p = testr + 1;
+                                               s = testr;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+static void mgag200_g200er_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                                struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = pixpllcm;
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+       WREG8(DAC_DATA, tmp);
+
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= MGA1064_REMHEADCTL_CLKDIS;
+       WREG8(DAC_DATA, tmp);
+
+       tmp = RREG8(MGAREG_MEM_MISC_READ);
+       tmp |= (0x3<<2) | 0xc0;
+       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+       tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+       WREG8(DAC_DATA, tmp);
+
+       udelay(500);
+
+       WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
+       WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
+       WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
+
+       udelay(50);
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200er_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200er_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static void mgag200_g200er_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+                                                    struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       const struct drm_format_info *format = mgag200_crtc_state->format;
+
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
+
+       mgag200_set_format_regs(mdev, format);
+       mgag200_set_mode_regs(mdev, adjusted_mode);
+
+       if (funcs->pixpllc_atomic_update)
+               funcs->pixpllc_atomic_update(crtc, old_state);
+
+       mgag200_g200er_reset_tagfifo(mdev);
+
+       mgag200_enable_display(mdev);
+
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
+}
+
+static const struct drm_crtc_helper_funcs mgag200_g200er_crtc_helper_funcs = {
+       .mode_valid = mgag200_crtc_helper_mode_valid,
+       .atomic_check = mgag200_crtc_helper_atomic_check,
+       .atomic_flush = mgag200_crtc_helper_atomic_flush,
+       .atomic_enable = mgag200_g200er_crtc_helper_atomic_enable,
+       .atomic_disable = mgag200_crtc_helper_atomic_disable
+};
+
+static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200er_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200er_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200er_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200er_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200er_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200er_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 55000, false, 1, 0, false);
 
-struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type)
+static const struct mgag200_device_funcs mgag200_g200er_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200er_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200er_pixpllc_atomic_update,
+};
+
+struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -32,15 +330,24 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200er_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200er_device_info,
+                                 &mgag200_g200er_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200er_init_registers(mdev);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200er_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 5353422d0eef1f56f573d8a9e291cec5a02dbb8f..ac957f42abe1824baeece84e7a1714029dbbfc5b 100644 (file)
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200ev_init_registers(struct mga_device *mdev)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x00,
+                                   MGA1064_PIX_CLK_CTL_SEL_PLL,
+                                   MGA1064_MISC_CTL_VGA8 | MGA1064_MISC_CTL_DAC_RAM_CS,
+                                   0x00, 0x00, 0x00)
+       };
+
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i >= 0x30) && (i <= 0x37)) ||
+                   ((i >= 0x44) && (i <= 0x4e)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       mgag200_init_registers(mdev);
+}
+
+static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
+{
+       WREG_ECRT(0x06, 0x00);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200ev_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                              struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 550000;
+       static const unsigned int vcomin = 150000;
+       static const unsigned int pllreffreq = 50000;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       for (testp = 16; testp > 0; testp--) {
+               if (clock * testp > vcomax)
+                       continue;
+               if (clock * testp < vcomin)
+                       continue;
+
+               for (testn = 1; testn < 257; testn++) {
+                       for (testm = 1; testm < 17; testm++) {
+                               computed = (pllreffreq * testn) /
+                                       (testm * testp);
+                               if (computed > clock)
+                                       tmpdelta = computed - clock;
+                               else
+                                       tmpdelta = clock - computed;
+                               if (tmpdelta < delta) {
+                                       delta = tmpdelta;
+                                       n = testn;
+                                       m = testm;
+                                       p = testp;
+                               }
+                       }
+               }
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+static void mgag200_g200ev_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                                struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = pixpllcm;
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+       WREG8(DAC_DATA, tmp);
+
+       tmp = RREG8(MGAREG_MEM_MISC_READ);
+       tmp |= 0x3 << 2;
+       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+       tmp = RREG8(DAC_DATA);
+       WREG8(DAC_DATA, tmp & ~0x40);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+       WREG8(DAC_DATA, tmp);
+
+       WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
+       WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
+       WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
+
+       udelay(50);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+       WREG8(DAC_DATA, tmp);
+
+       udelay(500);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+       tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+       WREG8(DAC_DATA, tmp);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
+       tmp = RREG8(DAC_DATA);
+       WREG8(DAC_DATA, tmp | 0x40);
+
+       tmp = RREG8(MGAREG_MEM_MISC_READ);
+       tmp |= (0x3 << 2);
+       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+       WREG8(DAC_DATA, tmp);
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200ev_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200ev_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static void mgag200_g200ev_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+                                                    struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       const struct drm_format_info *format = mgag200_crtc_state->format;
+
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
+
+       mgag200_set_format_regs(mdev, format);
+       mgag200_set_mode_regs(mdev, adjusted_mode);
+
+       if (funcs->pixpllc_atomic_update)
+               funcs->pixpllc_atomic_update(crtc, old_state);
+
+       mgag200_g200ev_set_hiprilvl(mdev);
+
+       mgag200_enable_display(mdev);
+
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
+}
+
+static const struct drm_crtc_helper_funcs mgag200_g200ev_crtc_helper_funcs = {
+       .mode_valid = mgag200_crtc_helper_mode_valid,
+       .atomic_check = mgag200_crtc_helper_atomic_check,
+       .atomic_flush = mgag200_crtc_helper_atomic_flush,
+       .atomic_enable = mgag200_g200ev_crtc_helper_atomic_enable,
+       .atomic_disable = mgag200_crtc_helper_atomic_disable
+};
+
+static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200ev_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200ev_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200ev_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200ev_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200ev_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200ev_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 32700, false, 0, 1, false);
 
-struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type)
+static const struct mgag200_device_funcs mgag200_g200ev_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200ev_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200ev_pixpllc_atomic_update,
+};
+
+struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -36,15 +335,24 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200ev_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200ev_device_info,
+                                 &mgag200_g200ev_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200ev_init_registers(mdev);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200ev_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 3bfc1324cf78cee43c309a12c9b3faeb2b4eed6d..170934414d7dd7f0ec72eedcbcd55cd0693fe18b 100644 (file)
 
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
+{
+       mgag200_g200wb_init_registers(mdev); // same as G200WB
+
+       WREG_ECRT(0x34, 0x5); // G200EW3 specific
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200ew3_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                               struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 800000;
+       static const unsigned int vcomin = 400000;
+       static const unsigned int pllreffreq = 25000;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       unsigned int testp, testm, testn, testp2;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       for (testp = 1; testp < 8; testp++) {
+               for (testp2 = 1; testp2 < 8; testp2++) {
+                       if (testp < testp2)
+                               continue;
+                       if ((clock * testp * testp2) > vcomax)
+                               continue;
+                       if ((clock * testp * testp2) < vcomin)
+                               continue;
+                       for (testm = 1; testm < 26; testm++) {
+                               for (testn = 32; testn < 2048 ; testn++) {
+                                       computed = (pllreffreq * testn) / (testm * testp * testp2);
+                                       if (computed > clock)
+                                               tmpdelta = computed - clock;
+                                       else
+                                               tmpdelta = clock - computed;
+                                       if (tmpdelta < delta) {
+                                               delta = tmpdelta;
+                                               m = testm + 1;
+                                               n = testn + 1;
+                                               p = testp + 1;
+                                               s = testp2;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200ew3_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200ew3_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200ew3_crtc_helper_funcs = {
+       MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200ew3_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200ew3_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200ew3_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200ew3_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200ew3_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200ew3_device_info =
        MGAG200_DEVICE_INFO_INIT(2048, 2048, 0, true, 0, 1, false);
 
+static const struct mgag200_device_funcs mgag200_g200ew3_device_funcs = {
+       .disable_vidrst = mgag200_bmc_disable_vidrst,
+       .enable_vidrst = mgag200_bmc_enable_vidrst,
+       .pixpllc_atomic_check = mgag200_g200ew3_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update, // same as G200WB
+};
+
 static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev)
 {
        resource_size_t vram_size = resource_size(mdev->vram_res);
@@ -23,8 +199,7 @@ static resource_size_t mgag200_g200ew3_device_probe_vram(struct mga_device *mdev
 }
 
 struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
-                                                const struct drm_driver *drv,
-                                                enum mga_type type)
+                                                const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -46,15 +221,24 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200ew3_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200ew3_device_info,
+                                 &mgag200_g200ew3_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200ew3_init_registers(mdev);
+
        vram_available = mgag200_g200ew3_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200ew3_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 0a3e66695e2297a9cea05af50edc6d3f14b6bfb8..be389ed91cbd8ebbfca37185b092f165e34cfb31 100644 (file)
@@ -1,8 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
@@ -28,6 +33,404 @@ static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
        return mgag200_init_pci_options(pdev, option, 0x00008000);
 }
 
+static void mgag200_g200se_init_registers(struct mgag200_g200se_device *g200se)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x03,
+                                   MGA1064_PIX_CLK_CTL_SEL_PLL,
+                                   MGA1064_MISC_CTL_DAC_EN |
+                                   MGA1064_MISC_CTL_VGA8 |
+                                   MGA1064_MISC_CTL_DAC_RAM_CS,
+                                   0x00, 0x00, 0x00)
+       };
+
+       struct mga_device *mdev = &g200se->base;
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)) ||
+                   ((i >= 0x30) && (i <= 0x37)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       mgag200_init_registers(mdev);
+}
+
+static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
+                                       const struct drm_display_mode *mode,
+                                       const struct drm_format_info *format)
+{
+       struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
+       unsigned int hiprilvl;
+       u8 crtcext6;
+
+       if  (g200se->unique_rev_id >= 0x04) {
+               hiprilvl = 0;
+       } else if (g200se->unique_rev_id >= 0x02) {
+               unsigned int bpp;
+               unsigned long mb;
+
+               if (format->cpp[0] * 8 > 16)
+                       bpp = 32;
+               else if (format->cpp[0] * 8 > 8)
+                       bpp = 16;
+               else
+                       bpp = 8;
+
+               mb = (mode->clock * bpp) / 1000;
+               if (mb > 3100)
+                       hiprilvl = 0;
+               else if (mb > 2600)
+                       hiprilvl = 1;
+               else if (mb > 1900)
+                       hiprilvl = 2;
+               else if (mb > 1160)
+                       hiprilvl = 3;
+               else if (mb > 440)
+                       hiprilvl = 4;
+               else
+                       hiprilvl = 5;
+
+       } else if (g200se->unique_rev_id >= 0x01) {
+               hiprilvl = 3;
+       } else {
+               hiprilvl = 4;
+       }
+
+       crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */
+
+       WREG_ECRT(0x06, crtcext6);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200se_00_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                                 struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 320000;
+       static const unsigned int vcomin = 160000;
+       static const unsigned int pllreffreq = 25000;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta, permitteddelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+       permitteddelta = clock * 5 / 1000;
+
+       for (testp = 8; testp > 0; testp /= 2) {
+               if (clock * testp > vcomax)
+                       continue;
+               if (clock * testp < vcomin)
+                       continue;
+
+               for (testn = 17; testn < 256; testn++) {
+                       for (testm = 1; testm < 32; testm++) {
+                               computed = (pllreffreq * testn) / (testm * testp);
+                               if (computed > clock)
+                                       tmpdelta = computed - clock;
+                               else
+                                       tmpdelta = clock - computed;
+                               if (tmpdelta < delta) {
+                                       delta = tmpdelta;
+                                       m = testm;
+                                       n = testn;
+                                       p = testp;
+                               }
+                       }
+               }
+       }
+
+       if (delta > permitteddelta) {
+               pr_warn("PLL delta too large\n");
+               return -EINVAL;
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+static void mgag200_g200se_00_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                                   struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+}
+
+static int mgag200_g200se_04_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                                 struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 1600000;
+       static const unsigned int vcomin = 800000;
+       static const unsigned int pllreffreq = 25000;
+       static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta, permitteddelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+       unsigned int fvv;
+       unsigned int i;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       if (clock < 25000)
+               clock = 25000;
+       clock = clock * 2;
+
+       /* Permited delta is 0.5% as VESA Specification */
+       permitteddelta = clock * 5 / 1000;
+
+       for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
+               testp = pvalues_e4[i];
+
+               if ((clock * testp) > vcomax)
+                       continue;
+               if ((clock * testp) < vcomin)
+                       continue;
+
+               for (testn = 50; testn <= 256; testn++) {
+                       for (testm = 1; testm <= 32; testm++) {
+                               computed = (pllreffreq * testn) / (testm * testp);
+                               if (computed > clock)
+                                       tmpdelta = computed - clock;
+                               else
+                                       tmpdelta = clock - computed;
+
+                               if (tmpdelta < delta) {
+                                       delta = tmpdelta;
+                                       m = testm;
+                                       n = testn;
+                                       p = testp;
+                               }
+                       }
+               }
+       }
+
+       fvv = pllreffreq * n / m;
+       fvv = (fvv - 800000) / 50000;
+       if (fvv > 15)
+               fvv = 15;
+       s = fvv << 1;
+
+       if (delta > permitteddelta) {
+               pr_warn("PLL delta too large\n");
+               return -EINVAL;
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                                   struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+       xpixpllcn = pixpllcn;
+       xpixpllcp = (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
+       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
+       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+
+       WREG_DAC(0x1a, 0x09);
+       msleep(20);
+       WREG_DAC(0x1a, 0x01);
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200se_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200se_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static void mgag200_g200se_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+                                                    struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       const struct drm_format_info *format = mgag200_crtc_state->format;
+
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
+
+       mgag200_set_format_regs(mdev, format);
+       mgag200_set_mode_regs(mdev, adjusted_mode);
+
+       if (funcs->pixpllc_atomic_update)
+               funcs->pixpllc_atomic_update(crtc, old_state);
+
+       mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, format);
+
+       mgag200_enable_display(mdev);
+
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
+}
+
+static const struct drm_crtc_helper_funcs mgag200_g200se_crtc_helper_funcs = {
+       .mode_valid = mgag200_crtc_helper_mode_valid,
+       .atomic_check = mgag200_crtc_helper_atomic_check,
+       .atomic_flush = mgag200_crtc_helper_atomic_flush,
+       .atomic_enable = mgag200_g200se_crtc_helper_atomic_enable,
+       .atomic_disable = mgag200_crtc_helper_atomic_disable
+};
+
+static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200se_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200se_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200se_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200se_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200se_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
@@ -65,11 +468,22 @@ static int mgag200_g200se_init_unique_rev_id(struct mgag200_g200se_device *g200s
        return 0;
 }
 
+static const struct mgag200_device_funcs mgag200_g200se_00_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200se_00_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200se_00_pixpllc_atomic_update,
+};
+
+static const struct mgag200_device_funcs mgag200_g200se_04_device_funcs = {
+       .pixpllc_atomic_check = mgag200_g200se_04_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200se_04_pixpllc_atomic_update,
+};
+
 struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
                                                enum mga_type type)
 {
        struct mgag200_g200se_device *g200se;
        const struct mgag200_device_info *info;
+       const struct mgag200_device_funcs *funcs;
        struct mga_device *mdev;
        struct drm_device *dev;
        resource_size_t vram_available;
@@ -116,15 +530,28 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
                return ERR_PTR(-EINVAL);
        }
 
-       ret = mgag200_device_init(mdev, type, info);
+       if (g200se->unique_rev_id >= 0x04)
+               funcs = &mgag200_g200se_04_device_funcs;
+       else
+               funcs = &mgag200_g200se_00_device_funcs;
+
+       ret = mgag200_device_init(mdev, info, funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200se_init_registers(g200se);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200se_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index c8450ac8eaeca335280f5b989fc17459f7ff5104..9baa727ac6f9f9fcdc0dd3cdf3f0300667ee9f8b 100644 (file)
 // SPDX-License-Identifier: GPL-2.0-only
 
+#include <linux/delay.h>
 #include <linux/pci.h>
 
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_probe_helper.h>
 
 #include "mgag200_drv.h"
 
+void mgag200_g200wb_init_registers(struct mga_device *mdev)
+{
+       static const u8 dacvalue[] = {
+               MGAG200_DAC_DEFAULT(0x07, 0xc9, 0x1f, 0x00, 0x00, 0x00)
+       };
+
+       size_t i;
+
+       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
+               if ((i <= 0x17) ||
+                   (i == 0x1b) ||
+                   (i == 0x1c) ||
+                   ((i >= 0x1f) && (i <= 0x29)) ||
+                   ((i >= 0x30) && (i <= 0x37)) ||
+                   ((i >= 0x44) && (i <= 0x4e)))
+                       continue;
+               WREG_DAC(i, dacvalue[i]);
+       }
+
+       mgag200_init_registers(mdev);
+}
+
+/*
+ * PIXPLLC
+ */
+
+static int mgag200_g200wb_pixpllc_atomic_check(struct drm_crtc *crtc,
+                                              struct drm_atomic_state *new_state)
+{
+       static const unsigned int vcomax = 550000;
+       static const unsigned int vcomin = 150000;
+       static const unsigned int pllreffreq = 48000;
+
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct mgag200_crtc_state *new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       long clock = new_crtc_state->mode.clock;
+       struct mgag200_pll_values *pixpllc = &new_mgag200_crtc_state->pixpllc;
+       unsigned int delta, tmpdelta;
+       unsigned int testp, testm, testn;
+       unsigned int p, m, n, s;
+       unsigned int computed;
+
+       m = n = p = s = 0;
+       delta = 0xffffffff;
+
+       for (testp = 1; testp < 9; testp++) {
+               if (clock * testp > vcomax)
+                       continue;
+               if (clock * testp < vcomin)
+                       continue;
+
+               for (testm = 1; testm < 17; testm++) {
+                       for (testn = 1; testn < 151; testn++) {
+                               computed = (pllreffreq * testn) / (testm * testp);
+                               if (computed > clock)
+                                       tmpdelta = computed - clock;
+                               else
+                                       tmpdelta = clock - computed;
+                               if (tmpdelta < delta) {
+                                       delta = tmpdelta;
+                                       n = testn;
+                                       m = testm;
+                                       p = testp;
+                                       s = 0;
+                               }
+                       }
+               }
+       }
+
+       pixpllc->m = m;
+       pixpllc->n = n;
+       pixpllc->p = p;
+       pixpllc->s = s;
+
+       return 0;
+}
+
+void mgag200_g200wb_pixpllc_atomic_update(struct drm_crtc *crtc,
+                                         struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct mgag200_pll_values *pixpllc = &mgag200_crtc_state->pixpllc;
+       bool pll_locked = false;
+       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
+       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
+       int i, j, tmpcount, vcount;
+
+       pixpllcm = pixpllc->m - 1;
+       pixpllcn = pixpllc->n - 1;
+       pixpllcp = pixpllc->p - 1;
+       pixpllcs = pixpllc->s;
+
+       xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
+       xpixpllcn = pixpllcn;
+       xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
+
+       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
+
+       for (i = 0; i <= 32 && pll_locked == false; i++) {
+               if (i > 0) {
+                       WREG8(MGAREG_CRTC_INDEX, 0x1e);
+                       tmp = RREG8(MGAREG_CRTC_DATA);
+                       if (tmp < 0xff)
+                               WREG8(MGAREG_CRTC_DATA, tmp+1);
+               }
+
+               /* set pixclkdis to 1 */
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+               WREG8(DAC_DATA, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= MGA1064_REMHEADCTL_CLKDIS;
+               WREG8(DAC_DATA, tmp);
+
+               /* select PLL Set C */
+               tmp = RREG8(MGAREG_MEM_MISC_READ);
+               tmp |= 0x3 << 2;
+               WREG8(MGAREG_MEM_MISC_WRITE, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
+               WREG8(DAC_DATA, tmp);
+
+               udelay(500);
+
+               /* reset the PLL */
+               WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~0x04;
+               WREG8(DAC_DATA, tmp);
+
+               udelay(50);
+
+               /* program pixel pll register */
+               WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
+               WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
+               WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
+
+               udelay(50);
+
+               /* turn pll on */
+               WREG8(DAC_INDEX, MGA1064_VREF_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp |= 0x04;
+               WREG_DAC(MGA1064_VREF_CTL, tmp);
+
+               udelay(500);
+
+               /* select the pixel pll */
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+               tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+               WREG8(DAC_DATA, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
+               tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
+               WREG8(DAC_DATA, tmp);
+
+               /* reset dotclock rate bit */
+               WREG8(MGAREG_SEQ_INDEX, 1);
+               tmp = RREG8(MGAREG_SEQ_DATA);
+               tmp &= ~0x8;
+               WREG8(MGAREG_SEQ_DATA, tmp);
+
+               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
+               tmp = RREG8(DAC_DATA);
+               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+               WREG8(DAC_DATA, tmp);
+
+               vcount = RREG8(MGAREG_VCOUNT);
+
+               for (j = 0; j < 30 && pll_locked == false; j++) {
+                       tmpcount = RREG8(MGAREG_VCOUNT);
+                       if (tmpcount < vcount)
+                               vcount = 0;
+                       if ((tmpcount - vcount) > 2)
+                               pll_locked = true;
+                       else
+                               udelay(5);
+               }
+       }
+
+       WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
+       tmp = RREG8(DAC_DATA);
+       tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
+       WREG_DAC(MGA1064_REMHEADCTL, tmp);
+}
+
+/*
+ * Mode-setting pipeline
+ */
+
+static const struct drm_plane_helper_funcs mgag200_g200wb_primary_plane_helper_funcs = {
+       MGAG200_PRIMARY_PLANE_HELPER_FUNCS,
+};
+
+static const struct drm_plane_funcs mgag200_g200wb_primary_plane_funcs = {
+       MGAG200_PRIMARY_PLANE_FUNCS,
+};
+
+static const struct drm_crtc_helper_funcs mgag200_g200wb_crtc_helper_funcs = {
+       MGAG200_CRTC_HELPER_FUNCS,
+};
+
+static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = {
+       MGAG200_CRTC_FUNCS,
+};
+
+static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = {
+       MGAG200_DAC_ENCODER_FUNCS,
+};
+
+static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = {
+       MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
+};
+
+static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = {
+       MGAG200_VGA_CONNECTOR_FUNCS,
+};
+
+static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
+{
+       struct drm_device *dev = &mdev->base;
+       struct drm_plane *primary_plane = &mdev->primary_plane;
+       struct drm_crtc *crtc = &mdev->crtc;
+       struct drm_encoder *encoder = &mdev->encoder;
+       struct mga_i2c_chan *i2c = &mdev->i2c;
+       struct drm_connector *connector = &mdev->connector;
+       int ret;
+
+       ret = drm_universal_plane_init(dev, primary_plane, 0,
+                                      &mgag200_g200wb_primary_plane_funcs,
+                                      mgag200_primary_plane_formats,
+                                      mgag200_primary_plane_formats_size,
+                                      mgag200_primary_plane_fmtmods,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
+       if (ret) {
+               drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+               return ret;
+       }
+       drm_plane_helper_add(primary_plane, &mgag200_g200wb_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &mgag200_g200wb_crtc_funcs, NULL);
+       if (ret) {
+               drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+               return ret;
+       }
+       drm_crtc_helper_add(crtc, &mgag200_g200wb_crtc_helper_funcs);
+
+       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+       drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+       drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+       ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs,
+                              DRM_MODE_ENCODER_DAC, NULL);
+       if (ret) {
+               drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mgag200_i2c_init(mdev, i2c);
+       if (ret) {
+               drm_err(dev, "failed to add DDC bus: %d\n", ret);
+               return ret;
+       }
+
+       ret = drm_connector_init_with_ddc(dev, connector,
+                                         &mgag200_g200wb_vga_connector_funcs,
+                                         DRM_MODE_CONNECTOR_VGA,
+                                         &i2c->adapter);
+       if (ret) {
+               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
+               return ret;
+       }
+       drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
+       if (ret) {
+               drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * DRM device
  */
 static const struct mgag200_device_info mgag200_g200wb_device_info =
        MGAG200_DEVICE_INFO_INIT(1280, 1024, 31877, true, 0, 1, false);
 
-struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv,
-                                               enum mga_type type)
+static const struct mgag200_device_funcs mgag200_g200wb_device_funcs = {
+       .disable_vidrst = mgag200_bmc_disable_vidrst,
+       .enable_vidrst = mgag200_bmc_enable_vidrst,
+       .pixpllc_atomic_check = mgag200_g200wb_pixpllc_atomic_check,
+       .pixpllc_atomic_update = mgag200_g200wb_pixpllc_atomic_update,
+};
+
+struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const struct drm_driver *drv)
 {
        struct mga_device *mdev;
        struct drm_device *dev;
@@ -36,15 +345,24 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
        if (ret)
                return ERR_PTR(ret);
 
-       ret = mgag200_device_init(mdev, type, &mgag200_g200wb_device_info);
+       ret = mgag200_device_init(mdev, &mgag200_g200wb_device_info,
+                                 &mgag200_g200wb_device_funcs);
        if (ret)
                return ERR_PTR(ret);
 
+       mgag200_g200wb_init_registers(mdev);
+
        vram_available = mgag200_device_probe_vram(mdev);
 
-       ret = mgag200_modeset_init(mdev, vram_available);
+       ret = mgag200_mode_config_init(mdev, vram_available);
        if (ret)
                return ERR_PTR(ret);
 
+       ret = mgag200_g200wb_pipeline_init(mdev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       drm_mode_config_reset(dev);
+
        return mdev;
 }
index 225cca2ed60e795b7caccbab38eee0b47512680c..bbab2549243abceebf5a4bf6a033b6edcebd925b 100644 (file)
 #include <linux/delay.h>
 #include <linux/iosys-map.h>
 
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_crtc_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
 
 #include "mgag200_drv.h"
 
-#define MGAG200_LUT_SIZE 256
-
 /*
  * This file contains setup code for the CRTC.
  */
@@ -132,95 +127,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
        } while ((status & 0x01) && time_before(jiffies, timeout));
 }
 
-static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
-{
-       u8 tmp;
-       int iter_max;
-
-       /* 1- The first step is to warn the BMC of an upcoming mode change.
-        * We are putting the misc<0> to output.*/
-
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x10;
-       WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
-
-       /* we are putting a 1 on the misc<0> line */
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x10;
-       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-
-       /* 2- Second step to mask and further scan request
-        * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
-        */
-       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x80;
-       WREG_DAC(MGA1064_SPAREREG, tmp);
-
-       /* 3a- the third step is to verifu if there is an active scan
-        * We are searching for a 0 on remhsyncsts <XSPAREREG<0>)
-        */
-       iter_max = 300;
-       while (!(tmp & 0x1) && iter_max) {
-               WREG8(DAC_INDEX, MGA1064_SPAREREG);
-               tmp = RREG8(DAC_DATA);
-               udelay(1000);
-               iter_max--;
-       }
-
-       /* 3b- this step occurs only if the remove is actually scanning
-        * we are waiting for the end of the frame which is a 1 on
-        * remvsyncsts (XSPAREREG<1>)
-        */
-       if (iter_max) {
-               iter_max = 300;
-               while ((tmp & 0x2) && iter_max) {
-                       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-                       tmp = RREG8(DAC_DATA);
-                       udelay(1000);
-                       iter_max--;
-               }
-       }
-}
-
-static void mgag200_g200wb_release_bmc(struct mga_device *mdev)
-{
-       u8 tmp;
-
-       /* 1- The first step is to ensure that the vrsten and hrsten are set */
-       WREG8(MGAREG_CRTCEXT_INDEX, 1);
-       tmp = RREG8(MGAREG_CRTCEXT_DATA);
-       WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
-
-       /* 2- second step is to assert the rstlvl2 */
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-       tmp = RREG8(DAC_DATA);
-       tmp |= 0x8;
-       WREG8(DAC_DATA, tmp);
-
-       /* wait 10 us */
-       udelay(10);
-
-       /* 3- deassert rstlvl2 */
-       tmp &= ~0x08;
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
-       WREG8(DAC_DATA, tmp);
-
-       /* 4- remove mask of scan request */
-       WREG8(DAC_INDEX, MGA1064_SPAREREG);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~0x80;
-       WREG8(DAC_DATA, tmp);
-
-       /* 5- put back a 0 on the misc<0> line */
-       WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~0x10;
-       WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
-}
-
 /*
  * This is how the framebuffer base address is stored in g200 cards:
  *   * Assume @offset is the gpu_addr variable of the framebuffer object
@@ -267,86 +173,10 @@ static void mgag200_set_startadd(struct mga_device *mdev,
        WREG_ECRT(0x00, crtcext0);
 }
 
-static void mgag200_set_dac_regs(struct mga_device *mdev)
-{
-       size_t i;
-       u8 dacvalue[] = {
-               /* 0x00: */        0,    0,    0,    0,    0,    0, 0x00,    0,
-               /* 0x08: */        0,    0,    0,    0,    0,    0,    0,    0,
-               /* 0x10: */        0,    0,    0,    0,    0,    0,    0,    0,
-               /* 0x18: */     0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
-               /* 0x20: */     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               /* 0x28: */     0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
-               /* 0x30: */     0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
-               /* 0x38: */     0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
-               /* 0x40: */        0,    0,    0,    0,    0,    0,    0,    0,
-               /* 0x48: */        0,    0,    0,    0,    0,    0,    0,    0
-       };
-
-       switch (mdev->type) {
-       case G200_PCI:
-       case G200_AGP:
-               dacvalue[MGA1064_SYS_PLL_M] = 0x04;
-               dacvalue[MGA1064_SYS_PLL_N] = 0x2D;
-               dacvalue[MGA1064_SYS_PLL_P] = 0x19;
-               break;
-       case G200_SE_A:
-       case G200_SE_B:
-               dacvalue[MGA1064_VREF_CTL] = 0x03;
-               dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
-               dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
-                                            MGA1064_MISC_CTL_VGA8 |
-                                            MGA1064_MISC_CTL_DAC_RAM_CS;
-               break;
-       case G200_WB:
-       case G200_EW3:
-               dacvalue[MGA1064_VREF_CTL] = 0x07;
-               break;
-       case G200_EV:
-               dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
-               dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
-                                            MGA1064_MISC_CTL_DAC_RAM_CS;
-               break;
-       case G200_EH:
-       case G200_EH3:
-               dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
-                                            MGA1064_MISC_CTL_DAC_RAM_CS;
-               break;
-       case G200_ER:
-               break;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(dacvalue); i++) {
-               if ((i <= 0x17) ||
-                   (i == 0x1b) ||
-                   (i == 0x1c) ||
-                   ((i >= 0x1f) && (i <= 0x29)) ||
-                   ((i >= 0x30) && (i <= 0x37)))
-                       continue;
-               if (IS_G200_SE(mdev) &&
-                   ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
-                       continue;
-               if ((mdev->type == G200_EV ||
-                   mdev->type == G200_WB ||
-                   mdev->type == G200_EH ||
-                   mdev->type == G200_EW3 ||
-                   mdev->type == G200_EH3) &&
-                   (i >= 0x44) && (i <= 0x4e))
-                       continue;
-
-               WREG_DAC(i, dacvalue[i]);
-       }
-
-       if (mdev->type == G200_ER)
-               WREG_DAC(0x90, 0);
-}
-
-static void mgag200_init_regs(struct mga_device *mdev)
+void mgag200_init_registers(struct mga_device *mdev)
 {
        u8 crtc11, misc;
 
-       mgag200_set_dac_regs(mdev);
-
        WREG_SEQ(2, 0x0f);
        WREG_SEQ(3, 0x00);
        WREG_SEQ(4, 0x0e);
@@ -364,19 +194,12 @@ static void mgag200_init_regs(struct mga_device *mdev)
                    MGAREG_CRTC11_VINTCLR);
        WREG_CRT(0x11, crtc11);
 
-       if (mdev->type == G200_ER)
-               WREG_ECRT(0x24, 0x5);
-
-       if (mdev->type == G200_EW3)
-               WREG_ECRT(0x34, 0x5);
-
        misc = RREG8(MGA_MISC_IN);
        misc |= MGAREG_MISC_IOADSEL;
        WREG8(MGA_MISC_OUT, misc);
 }
 
-static void mgag200_set_mode_regs(struct mga_device *mdev,
-                                 const struct drm_display_mode *mode)
+void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode)
 {
        const struct mgag200_device_info *info = mdev->info;
        unsigned int hdisplay, hsyncstart, hsyncend, htotal;
@@ -500,11 +323,9 @@ static void mgag200_set_offset(struct mga_device *mdev,
        WREG_ECRT(0x00, crtcext0);
 }
 
-static void mgag200_set_format_regs(struct mga_device *mdev,
-                                   const struct drm_framebuffer *fb)
+void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format)
 {
        struct drm_device *dev = &mdev->base;
-       const struct drm_format_info *format = fb->format;
        unsigned int bpp, bppshift, scale;
        u8 crtcext3, xmulctrl;
 
@@ -565,76 +386,9 @@ static void mgag200_set_format_regs(struct mga_device *mdev,
        WREG_ECRT(3, crtcext3);
 }
 
-static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
+void mgag200_enable_display(struct mga_device *mdev)
 {
-       static uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */
-       u32 memctl;
-
-       memctl = RREG32(MGAREG_MEMCTL);
-
-       memctl |= RESET_FLAG;
-       WREG32(MGAREG_MEMCTL, memctl);
-
-       udelay(1000);
-
-       memctl &= ~RESET_FLAG;
-       WREG32(MGAREG_MEMCTL, memctl);
-}
-
-static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
-                                       const struct drm_display_mode *mode,
-                                       const struct drm_framebuffer *fb)
-{
-       struct mgag200_g200se_device *g200se = to_mgag200_g200se_device(&mdev->base);
-       unsigned int hiprilvl;
-       u8 crtcext6;
-
-       if  (g200se->unique_rev_id >= 0x04) {
-               hiprilvl = 0;
-       } else if (g200se->unique_rev_id >= 0x02) {
-               unsigned int bpp;
-               unsigned long mb;
-
-               if (fb->format->cpp[0] * 8 > 16)
-                       bpp = 32;
-               else if (fb->format->cpp[0] * 8 > 8)
-                       bpp = 16;
-               else
-                       bpp = 8;
-
-               mb = (mode->clock * bpp) / 1000;
-               if (mb > 3100)
-                       hiprilvl = 0;
-               else if (mb > 2600)
-                       hiprilvl = 1;
-               else if (mb > 1900)
-                       hiprilvl = 2;
-               else if (mb > 1160)
-                       hiprilvl = 3;
-               else if (mb > 440)
-                       hiprilvl = 4;
-               else
-                       hiprilvl = 5;
-
-       } else if (g200se->unique_rev_id >= 0x01) {
-               hiprilvl = 3;
-       } else {
-               hiprilvl = 4;
-       }
-
-       crtcext6 = hiprilvl; /* implicitly sets maxhipri to 0 */
-
-       WREG_ECRT(0x06, crtcext6);
-}
-
-static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
-{
-       WREG_ECRT(0x06, 0x00);
-}
-
-static void mgag200_enable_display(struct mga_device *mdev)
-{
-       u8 seq0, seq1, crtcext1;
+       u8 seq0, crtcext1;
 
        RREG_SEQ(0x00, seq0);
        seq0 |= MGAREG_SEQ0_SYNCRST |
@@ -648,12 +402,6 @@ static void mgag200_enable_display(struct mga_device *mdev)
        mga_wait_vsync(mdev);
        mga_wait_busy(mdev);
 
-       RREG_SEQ(0x01, seq1);
-       seq1 &= ~MGAREG_SEQ1_SCROFF;
-       WREG_SEQ(0x01, seq1);
-
-       msleep(20);
-
        RREG_ECRT(0x01, crtcext1);
        crtcext1 &= ~MGAREG_CRTCEXT1_VSYNCOFF;
        crtcext1 &= ~MGAREG_CRTCEXT1_HSYNCOFF;
@@ -662,7 +410,7 @@ static void mgag200_enable_display(struct mga_device *mdev)
 
 static void mgag200_disable_display(struct mga_device *mdev)
 {
-       u8 seq0, seq1, crtcext1;
+       u8 seq0, crtcext1;
 
        RREG_SEQ(0x00, seq0);
        seq0 &= ~MGAREG_SEQ0_SYNCRST;
@@ -675,59 +423,127 @@ static void mgag200_disable_display(struct mga_device *mdev)
        mga_wait_vsync(mdev);
        mga_wait_busy(mdev);
 
-       RREG_SEQ(0x01, seq1);
-       seq1 |= MGAREG_SEQ1_SCROFF;
-       WREG_SEQ(0x01, seq1);
-
-       msleep(20);
-
        RREG_ECRT(0x01, crtcext1);
        crtcext1 |= MGAREG_CRTCEXT1_VSYNCOFF |
                    MGAREG_CRTCEXT1_HSYNCOFF;
        WREG_ECRT(0x01, crtcext1);
 }
 
+static void mgag200_handle_damage(struct mga_device *mdev, const struct iosys_map *vmap,
+                                 struct drm_framebuffer *fb, struct drm_rect *clip)
+{
+       struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram);
+
+       iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
+       drm_fb_memcpy(&dst, fb->pitches, vmap, fb, clip);
+}
+
 /*
- * Connector
+ * Primary plane
  */
 
-static int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
+const uint32_t mgag200_primary_plane_formats[] = {
+       DRM_FORMAT_XRGB8888,
+       DRM_FORMAT_RGB565,
+       DRM_FORMAT_RGB888,
+};
+
+const size_t mgag200_primary_plane_formats_size = ARRAY_SIZE(mgag200_primary_plane_formats);
+
+const uint64_t mgag200_primary_plane_fmtmods[] = {
+       DRM_FORMAT_MOD_LINEAR,
+       DRM_FORMAT_MOD_INVALID
+};
+
+int mgag200_primary_plane_helper_atomic_check(struct drm_plane *plane,
+                                             struct drm_atomic_state *new_state)
 {
-       struct mga_device *mdev = to_mga_device(connector->dev);
+       struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
+       struct drm_framebuffer *new_fb = new_plane_state->fb;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_crtc *new_crtc = new_plane_state->crtc;
+       struct drm_crtc_state *new_crtc_state = NULL;
+       struct mgag200_crtc_state *new_mgag200_crtc_state;
        int ret;
 
-       /*
-        * Protect access to I/O registers from concurrent modesetting
-        * by acquiring the I/O-register lock.
-        */
-       mutex_lock(&mdev->rmmio_lock);
-       ret = drm_connector_helper_get_modes_from_ddc(connector);
-       mutex_unlock(&mdev->rmmio_lock);
+       if (new_crtc)
+               new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc);
 
-       return ret;
+       ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, true);
+       if (ret)
+               return ret;
+       else if (!new_plane_state->visible)
+               return 0;
+
+       if (plane->state)
+               fb = plane->state->fb;
+
+       if (!fb || (fb->format != new_fb->format))
+               new_crtc_state->mode_changed = true; /* update PLL settings */
+
+       new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+       new_mgag200_crtc_state->format = new_fb->format;
+
+       return 0;
 }
 
-static const struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
-       .get_modes  = mgag200_vga_connector_helper_get_modes,
-};
+void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+                                               struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = plane->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       struct drm_plane_state *plane_state = plane->state;
+       struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
+       struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+       struct drm_framebuffer *fb = plane_state->fb;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect damage;
+       u8 seq1;
 
-static const struct drm_connector_funcs mga_vga_connector_funcs = {
-       .reset                  = drm_atomic_helper_connector_reset,
-       .fill_modes             = drm_helper_probe_single_connector_modes,
-       .destroy                = drm_connector_cleanup,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
-};
+       if (!fb)
+               return;
+
+       drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+       drm_atomic_for_each_plane_damage(&iter, &damage) {
+               mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
+       }
+
+       /* Always scanout image at VRAM offset 0 */
+       mgag200_set_startadd(mdev, (u32)0);
+       mgag200_set_offset(mdev, fb);
+
+       if (!old_plane_state->crtc && plane_state->crtc) { // enabling
+               RREG_SEQ(0x01, seq1);
+               seq1 &= ~MGAREG_SEQ1_SCROFF;
+               WREG_SEQ(0x01, seq1);
+               msleep(20);
+       }
+}
+
+void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+                                                struct drm_atomic_state *old_state)
+{
+       struct drm_device *dev = plane->dev;
+       struct mga_device *mdev = to_mga_device(dev);
+       u8 seq1;
+
+       RREG_SEQ(0x01, seq1);
+       seq1 |= MGAREG_SEQ1_SCROFF;
+       WREG_SEQ(0x01, seq1);
+       msleep(20);
+}
 
 /*
- * Simple Display Pipe
+ * CRTC
  */
 
-static enum drm_mode_status
-mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
-                                      const struct drm_display_mode *mode)
+enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+                                                   const struct drm_display_mode *mode)
 {
-       struct mga_device *mdev = to_mga_device(pipe->crtc.dev);
+       struct mga_device *mdev = to_mga_device(crtc->dev);
        const struct mgag200_device_info *info = mdev->info;
 
        /*
@@ -754,167 +570,112 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
        return MODE_OK;
 }
 
-static void
-mgag200_handle_damage(struct mga_device *mdev, struct drm_framebuffer *fb,
-                     struct drm_rect *clip, const struct iosys_map *map)
-{
-       void __iomem *dst = mdev->vram;
-       void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
-
-       dst += drm_fb_clip_offset(fb->pitches[0], fb->format, clip);
-       drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, clip);
-}
-
-static void
-mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
-                                  struct drm_crtc_state *crtc_state,
-                                  struct drm_plane_state *plane_state)
+int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *new_state)
 {
-       struct drm_crtc *crtc = &pipe->crtc;
        struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = to_mga_device(dev);
-       struct mgag200_pll *pixpll = &mdev->pixpll;
-       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
-       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
-       struct drm_framebuffer *fb = plane_state->fb;
-       struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
-       struct drm_rect fullscreen = {
-               .x1 = 0,
-               .x2 = fb->width,
-               .y1 = 0,
-               .y2 = fb->height,
-       };
-
-       /*
-        * Concurrent operations could possibly trigger a call to
-        * drm_connector_helper_funcs.get_modes by trying to read the
-        * display modes. Protect access to I/O registers by acquiring
-        * the I/O-register lock.
-        */
-       mutex_lock(&mdev->rmmio_lock);
-
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_hold_bmc(mdev);
-
-       mgag200_set_format_regs(mdev, fb);
-       mgag200_set_mode_regs(mdev, adjusted_mode);
-
-       pixpll->funcs->update(pixpll, &mgag200_crtc_state->pixpllc);
-
-       if (mdev->type == G200_ER)
-               mgag200_g200er_reset_tagfifo(mdev);
-
-       if (IS_G200_SE(mdev))
-               mgag200_g200se_set_hiprilvl(mdev, adjusted_mode, fb);
-       else if (mdev->type == G200_EV)
-               mgag200_g200ev_set_hiprilvl(mdev);
-
-       if (mdev->type == G200_WB || mdev->type == G200_EW3)
-               mgag200_g200wb_release_bmc(mdev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut;
+       int ret;
 
-       if (crtc_state->gamma_lut)
-               mgag200_crtc_set_gamma(mdev, fb->format, crtc_state->gamma_lut->data);
-       else
-               mgag200_crtc_set_gamma_linear(mdev, fb->format);
+       ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
+       if (ret)
+               return ret;
 
-       mgag200_enable_display(mdev);
+       if (!new_crtc_state->enable)
+               return 0;
 
-       mgag200_handle_damage(mdev, fb, &fullscreen, &shadow_plane_state->data[0]);
+       if (new_crtc_state->mode_changed) {
+               if (funcs->pixpllc_atomic_check) {
+                       ret = funcs->pixpllc_atomic_check(crtc, new_state);
+                       if (ret)
+                               return ret;
+               }
+       }
 
-       /* Always scanout image at VRAM offset 0 */
-       mgag200_set_startadd(mdev, (u32)0);
-       mgag200_set_offset(mdev, fb);
+       if (new_crtc_state->color_mgmt_changed && new_gamma_lut) {
+               if (new_gamma_lut->length != MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
+                       drm_dbg(dev, "Wrong size for gamma_lut %zu\n", new_gamma_lut->length);
+                       return -EINVAL;
+               }
+       }
 
-       mutex_unlock(&mdev->rmmio_lock);
+       return drm_atomic_add_affected_planes(new_state, crtc);
 }
 
-static void
-mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct mga_device *mdev = to_mga_device(crtc->dev);
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+       struct drm_device *dev = crtc->dev;
+       struct mga_device *mdev = to_mga_device(dev);
 
-       mgag200_disable_display(mdev);
+       if (crtc_state->enable && crtc_state->color_mgmt_changed) {
+               const struct drm_format_info *format = mgag200_crtc_state->format;
+
+               if (crtc_state->gamma_lut)
+                       mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
+               else
+                       mgag200_crtc_set_gamma_linear(mdev, format);
+       }
 }
 
-static int
-mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
-                                 struct drm_plane_state *plane_state,
-                                 struct drm_crtc_state *crtc_state)
+void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
-       struct drm_plane *plane = plane_state->plane;
-       struct drm_device *dev = plane->dev;
+       struct drm_device *dev = crtc->dev;
        struct mga_device *mdev = to_mga_device(dev);
-       struct mgag200_pll *pixpll = &mdev->pixpll;
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
+       struct drm_crtc_state *crtc_state = crtc->state;
+       struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
        struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
-       struct drm_framebuffer *new_fb = plane_state->fb;
-       struct drm_framebuffer *fb = NULL;
-       int ret;
+       const struct drm_format_info *format = mgag200_crtc_state->format;
 
-       if (!new_fb)
-               return 0;
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
 
-       if (plane->state)
-               fb = plane->state->fb;
+       mgag200_set_format_regs(mdev, format);
+       mgag200_set_mode_regs(mdev, adjusted_mode);
 
-       if (!fb || (fb->format != new_fb->format))
-               crtc_state->mode_changed = true; /* update PLL settings */
+       if (funcs->pixpllc_atomic_update)
+               funcs->pixpllc_atomic_update(crtc, old_state);
 
-       if (crtc_state->mode_changed) {
-               ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
-                                            &mgag200_crtc_state->pixpllc);
-               if (ret)
-                       return ret;
-       }
+       mgag200_enable_display(mdev);
 
-       if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
-               if (crtc_state->gamma_lut->length !=
-                   MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
-                       drm_err(dev, "Wrong size for gamma_lut %zu\n",
-                               crtc_state->gamma_lut->length);
-                       return -EINVAL;
-               }
-       }
-       return 0;
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
 }
 
-static void
-mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
-                                  struct drm_plane_state *old_state)
+void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
 {
-       struct drm_plane *plane = &pipe->plane;
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct drm_device *dev = plane->dev;
-       struct mga_device *mdev = to_mga_device(dev);
-       struct drm_plane_state *state = plane->state;
-       struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
-       struct drm_framebuffer *fb = state->fb;
-       struct drm_rect damage;
-       struct drm_atomic_helper_damage_iter iter;
+       struct mga_device *mdev = to_mga_device(crtc->dev);
+       const struct mgag200_device_funcs *funcs = mdev->funcs;
 
-       if (!fb)
-               return;
+       if (funcs->disable_vidrst)
+               funcs->disable_vidrst(mdev);
 
-       mutex_lock(&mdev->rmmio_lock);
+       mgag200_disable_display(mdev);
 
-       if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
-               mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data);
+       if (funcs->enable_vidrst)
+               funcs->enable_vidrst(mdev);
+}
 
-       drm_atomic_helper_damage_iter_init(&iter, old_state, state);
-       drm_atomic_for_each_plane_damage(&iter, &damage) {
-               mgag200_handle_damage(mdev, fb, &damage, &shadow_plane_state->data[0]);
-       }
-       /* Always scanout image at VRAM offset 0 */
-       mgag200_set_startadd(mdev, (u32)0);
-       mgag200_set_offset(mdev, fb);
+void mgag200_crtc_reset(struct drm_crtc *crtc)
+{
+       struct mgag200_crtc_state *mgag200_crtc_state;
 
-       mutex_unlock(&mdev->rmmio_lock);
+       if (crtc->state)
+               crtc->funcs->atomic_destroy_state(crtc, crtc->state);
+
+       mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
+       if (mgag200_crtc_state)
+               __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
+       else
+               __drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
-static struct drm_crtc_state *
-mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe)
+struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 {
-       struct drm_crtc *crtc = &pipe->crtc;
        struct drm_crtc_state *crtc_state = crtc->state;
        struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
        struct mgag200_crtc_state *new_mgag200_crtc_state;
@@ -927,14 +688,14 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe
                return NULL;
        __drm_atomic_helper_crtc_duplicate_state(crtc, &new_mgag200_crtc_state->base);
 
+       new_mgag200_crtc_state->format = mgag200_crtc_state->format;
        memcpy(&new_mgag200_crtc_state->pixpllc, &mgag200_crtc_state->pixpllc,
               sizeof(new_mgag200_crtc_state->pixpllc));
 
        return &new_mgag200_crtc_state->base;
 }
 
-static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe,
-                                                          struct drm_crtc_state *crtc_state)
+void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
 {
        struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
 
@@ -942,50 +703,49 @@ static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_dis
        kfree(mgag200_crtc_state);
 }
 
-static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe)
+/*
+ * Connector
+ */
+
+int mgag200_vga_connector_helper_get_modes(struct drm_connector *connector)
 {
-       struct drm_crtc *crtc = &pipe->crtc;
-       struct mgag200_crtc_state *mgag200_crtc_state;
+       struct mga_device *mdev = to_mga_device(connector->dev);
+       int ret;
 
-       if (crtc->state) {
-               mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state);
-               crtc->state = NULL; /* must be set to NULL here */
-       }
+       /*
+        * Protect access to I/O registers from concurrent modesetting
+        * by acquiring the I/O-register lock.
+        */
+       mutex_lock(&mdev->rmmio_lock);
+       ret = drm_connector_helper_get_modes_from_ddc(connector);
+       mutex_unlock(&mdev->rmmio_lock);
 
-       mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
-       if (!mgag200_crtc_state)
-               return;
-       __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
+       return ret;
 }
 
-static const struct drm_simple_display_pipe_funcs
-mgag200_simple_display_pipe_funcs = {
-       .mode_valid = mgag200_simple_display_pipe_mode_valid,
-       .enable     = mgag200_simple_display_pipe_enable,
-       .disable    = mgag200_simple_display_pipe_disable,
-       .check      = mgag200_simple_display_pipe_check,
-       .update     = mgag200_simple_display_pipe_update,
-       .reset_crtc = mgag200_simple_display_pipe_reset_crtc,
-       .duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state,
-       .destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state,
-       DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
-};
-
-static const uint32_t mgag200_simple_display_pipe_formats[] = {
-       DRM_FORMAT_XRGB8888,
-       DRM_FORMAT_RGB565,
-       DRM_FORMAT_RGB888,
-};
-
-static const uint64_t mgag200_simple_display_pipe_fmtmods[] = {
-       DRM_FORMAT_MOD_LINEAR,
-       DRM_FORMAT_MOD_INVALID
-};
-
 /*
  * Mode config
  */
 
+static void mgag200_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
+{
+       struct mga_device *mdev = to_mga_device(state->dev);
+
+       /*
+        * Concurrent operations could possibly trigger a call to
+        * drm_connector_helper_funcs.get_modes by trying to read the
+        * display modes. Protect access to I/O registers by acquiring
+        * the I/O-register lock.
+        */
+       mutex_lock(&mdev->rmmio_lock);
+       drm_atomic_helper_commit_tail(state);
+       mutex_unlock(&mdev->rmmio_lock);
+}
+
+static const struct drm_mode_config_helper_funcs mgag200_mode_config_helper_funcs = {
+       .atomic_commit_tail = mgag200_mode_config_helper_atomic_commit_tail,
+};
+
 /* Calculates a mode's required memory bandwidth (in KiB/sec). */
 static uint32_t mgag200_calculate_mode_bandwidth(const struct drm_display_mode *mode,
                                                 unsigned int bits_per_pixel)
@@ -1048,23 +808,16 @@ static const struct drm_mode_config_funcs mgag200_mode_config_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
-int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available)
+int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available)
 {
        struct drm_device *dev = &mdev->base;
-       struct mga_i2c_chan *i2c = &mdev->i2c;
-       struct drm_connector *connector = &mdev->connector;
-       struct drm_simple_display_pipe *pipe = &mdev->display_pipe;
-       size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
        int ret;
 
-       mgag200_init_regs(mdev);
-
        mdev->vram_available = vram_available;
 
        ret = drmm_mode_config_init(dev);
        if (ret) {
-               drm_err(dev, "drmm_mode_config_init() failed, error %d\n",
-                       ret);
+               drm_err(dev, "drmm_mode_config_init() failed: %d\n", ret);
                return ret;
        }
 
@@ -1073,48 +826,7 @@ int mgag200_modeset_init(struct mga_device *mdev, resource_size_t vram_available
        dev->mode_config.preferred_depth = 24;
        dev->mode_config.fb_base = mdev->vram_res->start;
        dev->mode_config.funcs = &mgag200_mode_config_funcs;
-
-       ret = mgag200_i2c_init(mdev, i2c);
-       if (ret) {
-               drm_err(dev, "failed to add DDC bus: %d\n", ret);
-               return ret;
-       }
-
-       ret = drm_connector_init_with_ddc(dev, connector,
-                                         &mga_vga_connector_funcs,
-                                         DRM_MODE_CONNECTOR_VGA,
-                                         &i2c->adapter);
-       if (ret) {
-               drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
-               return ret;
-       }
-       drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
-
-       ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
-       if (ret)
-               return ret;
-
-       ret = drm_simple_display_pipe_init(dev, pipe,
-                                          &mgag200_simple_display_pipe_funcs,
-                                          mgag200_simple_display_pipe_formats,
-                                          format_count,
-                                          mgag200_simple_display_pipe_fmtmods,
-                                          connector);
-       if (ret) {
-               drm_err(dev,
-                       "drm_simple_display_pipe_init() failed, error %d\n",
-                       ret);
-               return ret;
-       }
-
-       drm_plane_enable_fb_damage_clips(&pipe->plane);
-
-       /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
-       drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE);
-
-       drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE);
-
-       drm_mode_config_reset(dev);
+       dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;
 
        return 0;
 }
diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
deleted file mode 100644 (file)
index 8065ca5..0000000
+++ /dev/null
@@ -1,997 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-#include <linux/delay.h>
-
-#include "mgag200_drv.h"
-
-/*
- * G200
- */
-
-static int mgag200_pixpll_compute_g200(struct mgag200_pll *pixpll, long clock,
-                                      struct mgag200_pll_values *pixpllc)
-{
-       struct mga_device *mdev = pixpll->mdev;
-       struct drm_device *dev = &mdev->base;
-       struct mgag200_g200_device *g200 = to_mgag200_g200_device(dev);
-       const int post_div_max = 7;
-       const int in_div_min = 1;
-       const int in_div_max = 6;
-       const int feed_div_min = 7;
-       const int feed_div_max = 127;
-       u8 testp, testm, testn;
-       u8 n = 0, m = 0, p, s;
-       long f_vco;
-       long computed;
-       long delta, tmp_delta;
-       long ref_clk = g200->ref_clk;
-       long p_clk_min = g200->pclk_min;
-       long p_clk_max = g200->pclk_max;
-
-       if (clock > p_clk_max) {
-               drm_err(dev, "Pixel Clock %ld too high\n", clock);
-               return -EINVAL;
-       }
-
-       if (clock < p_clk_min >> 3)
-               clock = p_clk_min >> 3;
-
-       f_vco = clock;
-       for (testp = 0;
-            testp <= post_div_max && f_vco < p_clk_min;
-            testp = (testp << 1) + 1, f_vco <<= 1)
-               ;
-       p = testp + 1;
-
-       delta = clock;
-
-       for (testm = in_div_min; testm <= in_div_max; testm++) {
-               for (testn = feed_div_min; testn <= feed_div_max; testn++) {
-                       computed = ref_clk * (testn + 1) / (testm + 1);
-                       if (computed < f_vco)
-                               tmp_delta = f_vco - computed;
-                       else
-                               tmp_delta = computed - f_vco;
-                       if (tmp_delta < delta) {
-                               delta = tmp_delta;
-                               m = testm + 1;
-                               n = testn + 1;
-                       }
-               }
-       }
-       f_vco = ref_clk * n / m;
-       if (f_vco < 100000)
-               s = 0;
-       else if (f_vco < 140000)
-               s = 1;
-       else if (f_vco < 180000)
-               s = 2;
-       else
-               s = 3;
-
-       drm_dbg_kms(dev, "clock: %ld vco: %ld m: %d n: %d p: %d s: %d\n",
-                   clock, f_vco, m, n, p, s);
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void
-mgag200_pixpll_update_g200(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-       struct mga_device *mdev = pixpll->mdev;
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = pixpllcm;
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200 = {
-       .compute = mgag200_pixpll_compute_g200,
-       .update = mgag200_pixpll_update_g200,
-};
-
-/*
- * G200SE
- */
-
-static int mgag200_pixpll_compute_g200se_00(struct mgag200_pll *pixpll, long clock,
-                                           struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 320000;
-       static const unsigned int vcomin = 160000;
-       static const unsigned int pllreffreq = 25000;
-
-       unsigned int delta, tmpdelta, permitteddelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-       permitteddelta = clock * 5 / 1000;
-
-       for (testp = 8; testp > 0; testp /= 2) {
-               if (clock * testp > vcomax)
-                       continue;
-               if (clock * testp < vcomin)
-                       continue;
-
-               for (testn = 17; testn < 256; testn++) {
-                       for (testm = 1; testm < 32; testm++) {
-                               computed = (pllreffreq * testn) / (testm * testp);
-                               if (computed > clock)
-                                       tmpdelta = computed - clock;
-                               else
-                                       tmpdelta = clock - computed;
-                               if (tmpdelta < delta) {
-                                       delta = tmpdelta;
-                                       m = testm;
-                                       n = testn;
-                                       p = testp;
-                               }
-                       }
-               }
-       }
-
-       if (delta > permitteddelta) {
-               pr_warn("PLL delta too large\n");
-               return -EINVAL;
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void mgag200_pixpll_update_g200se_00(struct mgag200_pll *pixpll,
-                                           const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp;
-       struct mga_device *mdev = pixpll->mdev;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-}
-
-static int mgag200_pixpll_compute_g200se_04(struct mgag200_pll *pixpll, long clock,
-                                           struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 1600000;
-       static const unsigned int vcomin = 800000;
-       static const unsigned int pllreffreq = 25000;
-       static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};
-
-       unsigned int delta, tmpdelta, permitteddelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-       unsigned int fvv;
-       unsigned int i;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       if (clock < 25000)
-               clock = 25000;
-       clock = clock * 2;
-
-       /* Permited delta is 0.5% as VESA Specification */
-       permitteddelta = clock * 5 / 1000;
-
-       for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
-               testp = pvalues_e4[i];
-
-               if ((clock * testp) > vcomax)
-                       continue;
-               if ((clock * testp) < vcomin)
-                       continue;
-
-               for (testn = 50; testn <= 256; testn++) {
-                       for (testm = 1; testm <= 32; testm++) {
-                               computed = (pllreffreq * testn) / (testm * testp);
-                               if (computed > clock)
-                                       tmpdelta = computed - clock;
-                               else
-                                       tmpdelta = clock - computed;
-
-                               if (tmpdelta < delta) {
-                                       delta = tmpdelta;
-                                       m = testm;
-                                       n = testn;
-                                       p = testp;
-                               }
-                       }
-               }
-       }
-
-       fvv = pllreffreq * n / m;
-       fvv = (fvv - 800000) / 50000;
-       if (fvv > 15)
-               fvv = 15;
-       s = fvv << 1;
-
-       if (delta > permitteddelta) {
-               pr_warn("PLL delta too large\n");
-               return -EINVAL;
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll,
-                                           const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp;
-       struct mga_device *mdev = pixpll->mdev;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
-       WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
-       WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
-
-       WREG_DAC(0x1a, 0x09);
-       msleep(20);
-       WREG_DAC(0x1a, 0x01);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_00 = {
-       .compute = mgag200_pixpll_compute_g200se_00,
-       .update = mgag200_pixpll_update_g200se_00,
-};
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200se_04 = {
-       .compute = mgag200_pixpll_compute_g200se_04,
-       .update = mgag200_pixpll_update_g200se_04,
-};
-
-/*
- * G200WB
- */
-
-static int mgag200_pixpll_compute_g200wb(struct mgag200_pll *pixpll, long clock,
-                                        struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 550000;
-       static const unsigned int vcomin = 150000;
-       static const unsigned int pllreffreq = 48000;
-
-       unsigned int delta, tmpdelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       for (testp = 1; testp < 9; testp++) {
-               if (clock * testp > vcomax)
-                       continue;
-               if (clock * testp < vcomin)
-                       continue;
-
-               for (testm = 1; testm < 17; testm++) {
-                       for (testn = 1; testn < 151; testn++) {
-                               computed = (pllreffreq * testn) / (testm * testp);
-                               if (computed > clock)
-                                       tmpdelta = computed - clock;
-                               else
-                                       tmpdelta = clock - computed;
-                               if (tmpdelta < delta) {
-                                       delta = tmpdelta;
-                                       n = testn;
-                                       m = testm;
-                                       p = testp;
-                                       s = 0;
-                               }
-                       }
-               }
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void
-mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-       int i, j, tmpcount, vcount;
-       struct mga_device *mdev = pixpll->mdev;
-       bool pll_locked = false;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
-       xpixpllcn = pixpllcn;
-       xpixpllcp = ((pixpllcn & GENMASK(10, 9)) >> 3) | (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       for (i = 0; i <= 32 && pll_locked == false; i++) {
-               if (i > 0) {
-                       WREG8(MGAREG_CRTC_INDEX, 0x1e);
-                       tmp = RREG8(MGAREG_CRTC_DATA);
-                       if (tmp < 0xff)
-                               WREG8(MGAREG_CRTC_DATA, tmp+1);
-               }
-
-               /* set pixclkdis to 1 */
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG8(DAC_DATA, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= MGA1064_REMHEADCTL_CLKDIS;
-               WREG8(DAC_DATA, tmp);
-
-               /* select PLL Set C */
-               tmp = RREG8(MGAREG_MEM_MISC_READ);
-               tmp |= 0x3 << 2;
-               WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
-               WREG8(DAC_DATA, tmp);
-
-               udelay(500);
-
-               /* reset the PLL */
-               WREG8(DAC_INDEX, MGA1064_VREF_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~0x04;
-               WREG8(DAC_DATA, tmp);
-
-               udelay(50);
-
-               /* program pixel pll register */
-               WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
-               WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
-               WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
-
-               udelay(50);
-
-               /* turn pll on */
-               WREG8(DAC_INDEX, MGA1064_VREF_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= 0x04;
-               WREG_DAC(MGA1064_VREF_CTL, tmp);
-
-               udelay(500);
-
-               /* select the pixel pll */
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-               tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-               WREG8(DAC_DATA, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
-               tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
-               WREG8(DAC_DATA, tmp);
-
-               /* reset dotclock rate bit */
-               WREG8(MGAREG_SEQ_INDEX, 1);
-               tmp = RREG8(MGAREG_SEQ_DATA);
-               tmp &= ~0x8;
-               WREG8(MGAREG_SEQ_DATA, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG8(DAC_DATA, tmp);
-
-               vcount = RREG8(MGAREG_VCOUNT);
-
-               for (j = 0; j < 30 && pll_locked == false; j++) {
-                       tmpcount = RREG8(MGAREG_VCOUNT);
-                       if (tmpcount < vcount)
-                               vcount = 0;
-                       if ((tmpcount - vcount) > 2)
-                               pll_locked = true;
-                       else
-                               udelay(5);
-               }
-       }
-
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
-       WREG_DAC(MGA1064_REMHEADCTL, tmp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200wb = {
-       .compute = mgag200_pixpll_compute_g200wb,
-       .update = mgag200_pixpll_update_g200wb,
-};
-
-/*
- * G200EV
- */
-
-static int mgag200_pixpll_compute_g200ev(struct mgag200_pll *pixpll, long clock,
-                                        struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 550000;
-       static const unsigned int vcomin = 150000;
-       static const unsigned int pllreffreq = 50000;
-
-       unsigned int delta, tmpdelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       for (testp = 16; testp > 0; testp--) {
-               if (clock * testp > vcomax)
-                       continue;
-               if (clock * testp < vcomin)
-                       continue;
-
-               for (testn = 1; testn < 257; testn++) {
-                       for (testm = 1; testm < 17; testm++) {
-                               computed = (pllreffreq * testn) /
-                                       (testm * testp);
-                               if (computed > clock)
-                                       tmpdelta = computed - clock;
-                               else
-                                       tmpdelta = clock - computed;
-                               if (tmpdelta < delta) {
-                                       delta = tmpdelta;
-                                       n = testn;
-                                       m = testm;
-                                       p = testp;
-                               }
-                       }
-               }
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void
-mgag200_pixpll_update_g200ev(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-       struct mga_device *mdev = pixpll->mdev;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = pixpllcm;
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG8(DAC_DATA, tmp);
-
-       tmp = RREG8(MGAREG_MEM_MISC_READ);
-       tmp |= 0x3 << 2;
-       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
-       tmp = RREG8(DAC_DATA);
-       WREG8(DAC_DATA, tmp & ~0x40);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG8(DAC_DATA, tmp);
-
-       WREG_DAC(MGA1064_EV_PIX_PLLC_M, xpixpllcm);
-       WREG_DAC(MGA1064_EV_PIX_PLLC_N, xpixpllcn);
-       WREG_DAC(MGA1064_EV_PIX_PLLC_P, xpixpllcp);
-
-       udelay(50);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG8(DAC_DATA, tmp);
-
-       udelay(500);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-       tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-       WREG8(DAC_DATA, tmp);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
-       tmp = RREG8(DAC_DATA);
-       WREG8(DAC_DATA, tmp | 0x40);
-
-       tmp = RREG8(MGAREG_MEM_MISC_READ);
-       tmp |= (0x3 << 2);
-       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG8(DAC_DATA, tmp);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ev = {
-       .compute = mgag200_pixpll_compute_g200ev,
-       .update = mgag200_pixpll_update_g200ev,
-};
-
-/*
- * G200EH
- */
-
-static int mgag200_pixpll_compute_g200eh(struct mgag200_pll *pixpll, long clock,
-                                        struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 800000;
-       static const unsigned int vcomin = 400000;
-       static const unsigned int pllreffreq = 33333;
-
-       unsigned int delta, tmpdelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       for (testp = 16; testp > 0; testp >>= 1) {
-               if (clock * testp > vcomax)
-                       continue;
-               if (clock * testp < vcomin)
-                       continue;
-
-               for (testm = 1; testm < 33; testm++) {
-                       for (testn = 17; testn < 257; testn++) {
-                               computed = (pllreffreq * testn) / (testm * testp);
-                               if (computed > clock)
-                                       tmpdelta = computed - clock;
-                               else
-                                       tmpdelta = clock - computed;
-                               if (tmpdelta < delta) {
-                                       delta = tmpdelta;
-                                       n = testn;
-                                       m = testm;
-                                       p = testp;
-                               }
-                       }
-               }
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void
-mgag200_pixpll_update_g200eh(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-       int i, j, tmpcount, vcount;
-       struct mga_device *mdev = pixpll->mdev;
-       bool pll_locked = false;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = ((pixpllcn & BIT(8)) >> 1) | pixpllcm;
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       for (i = 0; i <= 32 && pll_locked == false; i++) {
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-               WREG8(DAC_DATA, tmp);
-
-               tmp = RREG8(MGAREG_MEM_MISC_READ);
-               tmp |= 0x3 << 2;
-               WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-               WREG8(DAC_DATA, tmp);
-
-               udelay(500);
-
-               WREG_DAC(MGA1064_EH_PIX_PLLC_M, xpixpllcm);
-               WREG_DAC(MGA1064_EH_PIX_PLLC_N, xpixpllcn);
-               WREG_DAC(MGA1064_EH_PIX_PLLC_P, xpixpllcp);
-
-               udelay(500);
-
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
-               tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
-               WREG8(DAC_DATA, tmp);
-
-               WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-               tmp = RREG8(DAC_DATA);
-               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-               tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-               WREG8(DAC_DATA, tmp);
-
-               vcount = RREG8(MGAREG_VCOUNT);
-
-               for (j = 0; j < 30 && pll_locked == false; j++) {
-                       tmpcount = RREG8(MGAREG_VCOUNT);
-                       if (tmpcount < vcount)
-                               vcount = 0;
-                       if ((tmpcount - vcount) > 2)
-                               pll_locked = true;
-                       else
-                               udelay(5);
-               }
-       }
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh = {
-       .compute = mgag200_pixpll_compute_g200eh,
-       .update = mgag200_pixpll_update_g200eh,
-};
-
-/*
- * G200EH3
- */
-
-static int mgag200_pixpll_compute_g200eh3(struct mgag200_pll *pixpll, long clock,
-                                         struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 3000000;
-       static const unsigned int vcomin = 1500000;
-       static const unsigned int pllreffreq = 25000;
-
-       unsigned int delta, tmpdelta;
-       unsigned int testp, testm, testn;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-       testp = 0;
-
-       for (testm = 150; testm >= 6; testm--) {
-               if (clock * testm > vcomax)
-                       continue;
-               if (clock * testm < vcomin)
-                       continue;
-               for (testn = 120; testn >= 60; testn--) {
-                       computed = (pllreffreq * testn) / testm;
-                       if (computed > clock)
-                               tmpdelta = computed - clock;
-                       else
-                               tmpdelta = clock - computed;
-                       if (tmpdelta < delta) {
-                               delta = tmpdelta;
-                               n = testn + 1;
-                               m = testm + 1;
-                               p = testp + 1;
-                       }
-                       if (delta == 0)
-                               break;
-               }
-               if (delta == 0)
-                       break;
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200eh3 = {
-       .compute = mgag200_pixpll_compute_g200eh3,
-       .update = mgag200_pixpll_update_g200eh, // same as G200EH
-};
-
-/*
- * G200ER
- */
-
-static int mgag200_pixpll_compute_g200er(struct mgag200_pll *pixpll, long clock,
-                                        struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 1488000;
-       static const unsigned int vcomin = 1056000;
-       static const unsigned int pllreffreq = 48000;
-       static const unsigned int m_div_val[] = { 1, 2, 4, 8 };
-
-       unsigned int delta, tmpdelta;
-       int testr, testn, testm, testo;
-       unsigned int p, m, n, s;
-       unsigned int computed, vco;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       for (testr = 0; testr < 4; testr++) {
-               if (delta == 0)
-                       break;
-               for (testn = 5; testn < 129; testn++) {
-                       if (delta == 0)
-                               break;
-                       for (testm = 3; testm >= 0; testm--) {
-                               if (delta == 0)
-                                       break;
-                               for (testo = 5; testo < 33; testo++) {
-                                       vco = pllreffreq * (testn + 1) /
-                                               (testr + 1);
-                                       if (vco < vcomin)
-                                               continue;
-                                       if (vco > vcomax)
-                                               continue;
-                                       computed = vco / (m_div_val[testm] * (testo + 1));
-                                       if (computed > clock)
-                                               tmpdelta = computed - clock;
-                                       else
-                                               tmpdelta = clock - computed;
-                                       if (tmpdelta < delta) {
-                                               delta = tmpdelta;
-                                               m = (testm | (testo << 3)) + 1;
-                                               n = testn + 1;
-                                               p = testr + 1;
-                                               s = testr;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static void
-mgag200_pixpll_update_g200er(struct mgag200_pll *pixpll, const struct mgag200_pll_values *pixpllc)
-{
-       unsigned int pixpllcm, pixpllcn, pixpllcp, pixpllcs;
-       u8 xpixpllcm, xpixpllcn, xpixpllcp, tmp;
-       struct mga_device *mdev = pixpll->mdev;
-
-       pixpllcm = pixpllc->m - 1;
-       pixpllcn = pixpllc->n - 1;
-       pixpllcp = pixpllc->p - 1;
-       pixpllcs = pixpllc->s;
-
-       xpixpllcm = pixpllcm;
-       xpixpllcn = pixpllcn;
-       xpixpllcp = (pixpllcs << 3) | pixpllcp;
-
-       WREG_MISC_MASKED(MGAREG_MISC_CLKSEL_MGA, MGAREG_MISC_CLKSEL_MASK);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
-       WREG8(DAC_DATA, tmp);
-
-       WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
-       tmp = RREG8(DAC_DATA);
-       tmp |= MGA1064_REMHEADCTL_CLKDIS;
-       WREG8(DAC_DATA, tmp);
-
-       tmp = RREG8(MGAREG_MEM_MISC_READ);
-       tmp |= (0x3<<2) | 0xc0;
-       WREG8(MGAREG_MEM_MISC_WRITE, tmp);
-
-       WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
-       tmp = RREG8(DAC_DATA);
-       tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
-       tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
-       WREG8(DAC_DATA, tmp);
-
-       udelay(500);
-
-       WREG_DAC(MGA1064_ER_PIX_PLLC_N, xpixpllcn);
-       WREG_DAC(MGA1064_ER_PIX_PLLC_M, xpixpllcm);
-       WREG_DAC(MGA1064_ER_PIX_PLLC_P, xpixpllcp);
-
-       udelay(50);
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200er = {
-       .compute = mgag200_pixpll_compute_g200er,
-       .update = mgag200_pixpll_update_g200er,
-};
-
-/*
- * G200EW3
- */
-
-static int mgag200_pixpll_compute_g200ew3(struct mgag200_pll *pixpll, long clock,
-                                         struct mgag200_pll_values *pixpllc)
-{
-       static const unsigned int vcomax = 800000;
-       static const unsigned int vcomin = 400000;
-       static const unsigned int pllreffreq = 25000;
-
-       unsigned int delta, tmpdelta;
-       unsigned int testp, testm, testn, testp2;
-       unsigned int p, m, n, s;
-       unsigned int computed;
-
-       m = n = p = s = 0;
-       delta = 0xffffffff;
-
-       for (testp = 1; testp < 8; testp++) {
-               for (testp2 = 1; testp2 < 8; testp2++) {
-                       if (testp < testp2)
-                               continue;
-                       if ((clock * testp * testp2) > vcomax)
-                               continue;
-                       if ((clock * testp * testp2) < vcomin)
-                               continue;
-                       for (testm = 1; testm < 26; testm++) {
-                               for (testn = 32; testn < 2048 ; testn++) {
-                                       computed = (pllreffreq * testn) / (testm * testp * testp2);
-                                       if (computed > clock)
-                                               tmpdelta = computed - clock;
-                                       else
-                                               tmpdelta = clock - computed;
-                                       if (tmpdelta < delta) {
-                                               delta = tmpdelta;
-                                               m = testm + 1;
-                                               n = testn + 1;
-                                               p = testp + 1;
-                                               s = testp2;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       pixpllc->m = m;
-       pixpllc->n = n;
-       pixpllc->p = p;
-       pixpllc->s = s;
-
-       return 0;
-}
-
-static const struct mgag200_pll_funcs mgag200_pixpll_funcs_g200ew3 = {
-       .compute = mgag200_pixpll_compute_g200ew3,
-       .update = mgag200_pixpll_update_g200wb, // same as G200WB
-};
-
-/*
- * PLL initialization
- */
-
-int mgag200_pixpll_init(struct mgag200_pll *pixpll, struct mga_device *mdev)
-{
-       struct drm_device *dev = &mdev->base;
-       struct mgag200_g200se_device *g200se;
-
-       pixpll->mdev = mdev;
-
-       switch (mdev->type) {
-       case G200_PCI:
-       case G200_AGP:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200;
-               break;
-       case G200_SE_A:
-       case G200_SE_B:
-               g200se = to_mgag200_g200se_device(dev);
-
-               if (g200se->unique_rev_id >= 0x04)
-                       pixpll->funcs = &mgag200_pixpll_funcs_g200se_04;
-               else
-                       pixpll->funcs = &mgag200_pixpll_funcs_g200se_00;
-               break;
-       case G200_WB:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200wb;
-               break;
-       case G200_EV:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200ev;
-               break;
-       case G200_EH:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200eh;
-               break;
-       case G200_EH3:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200eh3;
-               break;
-       case G200_ER:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200er;
-               break;
-       case G200_EW3:
-               pixpll->funcs = &mgag200_pixpll_funcs_g200ew3;
-               break;
-       default:
-               drm_err(dev, "unknown device type %d\n", mdev->type);
-               return -ENODEV;
-       }
-
-       return 0;
-}
index 99a9ab7d911908de608282d8bd186305bff28f69..1019ffd6c2601bae3eb979f13b11d252178314a2 100644 (file)
@@ -96,7 +96,7 @@
 #define MGAREG_SRCORG          0x2cb4
 #define MGAREG_DSTORG          0x2cb8
 
-/* add or or this to one of the previous "power registers" to start
+/* add or this to one of the previous "power registers" to start
    the drawing engine */
 
 #define MGAREG_EXEC            0x0100
index 1ed4cd09dbf8bf82b4c2e9f6a385f9c54fe56057..1d0bafedd585050d2ed44a0f3c052222e1b24f90 100644 (file)
@@ -355,7 +355,7 @@ static int msm_init_vram(struct drm_device *dev)
                DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start);
 
                /* if we have no IOMMU, then we need to use carveout allocator.
-                * Grab the entire CMA chunk carved out in early startup in
+                * Grab the entire DMA chunk carved out in early startup in
                 * mach-msm:
                 */
        } else if (!msm_use_mmu(dev)) {
index b3689a2d27d72af1dfb138a1ace03638c62b96c8..7d5fb0fc22ddd8ba99bb0c5366f90469bc547364 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/display/drm_dsc.h>
index 873551b4552f5023322b0b8c8819a323004dc3a9..116f8168bda4ab1b5ec57d0db876fafa5dc7bf13 100644 (file)
@@ -10,7 +10,7 @@ config DRM_MXSFB
        depends on COMMON_CLK
        select DRM_MXS
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_PANEL
        select DRM_PANEL_BRIDGE
        help
@@ -26,7 +26,7 @@ config DRM_IMX_LCDIF
        depends on COMMON_CLK
        select DRM_MXS
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_PANEL
        select DRM_PANEL_BRIDGE
        help
index befad33dcb959d0d8dc4abfc468d86f39af2d525..05db135800db09f95faa19351424e16dee7898e9 100644 (file)
@@ -20,7 +20,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drm_module.h>
@@ -199,11 +199,11 @@ static void lcdif_unload(struct drm_device *drm)
        drm->dev_private = NULL;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver lcdif_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops   = &fops,
        .name   = "imx-lcdif",
        .desc   = "i.MX LCDIF Controller DRM",
index 1bec1279c8b567c6aebd344f5b62dfd52fc40a3b..c7efc0d27f0e34fecd933766a4c8a19a3933b98b 100644 (file)
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "lcdif_drv.h"
@@ -297,7 +296,7 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
        lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format);
 
        /* Write cur_buf as well to avoid an initial corrupt frame */
-       paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
+       paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
        if (paddr) {
                writel(lower_32_bits(paddr),
                       lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4);
@@ -393,8 +392,8 @@ static int lcdif_plane_atomic_check(struct drm_plane *plane,
                                                   &lcdif->crtc);
 
        return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   false, true);
 }
 
@@ -406,7 +405,7 @@ static void lcdif_plane_primary_atomic_update(struct drm_plane *plane,
                                                                            plane);
        dma_addr_t paddr;
 
-       paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
+       paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
        if (paddr) {
                writel(lower_32_bits(paddr),
                       lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4);
index 55aad92e08ba14b72c18ecb2a2321b9e07a669e3..b29b332ed38149c3b50459055275156c21239904 100644 (file)
@@ -22,7 +22,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mode_config.h>
 #include <drm/drm_module.h>
@@ -324,11 +324,11 @@ static void mxsfb_unload(struct drm_device *drm)
        pm_runtime_disable(drm->dev);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver mxsfb_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops   = &fops,
        .name   = "mxsfb-drm",
        .desc   = "MXSFB Controller DRM",
index e38ce5737a5fb57456ee03d7124a672216bc79c4..3bcc9c0f20193e276438af51653b6146585228cf 100644 (file)
 #include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_encoder.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "mxsfb_drv.h"
@@ -353,7 +352,7 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
        struct drm_bridge_state *bridge_state = NULL;
        struct drm_device *drm = mxsfb->drm;
        u32 bus_format = 0;
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
 
        pm_runtime_get_sync(drm->dev);
        mxsfb_enable_axi_clk(mxsfb);
@@ -389,10 +388,10 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
        mxsfb_crtc_mode_set_nofb(mxsfb, bridge_state, bus_format);
 
        /* Write cur_buf as well to avoid an initial corrupt frame */
-       paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
-       if (paddr) {
-               writel(paddr, mxsfb->base + mxsfb->devdata->cur_buf);
-               writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+       dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
+       if (dma_addr) {
+               writel(dma_addr, mxsfb->base + mxsfb->devdata->cur_buf);
+               writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf);
        }
 
        mxsfb_enable_controller(mxsfb);
@@ -531,8 +530,8 @@ static int mxsfb_plane_atomic_check(struct drm_plane *plane,
                                                   &mxsfb->crtc);
 
        return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   false, true);
 }
 
@@ -542,11 +541,11 @@ static void mxsfb_plane_primary_atomic_update(struct drm_plane *plane,
        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
        struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
                                                                            plane);
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
 
-       paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
-       if (paddr)
-               writel(paddr, mxsfb->base + mxsfb->devdata->next_buf);
+       dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
+       if (dma_addr)
+               writel(dma_addr, mxsfb->base + mxsfb->devdata->next_buf);
 }
 
 static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
@@ -557,11 +556,11 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
        struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(plane->dev);
        struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
                                                                            plane);
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        u32 ctrl;
 
-       paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
-       if (!paddr) {
+       dma_addr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
+       if (!dma_addr) {
                writel(0, mxsfb->base + LCDC_AS_CTRL);
                return;
        }
@@ -572,16 +571,16 @@ static void mxsfb_plane_overlay_atomic_update(struct drm_plane *plane,
         * is understood, live with the 16 initial invalid pixels on the first
         * line and start 64 bytes within the framebuffer.
         */
-       paddr += 64;
+       dma_addr += 64;
 
-       writel(paddr, mxsfb->base + LCDC_AS_NEXT_BUF);
+       writel(dma_addr, mxsfb->base + LCDC_AS_NEXT_BUF);
 
        /*
         * If the plane was previously disabled, write LCDC_AS_BUF as well to
         * provide the first buffer.
         */
        if (!old_pstate->fb)
-               writel(paddr, mxsfb->base + LCDC_AS_BUF);
+               writel(dma_addr, mxsfb->base + LCDC_AS_BUF);
 
        ctrl = AS_CTRL_AS_ENABLE | AS_CTRL_ALPHA(255);
 
index f9e962fd94d0d31f01d342fd7c44ad11d60ac95f..660c4cbc0b3d97edcfacde8cbc2d311e72b047ab 100644 (file)
@@ -1275,6 +1275,12 @@ static const uint32_t modeset_formats[] = {
         DRM_FORMAT_XRGB1555,
 };
 
+static const struct drm_plane_funcs nv04_primary_plane_funcs = {
+       .update_plane = drm_plane_helper_update_primary,
+       .disable_plane = drm_plane_helper_disable_primary,
+       .destroy = drm_plane_helper_destroy,
+};
+
 static struct drm_plane *
 create_primary_plane(struct drm_device *dev)
 {
@@ -1289,7 +1295,7 @@ create_primary_plane(struct drm_device *dev)
 
         /* possible_crtc's will be filled in later by crtc_init */
         ret = drm_universal_plane_init(dev, primary, 0,
-                                       &drm_primary_helper_funcs,
+                                      &nv04_primary_plane_funcs,
                                        modeset_formats,
                                        ARRAY_SIZE(modeset_formats), NULL,
                                        DRM_PLANE_TYPE_PRIMARY, NULL);
index cad5a646983af8c6403d8c07099adaf0b30f53e9..70c62b8612769ffe42c8aef19cc32f420326074f 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "nouveau_bo.h"
 
@@ -237,8 +236,8 @@ base507c_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
        int ret;
 
        ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  false, true);
        if (ret)
                return ret;
index cd2c79e4b7af2b94c6a535f164794d857b13c0e3..78ee32da01c8adee5e4f8718b40a24d596c5b836 100644 (file)
@@ -29,7 +29,6 @@
 #include <nvhw/class/cl507a.h>
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 bool
 curs507a_space(struct nv50_wndw *wndw)
@@ -103,8 +102,8 @@ curs507a_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
        int ret;
 
        ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        asyh->curs.visible = asyw->state.visible;
        if (ret || !asyh->curs.visible)
index a53d685a77eb0e1ec8a1aff4e91ec44b671e5d98..c8fedd7d227f18bcd2fe3c11db1e539a1b1fa3b2 100644 (file)
@@ -39,7 +39,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
index d4af69e903ad7cacf7ec8850f328bd7a9b76c1f2..797c1e4e0eaa35f01a474ec3d8a65b18fe6eddcd 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include <nvif/if0014.h>
 #include <nvif/push507c.h>
@@ -106,8 +105,8 @@ ovly507e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
        int ret;
 
        ret = drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        if (ret)
                return ret;
index 082a66d595068bc148a6dca5948779b9ffe39c47..b3deea5aca58d79f6803b9a66f5a78b057bf480f 100644 (file)
@@ -23,7 +23,6 @@
 #include "atom.h"
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <nouveau_bo.h>
 
 #include <nvif/if0014.h>
@@ -297,8 +296,8 @@ wndwc37e_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
                 struct nv50_head_atom *asyh)
 {
        return drm_atomic_helper_check_plane_state(&asyw->state, &asyh->state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   true, true);
 }
 
index 31167c3987085323c4fcb27d61751e5431e05d50..1d214a4b960ab9021a1be543d6c36b36e3db22c9 100644 (file)
@@ -23,7 +23,6 @@
 #include "atom.h"
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <nouveau_bo.h>
 
 #include <nvif/pushc37b.h>
index 05076e530e7d443810ca4aaca149ddf6007b2b41..35bb0bb3fe61ec8626c8333ccab71d345c7e7426 100644 (file)
@@ -281,8 +281,10 @@ nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain,
                        break;
        }
 
-       if (WARN_ON(pi < 0))
+       if (WARN_ON(pi < 0)) {
+               kfree(nvbo);
                return ERR_PTR(-EINVAL);
+       }
 
        /* Disable compression if suitable settings couldn't be found. */
        if (nvbo->comp && !vmm->page[pi].comp) {
@@ -307,9 +309,9 @@ nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 domain,
        nouveau_bo_placement_set(nvbo, domain, 0);
        INIT_LIST_HEAD(&nvbo->io_reserve_lru);
 
-       ret = ttm_bo_init(nvbo->bo.bdev, &nvbo->bo, size, type,
-                         &nvbo->placement, align >> PAGE_SHIFT, false, sg,
-                         robj, nouveau_bo_del_ttm);
+       ret = ttm_bo_init_validate(nvbo->bo.bdev, &nvbo->bo, type,
+                                  &nvbo->placement, align >> PAGE_SHIFT, false,
+                                  sg, robj, nouveau_bo_del_ttm);
        if (ret) {
                /* ttm will call nouveau_bo_del_ttm if it fails.. */
                return ret;
@@ -1006,7 +1008,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
        }
 
        /* Fake bo copy. */
-       if (old_reg->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
+       if (!old_reg || (old_reg->mem_type == TTM_PL_SYSTEM &&
+                        !bo->ttm)) {
                ttm_bo_move_null(bo, new_reg);
                goto out;
        }
index 43a9d1e1cf719fab99044ee01364c3f75dccfc3d..8100c75ee7319902a36239a80d3440d24f69ddc4 100644 (file)
@@ -504,7 +504,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
                        connector->interlace_allowed =
                                nv_encoder->caps.dp_interlace;
                else
-                       connector->interlace_allowed = true;
+                       connector->interlace_allowed =
+                               drm->client.device.info.family < NV_DEVICE_INFO_V0_VOLTA;
                connector->doublescan_allowed = true;
        } else
        if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS ||
index 347488685f745a2cd80a88b431769daa59006371..9608121e49b7efad33a9d7b23c16b462d467e984 100644 (file)
@@ -71,7 +71,6 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
        ret = nouveau_bo_init(nvbo, size, align, NOUVEAU_GEM_DOMAIN_GART,
                              sg, robj);
        if (ret) {
-               nouveau_bo_ref(NULL, &nvbo);
                obj = ERR_PTR(ret);
                goto unlock;
        }
index b4a308f3cf7b0c461515a9904e62280b245d70a9..49e2664a734cba4d6592a28164bf44b0b0584958 100644 (file)
@@ -64,12 +64,9 @@ nvbios_pmuEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
             struct nvbios_pmuE *info)
 {
        u32 data = nvbios_pmuEe(bios, idx, ver, hdr);
-       memset(info, 0x00, sizeof(*info));
-       switch (!!data * *ver) {
-       default:
+       if (data) {
                info->type = nvbios_rd08(bios, data + 0x00);
                info->data = nvbios_rd32(bios, data + 0x02);
-               break;
        }
        return data;
 }
index 06a719c104f4e492a7b58f7b71bf7e09e0183479..63ddc5127f7b66ab98a5597452c1510fb4e1a480 100644 (file)
@@ -10,7 +10,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_mode.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "omap_drv.h"
index b0bc9ad2ef73a2db352972c91b077be91b0e68e9..fb97c74386f2d3776bf90f862eca1bfa49b9ee92 100644 (file)
@@ -6,7 +6,6 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_drv.h"
index b6cb537f7689dab2df36abd5bc3800482925680b..24a2ded08b454c4f2225e84f7b0ed09ed733d6b7 100644 (file)
@@ -8,7 +8,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 
index a9043eacce97c6c06234a15bc9fac306a5c3ed3c..584a69f99af6f2511c95fd4ee3b6ccb96b5a7000 100644 (file)
@@ -166,7 +166,7 @@ config DRM_PANEL_ILITEK_ILI9341
        tristate "Ilitek ILI9341 240x320 QVGA panels"
        depends on OF && SPI
        depends on DRM_KMS_HELPER
-       depends on DRM_GEM_CMA_HELPER
+       depends on DRM_GEM_DMA_HELPER
        depends on BACKLIGHT_CLASS_DEVICE
        select DRM_MIPI_DBI
        help
index 174ff434bd71e0a7cbb0134ac84e192f9106f030..b3235781e6ba19d9af0aef8277f7cbdf51940e82 100644 (file)
@@ -321,7 +321,7 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int tm5p5_nt35596_remove(struct mipi_dsi_device *dsi)
+static void tm5p5_nt35596_remove(struct mipi_dsi_device *dsi)
 {
        struct tm5p5_nt35596 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -332,8 +332,6 @@ static int tm5p5_nt35596_remove(struct mipi_dsi_device *dsi)
                        "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id tm5p5_nt35596_of_match[] = {
index ef00cd67dc407a80d19c1cab3008cb2f4eb74032..ad58840eda41868781717e111f2d31dbaef7640d 100644 (file)
@@ -410,7 +410,7 @@ static int boe_bf060y8m_aj0_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi)
+static void boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi)
 {
        struct boe_bf060y8m_aj0 *boe = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -420,8 +420,6 @@ static int boe_bf060y8m_aj0_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&boe->panel);
-
-       return 0;
 }
 
 static const struct of_device_id boe_bf060y8m_aj0_of_match[] = {
index 42854bd37fd5b569fab8b6703f584775b3ff37c1..d879b3b14c484922019ead73f15b8df299a46e21 100644 (file)
@@ -919,7 +919,7 @@ static int panel_probe(struct mipi_dsi_device *dsi)
        return err;
 }
 
-static int panel_remove(struct mipi_dsi_device *dsi)
+static void panel_remove(struct mipi_dsi_device *dsi)
 {
        struct panel_info *pinfo = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -937,8 +937,6 @@ static int panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
        drm_panel_remove(&pinfo->base);
-
-       return 0;
 }
 
 static void panel_shutdown(struct mipi_dsi_device *dsi)
index 07f722f33fc5bbc7d16a5e6fc8abbb80831a9409..857a2f0420d778731006b3b92754293de6726c7c 100644 (file)
@@ -1622,7 +1622,7 @@ static void boe_panel_shutdown(struct mipi_dsi_device *dsi)
        drm_panel_unprepare(&boe->base);
 }
 
-static int boe_panel_remove(struct mipi_dsi_device *dsi)
+static void boe_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct boe_panel *boe = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -1635,8 +1635,6 @@ static int boe_panel_remove(struct mipi_dsi_device *dsi)
 
        if (boe->base.dev)
                drm_panel_remove(&boe->base);
-
-       return 0;
 }
 
 static const struct of_device_id boe_of_match[] = {
index b0213a518f9d88198c3b518daf8faec8d4152620..ba17bcc4461c76472acce1abfe8b4a429bd2f03d 100644 (file)
@@ -579,7 +579,7 @@ err_bl:
        return r;
 }
 
-static int dsicm_remove(struct mipi_dsi_device *dsi)
+static void dsicm_remove(struct mipi_dsi_device *dsi)
 {
        struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
 
@@ -593,8 +593,6 @@ static int dsicm_remove(struct mipi_dsi_device *dsi)
 
        if (ddata->extbldev)
                put_device(&ddata->extbldev->dev);
-
-       return 0;
 }
 
 static const struct dsic_panel_data taal_data = {
index 386f8321b930e5b95e16c74305aae9eac8564e25..e85d63a176d04274177cf3c830a64fac6439e9fa 100644 (file)
@@ -250,7 +250,7 @@ static int ebbg_ft8719_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int ebbg_ft8719_remove(struct mipi_dsi_device *dsi)
+static void ebbg_ft8719_remove(struct mipi_dsi_device *dsi)
 {
        struct ebbg_ft8719 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -260,8 +260,6 @@ static int ebbg_ft8719_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id ebbg_ft8719_of_match[] = {
index cdb154c8b866bbbee2952ab92f1c5b65bc89d000..335153bb76e2f94512bd2bf13631ff4e28e96085 100644 (file)
@@ -1854,6 +1854,12 @@ static const struct panel_delay delay_100_500_e200 = {
        .enable = 200,
 };
 
+static const struct panel_delay delay_200_500_e200 = {
+       .hpd_absent = 200,
+       .unprepare = 500,
+       .enable = 200,
+};
+
 #define EDP_PANEL_ENTRY(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name) \
 { \
        .name = _name, \
@@ -1870,6 +1876,7 @@ static const struct panel_delay delay_100_500_e200 = {
  * Sort first by vendor, then by product ID.
  */
 static const struct edp_panel_entry edp_panels[] = {
+       EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"),
        EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"),
@@ -1882,6 +1889,8 @@ static const struct edp_panel_entry edp_panels[] = {
 
        EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"),
 
+       EDP_PANEL_ENTRY('I', 'V', 'O', 0x057d, &delay_200_500_e200, "R140NWF5 RH"),
+
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"),
        EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"),
 
index 01dd555a7f26aa758e9d0b23f1d86039573c7f8e..eee714cf3f4906431c21503afbf669051cdbbd7d 100644 (file)
@@ -321,7 +321,7 @@ static void kd35t133_shutdown(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
 }
 
-static int kd35t133_remove(struct mipi_dsi_device *dsi)
+static void kd35t133_remove(struct mipi_dsi_device *dsi)
 {
        struct kd35t133 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -333,8 +333,6 @@ static int kd35t133_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id kd35t133_of_match[] = {
index cb0bb30760994878e01d014e8d1fed6aa535337e..76572c9229836eb8c687dc7c0214b38199eb8827 100644 (file)
@@ -486,14 +486,12 @@ static int k101_im2ba02_dsi_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int k101_im2ba02_dsi_remove(struct mipi_dsi_device *dsi)
+static void k101_im2ba02_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct k101_im2ba02 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id k101_im2ba02_of_match[] = {
index ee61d60eceae179e488c140085b432f5b3555b24..df493da50afece6b7faa1d2f87458e8cfdeb38ea 100644 (file)
@@ -233,14 +233,12 @@ static int feiyang_dsi_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int feiyang_dsi_remove(struct mipi_dsi_device *dsi)
+static void feiyang_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct feiyang *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id feiyang_of_match[] = {
index 6826f4d4826a4b12520c813da4540f47f2296efd..7da09e34385d3d73231fdcc570cb3ce95b4f12cb 100644 (file)
@@ -32,7 +32,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modes.h>
@@ -586,12 +586,12 @@ static const struct drm_display_mode ili9341_dbi_mode = {
        DRM_SIMPLE_MODE(240, 320, 37, 49),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9341_dbi_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ili9341_dbi_fops);
 
 static struct drm_driver ili9341_dbi_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &ili9341_dbi_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "ili9341",
        .desc                   = "Ilitek ILI9341",
index 596861269774f2af6dc3df72f8247fea0c8ff0a2..cbb68caa36f267690ae9e737773bd15f6256785c 100644 (file)
@@ -923,14 +923,12 @@ static int ili9881c_dsi_probe(struct mipi_dsi_device *dsi)
        return mipi_dsi_attach(dsi);
 }
 
-static int ili9881c_dsi_remove(struct mipi_dsi_device *dsi)
+static void ili9881c_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct ili9881c *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct ili9881c_desc lhr050h41_desc = {
index f194b62e290cae561b2c2b188701481f6aa4ee73..9992d0d4c0e5c54281fb201818d2644f931c403b 100644 (file)
@@ -506,7 +506,7 @@ static int innolux_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int innolux_panel_remove(struct mipi_dsi_device *dsi)
+static void innolux_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct innolux_panel *innolux = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -524,8 +524,6 @@ static int innolux_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
        innolux_panel_del(innolux);
-
-       return 0;
 }
 
 static void innolux_panel_shutdown(struct mipi_dsi_device *dsi)
index 31eafbc38ec0c36aaa39947ac9e8b1aeb5c7c61d..d8765b2294fbebf95d61113e8bad48cfaee8df7d 100644 (file)
@@ -288,7 +288,7 @@ static int jdi_fhd_r63452_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi)
+static void jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi)
 {
        struct jdi_fhd_r63452 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -298,8 +298,6 @@ static int jdi_fhd_r63452_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id jdi_fhd_r63452_of_match[] = {
index 3c86ad262d5e013a5285f7feec302a2580f5cfba..8f4f137a2af6b9c26cf56a7d26fb1fed67f9e7cd 100644 (file)
@@ -482,7 +482,7 @@ static int jdi_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int jdi_panel_remove(struct mipi_dsi_device *dsi)
+static void jdi_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -497,8 +497,6 @@ static int jdi_panel_remove(struct mipi_dsi_device *dsi)
                        ret);
 
        jdi_panel_del(jdi);
-
-       return 0;
 }
 
 static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
index a3ec4cbdbf7aadc0ae9a060a19d53ebe3bced7da..1ab1ebe30882077f3b9f76e8f225c47fb9038e97 100644 (file)
@@ -830,7 +830,7 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
        return err;
 }
 
-static int khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
+static void khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct khadas_ts050_panel *khadas_ts050 = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -842,8 +842,6 @@ static int khadas_ts050_panel_remove(struct mipi_dsi_device *dsi)
        drm_panel_remove(&khadas_ts050->base);
        drm_panel_disable(&khadas_ts050->base);
        drm_panel_unprepare(&khadas_ts050->base);
-
-       return 0;
 }
 
 static void khadas_ts050_panel_shutdown(struct mipi_dsi_device *dsi)
index daccb1fd5fdad82dcdfd8caacfe89e43a5bb5746..17f8d80cf2b36935a9845a7a0dbe63b4f70198d4 100644 (file)
@@ -415,7 +415,7 @@ static int kingdisplay_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
+static void kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct kingdisplay_panel *kingdisplay = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -433,8 +433,6 @@ static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
        kingdisplay_panel_del(kingdisplay);
-
-       return 0;
 }
 
 static void kingdisplay_panel_shutdown(struct mipi_dsi_device *dsi)
index a5a414920430d1781ae37dc38fb397da6c946d93..5619f186d28cf524237720256eb108a9ee293147 100644 (file)
@@ -628,7 +628,7 @@ static void ltk050h3146w_shutdown(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
 }
 
-static int ltk050h3146w_remove(struct mipi_dsi_device *dsi)
+static void ltk050h3146w_remove(struct mipi_dsi_device *dsi)
 {
        struct ltk050h3146w *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -640,8 +640,6 @@ static int ltk050h3146w_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id ltk050h3146w_of_match[] = {
index 21e48923836d4a2b01b10e7dde3c78ba9d95fbe9..39e408c9f762f2690a7ba1c0347b4ef2848b50c7 100644 (file)
@@ -477,7 +477,7 @@ static void ltk500hd1829_shutdown(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
 }
 
-static int ltk500hd1829_remove(struct mipi_dsi_device *dsi)
+static void ltk500hd1829_remove(struct mipi_dsi_device *dsi)
 {
        struct ltk500hd1829 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -489,8 +489,6 @@ static int ltk500hd1829_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id ltk500hd1829_of_match[] = {
index 31daae1da9c9c6479dfaf0a30b8672f2d482d4df..772e3b6acece819c736d499d056b2886c089353b 100644 (file)
@@ -336,7 +336,7 @@ static void mantix_shutdown(struct mipi_dsi_device *dsi)
        drm_panel_disable(&ctx->panel);
 }
 
-static int mantix_remove(struct mipi_dsi_device *dsi)
+static void mantix_remove(struct mipi_dsi_device *dsi)
 {
        struct mantix *ctx = mipi_dsi_get_drvdata(dsi);
 
@@ -344,8 +344,6 @@ static int mantix_remove(struct mipi_dsi_device *dsi)
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id mantix_of_match[] = {
index 40ea41b0a5ddb7ca8782ba75b4653981b2e95237..493c3c23f0d649f1ee7aff88281613b8ab50048d 100644 (file)
@@ -231,7 +231,7 @@ struct nt35510_config {
         * bits 0..2 in the lower nibble controls HCK, the booster clock
         * frequency, the values are the same as for PCK in @bt1ctr.
         * bits 4..5 in the upper nibble controls BTH, the boosting
-        * amplification for the the step-up circuit.
+        * amplification for the step-up circuit.
         * 0 = AVDD + VDDB
         * 1 = AVDD - AVEE
         * 2 = AVDD - AVEE + VDDB
@@ -966,7 +966,7 @@ static int nt35510_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int nt35510_remove(struct mipi_dsi_device *dsi)
+static void nt35510_remove(struct mipi_dsi_device *dsi)
 {
        struct nt35510 *nt = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -974,9 +974,10 @@ static int nt35510_remove(struct mipi_dsi_device *dsi)
        mipi_dsi_detach(dsi);
        /* Power off */
        ret = nt35510_power_off(nt);
-       drm_panel_remove(&nt->panel);
+       if (ret)
+               dev_err(&dsi->dev, "Failed to power off\n");
 
-       return ret;
+       drm_panel_remove(&nt->panel);
 }
 
 /*
index 1b6042321ea1d4515ecba18576068f42a7b25b9f..cc7f96d70826322475b4a2345d8cf96608431dff 100644 (file)
@@ -523,14 +523,12 @@ static int nt35560_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int nt35560_remove(struct mipi_dsi_device *dsi)
+static void nt35560_remove(struct mipi_dsi_device *dsi)
 {
        struct nt35560 *nt = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&nt->panel);
-
-       return 0;
 }
 
 static const struct of_device_id nt35560_of_match[] = {
index 288c7fa83ecc53a1ebf4e19816244c852802478f..3a844917da075b1251f055cfe40b7045518929cb 100644 (file)
@@ -620,7 +620,7 @@ static int nt35950_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int nt35950_remove(struct mipi_dsi_device *dsi)
+static void nt35950_remove(struct mipi_dsi_device *dsi)
 {
        struct nt35950 *nt = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -639,8 +639,6 @@ static int nt35950_remove(struct mipi_dsi_device *dsi)
        }
 
        drm_panel_remove(&nt->panel);
-
-       return 0;
 }
 
 static const struct nt35950_panel_mode sharp_ls055d1sx04_modes[] = {
index 6d6ce42787e2c063526c2307d907943bd398f412..73bcffa1e0c151eb3f1ca852b27c60b8fdc5e2cf 100644 (file)
@@ -669,7 +669,7 @@ static int nt36672a_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int nt36672a_panel_remove(struct mipi_dsi_device *dsi)
+static void nt36672a_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct nt36672a_panel *pinfo = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -687,8 +687,6 @@ static int nt36672a_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
        drm_panel_remove(&pinfo->base);
-
-       return 0;
 }
 
 static void nt36672a_panel_shutdown(struct mipi_dsi_device *dsi)
index dfb43b1374e75edc9a3fe2998fed53b377bd232c..b4729a94c34a8e2c99d412815128529c23595ef2 100644 (file)
@@ -497,14 +497,12 @@ static int otm8009a_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int otm8009a_remove(struct mipi_dsi_device *dsi)
+static void otm8009a_remove(struct mipi_dsi_device *dsi)
 {
        struct otm8009a *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id orisetech_otm8009a_of_match[] = {
index 198493a6eb6a5e689f6a2519b10437f17767dcf9..493e0504f6f727dbeaccc459abf10973b02bda82 100644 (file)
@@ -206,7 +206,7 @@ static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
+static void osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct osd101t2587_panel *osd101t2587 = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -221,8 +221,6 @@ static int osd101t2587_panel_remove(struct mipi_dsi_device *dsi)
        ret = mipi_dsi_detach(dsi);
        if (ret < 0)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
-
-       return ret;
 }
 
 static void osd101t2587_panel_shutdown(struct mipi_dsi_device *dsi)
index 3991f5d950af49eb11702e39143fbde8b4f9fba9..8ba6d82879381e9669e5669a09ea611c15adf590 100644 (file)
@@ -250,7 +250,7 @@ static int wuxga_nt_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
+static void wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct wuxga_nt_panel *wuxga_nt = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -264,8 +264,6 @@ static int wuxga_nt_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 
        wuxga_nt_panel_del(wuxga_nt);
-
-       return 0;
 }
 
 static void wuxga_nt_panel_shutdown(struct mipi_dsi_device *dsi)
index 4e021a57221128d741f18242245e4951276e1f1c..dbb1ed4efbed095ad12fc881160ad392710d3e2a 100644 (file)
@@ -616,7 +616,7 @@ static int rad_panel_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int rad_panel_remove(struct mipi_dsi_device *dsi)
+static void rad_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct rad_panel *rad = mipi_dsi_get_drvdata(dsi);
        struct device *dev = &dsi->dev;
@@ -627,8 +627,6 @@ static int rad_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(dev, "Failed to detach from host (%d)\n", ret);
 
        drm_panel_remove(&rad->panel);
-
-       return 0;
 }
 
 static void rad_panel_shutdown(struct mipi_dsi_device *dsi)
index 412c0dbcb2b6f25cb93e5d98590430ab73e2cf49..5f9b340588fb25d7984c7500764347c4be65520c 100644 (file)
@@ -412,14 +412,12 @@ static int rm68200_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int rm68200_remove(struct mipi_dsi_device *dsi)
+static void rm68200_remove(struct mipi_dsi_device *dsi)
 {
        struct rm68200 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id raydium_rm68200_of_match[] = {
index 1fb579a574d9f52ccd484db2010e91da44cdbd3c..a8a98c91b13c716275f11ff2835253c688da0f98 100644 (file)
@@ -208,14 +208,12 @@ static int rb070d30_panel_dsi_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int rb070d30_panel_dsi_remove(struct mipi_dsi_device *dsi)
+static void rb070d30_panel_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct rb070d30_panel *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id rb070d30_panel_of_match[] = {
index 70560cac53a99e1a9d7709df7203feedba73a37b..008e2b0d6652b6239bd4633a620988897493a74a 100644 (file)
@@ -212,14 +212,12 @@ static int s6d16d0_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int s6d16d0_remove(struct mipi_dsi_device *dsi)
+static void s6d16d0_remove(struct mipi_dsi_device *dsi)
 {
        struct s6d16d0 *s6 = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&s6->panel);
-
-       return 0;
 }
 
 static const struct of_device_id s6d16d0_of_match[] = {
index 0ab1b7ec84cdaf7cb68e6de4c6dddedbc39f5479..5c621b15e84c2e1f4d409966cc5b2dfea3c92b90 100644 (file)
@@ -747,15 +747,13 @@ remove_panel:
        return ret;
 }
 
-static int s6e3ha2_remove(struct mipi_dsi_device *dsi)
+static void s6e3ha2_remove(struct mipi_dsi_device *dsi)
 {
        struct s6e3ha2 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
        backlight_device_unregister(ctx->bl_dev);
-
-       return 0;
 }
 
 static const struct of_device_id s6e3ha2_of_match[] = {
index e38262b67ff7e08cceab2cbf00805a4392579a39..e06fd35de814bd162711314c2aeeef8b49a4b2e3 100644 (file)
@@ -488,7 +488,7 @@ remove_panel:
        return ret;
 }
 
-static int s6e63j0x03_remove(struct mipi_dsi_device *dsi)
+static void s6e63j0x03_remove(struct mipi_dsi_device *dsi)
 {
        struct s6e63j0x03 *ctx = mipi_dsi_get_drvdata(dsi);
 
@@ -496,8 +496,6 @@ static int s6e63j0x03_remove(struct mipi_dsi_device *dsi)
        drm_panel_remove(&ctx->panel);
 
        backlight_device_unregister(ctx->bl_dev);
-
-       return 0;
 }
 
 static const struct of_device_id s6e63j0x03_of_match[] = {
index e0f773678168d82c6132baf3b65bbdab5ca03e31..ed3895e4ca5e75aa0d6c8d2fd0d875a1c866ef24 100644 (file)
@@ -113,11 +113,10 @@ static int s6e63m0_dsi_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int s6e63m0_dsi_remove(struct mipi_dsi_device *dsi)
+static void s6e63m0_dsi_remove(struct mipi_dsi_device *dsi)
 {
        mipi_dsi_detach(dsi);
        s6e63m0_remove(&dsi->dev);
-       return 0;
 }
 
 static const struct of_device_id s6e63m0_dsi_of_match[] = {
index 29fde3823212bf8715d7876c4eb781fb2ae02217..97ff7a18545c3f6e2a78cdecc30da8c00173d010 100644 (file)
@@ -254,7 +254,7 @@ static int s6e88a0_ams452ef01_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi)
+static void s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi)
 {
        struct s6e88a0_ams452ef01 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -264,8 +264,6 @@ static int s6e88a0_ams452ef01_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id s6e88a0_ams452ef01_of_match[] = {
index 9b3599d6d2dea20f3acfdce0c455f08add507ca2..54213beafaf5ebeaf4dabf141726a0fc5acfa87b 100644 (file)
@@ -1028,14 +1028,12 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
        return ret;
 }
 
-static int s6e8aa0_remove(struct mipi_dsi_device *dsi)
+static void s6e8aa0_remove(struct mipi_dsi_device *dsi)
 {
        struct s6e8aa0 *ctx = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id s6e8aa0_of_match[] = {
index 1fb37fda4ba96d4d23d9d81db8c1c2eca5e500f7..1a0d24595faa540eeda78517a0f3ab7e2abcd8e5 100644 (file)
@@ -305,7 +305,7 @@ static int sofef00_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int sofef00_panel_remove(struct mipi_dsi_device *dsi)
+static void sofef00_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct sofef00_panel *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -315,8 +315,6 @@ static int sofef00_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id sofef00_panel_of_match[] = {
index f8cd2a42ed13bd25fd653deebb5416d865db1702..14851408a5e15a240a718f834cffaaf10a8bba07 100644 (file)
@@ -391,7 +391,7 @@ static int sharp_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int sharp_panel_remove(struct mipi_dsi_device *dsi)
+static void sharp_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -399,7 +399,7 @@ static int sharp_panel_remove(struct mipi_dsi_device *dsi)
        /* only detach from host for the DSI-LINK2 interface */
        if (!sharp) {
                mipi_dsi_detach(dsi);
-               return 0;
+               return;
        }
 
        err = drm_panel_disable(&sharp->base);
@@ -411,8 +411,6 @@ static int sharp_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
        sharp_panel_del(sharp);
-
-       return 0;
 }
 
 static void sharp_panel_shutdown(struct mipi_dsi_device *dsi)
index 25829a0a8e80129f538d9a3417d7a0ca51630e3e..d1ec80a3e3c72228beb56a763827801b533d2a6b 100644 (file)
@@ -305,7 +305,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
+static void sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -319,8 +319,6 @@ static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret);
 
        sharp_nt_panel_del(sharp_nt);
-
-       return 0;
 }
 
 static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi)
index e12570561629c2833e27b2f44b7b05bb13a77cf1..8a4e0c1fe73ff239d8624af0a92b10291d8044d5 100644 (file)
@@ -298,7 +298,7 @@ static int sharp_ls060_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int sharp_ls060_remove(struct mipi_dsi_device *dsi)
+static void sharp_ls060_remove(struct mipi_dsi_device *dsi)
 {
        struct sharp_ls060 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -308,8 +308,6 @@ static int sharp_ls060_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id sharp_ls060t1sx01_of_match[] = {
index ff5e1a44c43a513a7e8f46a63a914e952ca1f8c6..edd5a0c3543726cc6f0b60d64f5aeaa405500950 100644 (file)
@@ -696,7 +696,7 @@ free_ddc:
        return err;
 }
 
-static int panel_simple_remove(struct device *dev)
+static void panel_simple_remove(struct device *dev)
 {
        struct panel_simple *panel = dev_get_drvdata(dev);
 
@@ -708,8 +708,6 @@ static int panel_simple_remove(struct device *dev)
        pm_runtime_disable(dev);
        if (panel->ddc)
                put_device(&panel->ddc->dev);
-
-       return 0;
 }
 
 static void panel_simple_shutdown(struct device *dev)
@@ -3220,6 +3218,37 @@ static const struct panel_desc rocktech_rk101ii01d_ct = {
        .connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct display_timing samsung_ltl101al01_timing = {
+       .pixelclock = { 66663000, 66663000, 66663000 },
+       .hactive = { 1280, 1280, 1280 },
+       .hfront_porch = { 18, 18, 18 },
+       .hback_porch = { 36, 36, 36 },
+       .hsync_len = { 16, 16, 16 },
+       .vactive = { 800, 800, 800 },
+       .vfront_porch = { 4, 4, 4 },
+       .vback_porch = { 16, 16, 16 },
+       .vsync_len = { 3, 3, 3 },
+       .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
+};
+
+static const struct panel_desc samsung_ltl101al01 = {
+       .timings = &samsung_ltl101al01_timing,
+       .num_timings = 1,
+       .bpc = 8,
+       .size = {
+               .width = 217,
+               .height = 135,
+       },
+       .delay = {
+               .prepare = 40,
+               .enable = 300,
+               .disable = 200,
+               .unprepare = 600,
+       },
+       .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+       .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct drm_display_mode samsung_ltn101nt05_mode = {
        .clock = 54030,
        .hdisplay = 1024,
@@ -4163,6 +4192,9 @@ static const struct of_device_id platform_of_match[] = {
        }, {
                .compatible = "rocktech,rk101ii01d-ct",
                .data = &rocktech_rk101ii01d_ct,
+       }, {
+               .compatible = "samsung,ltl101al01",
+               .data = &samsung_ltl101al01,
        }, {
                .compatible = "samsung,ltn101nt05",
                .data = &samsung_ltn101nt05,
@@ -4273,7 +4305,9 @@ static int panel_simple_platform_probe(struct platform_device *pdev)
 
 static int panel_simple_platform_remove(struct platform_device *pdev)
 {
-       return panel_simple_remove(&pdev->dev);
+       panel_simple_remove(&pdev->dev);
+
+       return 0;
 }
 
 static void panel_simple_platform_shutdown(struct platform_device *pdev)
@@ -4566,7 +4600,7 @@ static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
        return err;
 }
 
-static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
+static void panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
 {
        int err;
 
@@ -4574,7 +4608,7 @@ static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
        if (err < 0)
                dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
 
-       return panel_simple_remove(&dsi->dev);
+       panel_simple_remove(&dsi->dev);
 }
 
 static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi)
index 320a2a8fd4592baf2e3a999fc0a94a78ca9d78f7..c481daa4bbceb8732a0cb4f247c8e0e27527f9c2 100644 (file)
@@ -8,6 +8,7 @@
 #include <drm/drm_modes.h>
 #include <drm/drm_panel.h>
 
+#include <linux/bitfield.h>
 #include <linux/gpio/consumer.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 /*
  * Command2 with BK function selection.
  *
- * BIT[4, 0]: [CN2, BKXSEL]
- * 10 = CMD2BK0, Command2 BK0
- * 11 = CMD2BK1, Command2 BK1
- * 00 = Command2 disable
+ * BIT[4].....CN2
+ * BIT[1:0]...BKXSEL
+ * 1:00 = CMD2BK0, Command2 BK0
+ * 1:01 = CMD2BK1, Command2 BK1
+ * 1:11 = CMD2BK3, Command2 BK3
+ * 0:00 = Command2 disable
  */
-#define DSI_CMD2BK1_SEL                        0x11
 #define DSI_CMD2BK0_SEL                        0x10
+#define DSI_CMD2BK1_SEL                        0x11
+#define DSI_CMD2BK3_SEL                        0x13
 #define DSI_CMD2BKX_SEL_NONE           0x00
 
 /* Command2, BK0 bytes */
-#define DSI_LINESET_LINE               0x69
-#define DSI_LINESET_LDE_EN             BIT(7)
-#define DSI_LINESET_LINEDELTA          GENMASK(1, 0)
-#define DSI_CMD2_BK0_LNESET_B1         DSI_LINESET_LINEDELTA
-#define DSI_CMD2_BK0_LNESET_B0         (DSI_LINESET_LDE_EN | DSI_LINESET_LINE)
-#define DSI_INVSEL_DEFAULT             GENMASK(5, 4)
-#define DSI_INVSEL_NLINV               GENMASK(2, 0)
-#define DSI_INVSEL_RTNI                        GENMASK(2, 1)
-#define DSI_CMD2_BK0_INVSEL_B1         DSI_INVSEL_RTNI
-#define DSI_CMD2_BK0_INVSEL_B0         (DSI_INVSEL_DEFAULT | DSI_INVSEL_NLINV)
-#define DSI_CMD2_BK0_PORCTRL_B0(m)     ((m)->vtotal - (m)->vsync_end)
-#define DSI_CMD2_BK0_PORCTRL_B1(m)     ((m)->vsync_start - (m)->vdisplay)
+#define DSI_CMD2_BK0_GAMCTRL_AJ_MASK   GENMASK(7, 6)
+#define DSI_CMD2_BK0_GAMCTRL_VC0_MASK  GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC4_MASK  GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC8_MASK  GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC16_MASK GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC24_MASK GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC52_MASK GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC80_MASK GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC108_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC147_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC175_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC203_MASK        GENMASK(3, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC231_MASK        GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC239_MASK        GENMASK(4, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC247_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC251_MASK        GENMASK(5, 0)
+#define DSI_CMD2_BK0_GAMCTRL_VC255_MASK        GENMASK(4, 0)
+#define DSI_CMD2_BK0_LNESET_LINE_MASK  GENMASK(6, 0)
+#define DSI_CMD2_BK0_LNESET_LDE_EN     BIT(7)
+#define DSI_CMD2_BK0_LNESET_LINEDELTA  GENMASK(1, 0)
+#define DSI_CMD2_BK0_PORCTRL_VBP_MASK  GENMASK(7, 0)
+#define DSI_CMD2_BK0_PORCTRL_VFP_MASK  GENMASK(7, 0)
+#define DSI_CMD2_BK0_INVSEL_ONES_MASK  GENMASK(5, 4)
+#define DSI_CMD2_BK0_INVSEL_NLINV_MASK GENMASK(2, 0)
+#define DSI_CMD2_BK0_INVSEL_RTNI_MASK  GENMASK(4, 0)
 
 /* Command2, BK1 bytes */
-#define DSI_CMD2_BK1_VRHA_SET          0x45
-#define DSI_CMD2_BK1_VCOM_SET          0x13
-#define DSI_CMD2_BK1_VGHSS_SET         GENMASK(2, 0)
+#define DSI_CMD2_BK1_VRHA_MASK         GENMASK(7, 0)
+#define DSI_CMD2_BK1_VCOM_MASK         GENMASK(7, 0)
+#define DSI_CMD2_BK1_VGHSS_MASK                GENMASK(3, 0)
 #define DSI_CMD2_BK1_TESTCMD_VAL       BIT(7)
-#define DSI_VGLS_DEFAULT               BIT(6)
-#define DSI_VGLS_SEL                   GENMASK(2, 0)
-#define DSI_CMD2_BK1_VGLS_SET          (DSI_VGLS_DEFAULT | DSI_VGLS_SEL)
-#define DSI_PWCTLR1_AP                 BIT(7) /* Gamma OP bias, max */
-#define DSI_PWCTLR1_APIS               BIT(2) /* Source OP input bias, min */
-#define DSI_PWCTLR1_APOS               BIT(0) /* Source OP output bias, min */
-#define DSI_CMD2_BK1_PWCTLR1_SET       (DSI_PWCTLR1_AP | DSI_PWCTLR1_APIS | \
-                                       DSI_PWCTLR1_APOS)
-#define DSI_PWCTLR2_AVDD               BIT(5) /* AVDD 6.6v */
-#define DSI_PWCTLR2_AVCL               0x0    /* AVCL -4.4v */
-#define DSI_CMD2_BK1_PWCTLR2_SET       (DSI_PWCTLR2_AVDD | DSI_PWCTLR2_AVCL)
-#define DSI_SPD1_T2D                   BIT(3)
-#define DSI_CMD2_BK1_SPD1_SET          (GENMASK(6, 4) | DSI_SPD1_T2D)
-#define DSI_CMD2_BK1_SPD2_SET          DSI_CMD2_BK1_SPD1_SET
-#define DSI_MIPISET1_EOT_EN            BIT(3)
-#define DSI_CMD2_BK1_MIPISET1_SET      (BIT(7) | DSI_MIPISET1_EOT_EN)
+#define DSI_CMD2_BK1_VGLS_ONES         BIT(6)
+#define DSI_CMD2_BK1_VGLS_MASK         GENMASK(3, 0)
+#define DSI_CMD2_BK1_PWRCTRL1_AP_MASK  GENMASK(7, 6)
+#define DSI_CMD2_BK1_PWRCTRL1_APIS_MASK        GENMASK(3, 2)
+#define DSI_CMD2_BK1_PWRCTRL1_APOS_MASK        GENMASK(1, 0)
+#define DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK        GENMASK(5, 4)
+#define DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK        GENMASK(1, 0)
+#define DSI_CMD2_BK1_SPD1_ONES_MASK    GENMASK(6, 4)
+#define DSI_CMD2_BK1_SPD1_T2D_MASK     GENMASK(3, 0)
+#define DSI_CMD2_BK1_SPD2_ONES_MASK    GENMASK(6, 4)
+#define DSI_CMD2_BK1_SPD2_T3D_MASK     GENMASK(3, 0)
+#define DSI_CMD2_BK1_MIPISET1_ONES     BIT(7)
+#define DSI_CMD2_BK1_MIPISET1_EOT_EN   BIT(3)
+
+#define CFIELD_PREP(_mask, _val)                                       \
+       (((typeof(_mask))(_val) << (__builtin_ffsll(_mask) - 1)) & (_mask))
+
+enum op_bias {
+       OP_BIAS_OFF = 0,
+       OP_BIAS_MIN,
+       OP_BIAS_MIDDLE,
+       OP_BIAS_MAX
+};
+
+struct st7701;
 
 struct st7701_panel_desc {
        const struct drm_display_mode *mode;
        unsigned int lanes;
-       unsigned long flags;
        enum mipi_dsi_pixel_format format;
-       const char *const *supply_names;
-       unsigned int num_supplies;
        unsigned int panel_sleep_delay;
+
+       /* TFT matrix driver configuration, panel specific. */
+       const u8        pv_gamma[16];   /* Positive voltage gamma control */
+       const u8        nv_gamma[16];   /* Negative voltage gamma control */
+       const u8        nlinv;          /* Inversion selection */
+       const u32       vop_uv;         /* Vop in uV */
+       const u32       vcom_uv;        /* Vcom in uV */
+       const u16       vgh_mv;         /* Vgh in mV */
+       const s16       vgl_mv;         /* Vgl in mV */
+       const u16       avdd_mv;        /* Avdd in mV */
+       const s16       avcl_mv;        /* Avcl in mV */
+       const enum op_bias      gamma_op_bias;
+       const enum op_bias      input_op_bias;
+       const enum op_bias      output_op_bias;
+       const u16       t2d_ns;         /* T2D in ns */
+       const u16       t3d_ns;         /* T3D in ns */
+       const bool      eot_en;
+
+       /* GIP sequence, fully custom and undocumented. */
+       void            (*gip_sequence)(struct st7701 *st7701);
 };
 
 struct st7701 {
@@ -101,7 +144,7 @@ struct st7701 {
        struct mipi_dsi_device *dsi;
        const struct st7701_panel_desc *desc;
 
-       struct regulator_bulk_data *supplies;
+       struct regulator_bulk_data supplies[2];
        struct gpio_desc *reset;
        unsigned int sleep_delay;
 };
@@ -123,9 +166,37 @@ static inline int st7701_dsi_write(struct st7701 *st7701, const void *seq,
                st7701_dsi_write(st7701, d, ARRAY_SIZE(d));     \
        }
 
+static u8 st7701_vgls_map(struct st7701 *st7701)
+{
+       const struct st7701_panel_desc *desc = st7701->desc;
+       struct {
+               s32     vgl;
+               u8      val;
+       } map[16] = {
+               { -7060, 0x0 }, { -7470, 0x1 },
+               { -7910, 0x2 }, { -8140, 0x3 },
+               { -8650, 0x4 }, { -8920, 0x5 },
+               { -9210, 0x6 }, { -9510, 0x7 },
+               { -9830, 0x8 }, { -10170, 0x9 },
+               { -10530, 0xa }, { -10910, 0xb },
+               { -11310, 0xc }, { -11730, 0xd },
+               { -12200, 0xe }, { -12690, 0xf }
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(map); i++)
+               if (desc->vgl_mv == map[i].vgl)
+                       return map[i].val;
+
+       return 0;
+}
+
 static void st7701_init_sequence(struct st7701 *st7701)
 {
-       const struct drm_display_mode *mode = st7701->desc->mode;
+       const struct st7701_panel_desc *desc = st7701->desc;
+       const struct drm_display_mode *mode = desc->mode;
+       const u8 linecount8 = mode->vdisplay / 8;
+       const u8 linecountrem2 = (mode->vdisplay % 8) / 2;
 
        ST7701_DSI(st7701, MIPI_DCS_SOFT_RESET, 0x00);
 
@@ -139,34 +210,105 @@ static void st7701_init_sequence(struct st7701 *st7701)
        /* Command2, BK0 */
        ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
                   0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL);
-       ST7701_DSI(st7701, DSI_CMD2_BK0_PVGAMCTRL, 0x00, 0x0E, 0x15, 0x0F,
-                  0x11, 0x08, 0x08, 0x08, 0x08, 0x23, 0x04, 0x13, 0x12,
-                  0x2B, 0x34, 0x1F);
-       ST7701_DSI(st7701, DSI_CMD2_BK0_NVGAMCTRL, 0x00, 0x0E, 0x95, 0x0F,
-                  0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E,
-                  0x2C, 0x34, 0x1F);
+       mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_PVGAMCTRL,
+                          desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma));
+       mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL,
+                          desc->nv_gamma, ARRAY_SIZE(desc->nv_gamma));
+       /*
+        * Vertical line count configuration:
+        * Line[6:0]: select number of vertical lines of the TFT matrix in
+        *            multiples of 8 lines
+        * LDE_EN: enable sub-8-line granularity line count
+        * Line_delta[1:0]: add 0/2/4/6 extra lines to line count selected
+        *                  using Line[6:0]
+        *
+        * Total number of vertical lines:
+        * LN = ((Line[6:0] + 1) * 8) + (LDE_EN ? Line_delta[1:0] * 2 : 0)
+        */
        ST7701_DSI(st7701, DSI_CMD2_BK0_LNESET,
-                  DSI_CMD2_BK0_LNESET_B0, DSI_CMD2_BK0_LNESET_B1);
+                  FIELD_PREP(DSI_CMD2_BK0_LNESET_LINE_MASK, linecount8 - 1) |
+                  (linecountrem2 ? DSI_CMD2_BK0_LNESET_LDE_EN : 0),
+                  FIELD_PREP(DSI_CMD2_BK0_LNESET_LINEDELTA, linecountrem2));
        ST7701_DSI(st7701, DSI_CMD2_BK0_PORCTRL,
-                  DSI_CMD2_BK0_PORCTRL_B0(mode),
-                  DSI_CMD2_BK0_PORCTRL_B1(mode));
+                  FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VBP_MASK,
+                             mode->vtotal - mode->vsync_end),
+                  FIELD_PREP(DSI_CMD2_BK0_PORCTRL_VFP_MASK,
+                             mode->vsync_start - mode->vdisplay));
+       /*
+        * Horizontal pixel count configuration:
+        * PCLK = 512 + (RTNI[4:0] * 16)
+        * The PCLK is number of pixel clock per line, which matches
+        * mode htotal. The minimum is 512 PCLK.
+        */
        ST7701_DSI(st7701, DSI_CMD2_BK0_INVSEL,
-                  DSI_CMD2_BK0_INVSEL_B0, DSI_CMD2_BK0_INVSEL_B1);
+                  DSI_CMD2_BK0_INVSEL_ONES_MASK |
+                  FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv),
+                  FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK,
+                             DIV_ROUND_UP(mode->htotal, 16)));
 
        /* Command2, BK1 */
        ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
                        0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS, DSI_CMD2_BK1_VRHA_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM, DSI_CMD2_BK1_VCOM_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS, DSI_CMD2_BK1_VGHSS_SET);
+
+       /* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS,
+                  FIELD_PREP(DSI_CMD2_BK1_VRHA_MASK,
+                             DIV_ROUND_CLOSEST(desc->vop_uv - 3537500, 12500)));
+
+       /* Vcom = 0.1V + (VCOM[7:0] * 0.0125V) */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_VCOM,
+                  FIELD_PREP(DSI_CMD2_BK1_VCOM_MASK,
+                             DIV_ROUND_CLOSEST(desc->vcom_uv - 100000, 12500)));
+
+       /* Vgh = 11.5V + (VGHSS[7:0] * 0.5V) */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_VGHSS,
+                  FIELD_PREP(DSI_CMD2_BK1_VGHSS_MASK,
+                             DIV_ROUND_CLOSEST(clamp(desc->vgh_mv,
+                                                     (u16)11500,
+                                                     (u16)17000) - 11500,
+                                               500)));
+
        ST7701_DSI(st7701, DSI_CMD2_BK1_TESTCMD, DSI_CMD2_BK1_TESTCMD_VAL);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS, DSI_CMD2_BK1_VGLS_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1, DSI_CMD2_BK1_PWCTLR1_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2, DSI_CMD2_BK1_PWCTLR2_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1, DSI_CMD2_BK1_SPD1_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2, DSI_CMD2_BK1_SPD2_SET);
-       ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1, DSI_CMD2_BK1_MIPISET1_SET);
 
+       /* Vgl is non-linear */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_VGLS,
+                  DSI_CMD2_BK1_VGLS_ONES |
+                  FIELD_PREP(DSI_CMD2_BK1_VGLS_MASK, st7701_vgls_map(st7701)));
+
+       ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR1,
+                  FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_AP_MASK,
+                             desc->gamma_op_bias) |
+                  FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APIS_MASK,
+                             desc->input_op_bias) |
+                  FIELD_PREP(DSI_CMD2_BK1_PWRCTRL1_APOS_MASK,
+                             desc->output_op_bias));
+
+       /* Avdd = 6.2V + (AVDD[1:0] * 0.2V) , Avcl = -4.4V - (AVCL[1:0] * 0.2V) */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_PWCTLR2,
+                  FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVDD_MASK,
+                             DIV_ROUND_CLOSEST(desc->avdd_mv - 6200, 200)) |
+                  FIELD_PREP(DSI_CMD2_BK1_PWRCTRL2_AVCL_MASK,
+                             DIV_ROUND_CLOSEST(-4400 + desc->avcl_mv, 200)));
+
+       /* T2D = 0.2us * T2D[3:0] */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_SPD1,
+                  DSI_CMD2_BK1_SPD1_ONES_MASK |
+                  FIELD_PREP(DSI_CMD2_BK1_SPD1_T2D_MASK,
+                             DIV_ROUND_CLOSEST(desc->t2d_ns, 200)));
+
+       /* T3D = 4us + (0.8us * T3D[3:0]) */
+       ST7701_DSI(st7701, DSI_CMD2_BK1_SPD2,
+                  DSI_CMD2_BK1_SPD2_ONES_MASK |
+                  FIELD_PREP(DSI_CMD2_BK1_SPD2_T3D_MASK,
+                             DIV_ROUND_CLOSEST(desc->t3d_ns - 4000, 800)));
+
+       ST7701_DSI(st7701, DSI_CMD2_BK1_MIPISET1,
+                  DSI_CMD2_BK1_MIPISET1_ONES |
+                  (desc->eot_en ? DSI_CMD2_BK1_MIPISET1_EOT_EN : 0));
+}
+
+static void ts8550b_gip_sequence(struct st7701 *st7701)
+{
        /**
         * ST7701_SPEC_V1.2 is unable to provide enough information above this
         * specific command sequence, so grab the same from vendor BSP driver.
@@ -188,10 +330,78 @@ static void st7701_init_sequence(struct st7701 *st7701)
        ST7701_DSI(st7701, 0xEC, 0x00, 0x00);
        ST7701_DSI(st7701, 0xED, 0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF,
                   0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40, 0x1F, 0xFF);
+}
+
+static void dmt028vghmcmi_1a_gip_sequence(struct st7701 *st7701)
+{
+       ST7701_DSI(st7701, 0xEE, 0x42);
+       ST7701_DSI(st7701, 0xE0, 0x00, 0x00, 0x02);
+
+       ST7701_DSI(st7701, 0xE1,
+                  0x04, 0xA0, 0x06, 0xA0,
+                          0x05, 0xA0, 0x07, 0xA0,
+                          0x00, 0x44, 0x44);
+       ST7701_DSI(st7701, 0xE2,
+                  0x00, 0x00, 0x00, 0x00,
+                          0x00, 0x00, 0x00, 0x00,
+                          0x00, 0x00, 0x00, 0x00);
+       ST7701_DSI(st7701, 0xE3,
+                  0x00, 0x00, 0x22, 0x22);
+       ST7701_DSI(st7701, 0xE4, 0x44, 0x44);
+       ST7701_DSI(st7701, 0xE5,
+                  0x0C, 0x90, 0xA0, 0xA0,
+                          0x0E, 0x92, 0xA0, 0xA0,
+                          0x08, 0x8C, 0xA0, 0xA0,
+                          0x0A, 0x8E, 0xA0, 0xA0);
+       ST7701_DSI(st7701, 0xE6,
+                  0x00, 0x00, 0x22, 0x22);
+       ST7701_DSI(st7701, 0xE7, 0x44, 0x44);
+       ST7701_DSI(st7701, 0xE8,
+                  0x0D, 0x91, 0xA0, 0xA0,
+                          0x0F, 0x93, 0xA0, 0xA0,
+                          0x09, 0x8D, 0xA0, 0xA0,
+                          0x0B, 0x8F, 0xA0, 0xA0);
+       ST7701_DSI(st7701, 0xEB,
+                  0x00, 0x00, 0xE4, 0xE4,
+                          0x44, 0x00, 0x00);
+       ST7701_DSI(st7701, 0xED,
+                  0xFF, 0xF5, 0x47, 0x6F,
+                          0x0B, 0xA1, 0xAB, 0xFF,
+                          0xFF, 0xBA, 0x1A, 0xB0,
+                          0xF6, 0x74, 0x5F, 0xFF);
+       ST7701_DSI(st7701, 0xEF,
+                  0x08, 0x08, 0x08, 0x40,
+                          0x3F, 0x64);
+
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL);
+       ST7701_DSI(st7701, 0xE6, 0x7C);
+       ST7701_DSI(st7701, 0xE8, 0x00, 0x0E);
+
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+       ST7701_DSI(st7701, 0x11);
+       msleep(120);
+
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL);
+       ST7701_DSI(st7701, 0xE8, 0x00, 0x0C);
+       msleep(10);
+       ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
+
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+       ST7701_DSI(st7701, 0x11);
+       msleep(120);
+       ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
 
-       /* disable Command2 */
        ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
                   0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+
+       ST7701_DSI(st7701, 0x3A, 0x70);
 }
 
 static int st7701_prepare(struct drm_panel *panel)
@@ -201,7 +411,7 @@ static int st7701_prepare(struct drm_panel *panel)
 
        gpiod_set_value(st7701->reset, 0);
 
-       ret = regulator_bulk_enable(st7701->desc->num_supplies,
+       ret = regulator_bulk_enable(ARRAY_SIZE(st7701->supplies),
                                    st7701->supplies);
        if (ret < 0)
                return ret;
@@ -212,6 +422,13 @@ static int st7701_prepare(struct drm_panel *panel)
 
        st7701_init_sequence(st7701);
 
+       if (st7701->desc->gip_sequence)
+               st7701->desc->gip_sequence(st7701);
+
+       /* Disable Command2 */
+       ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
+                  0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+
        return 0;
 }
 
@@ -254,7 +471,7 @@ static int st7701_unprepare(struct drm_panel *panel)
         */
        msleep(st7701->sleep_delay);
 
-       regulator_bulk_disable(st7701->desc->num_supplies, st7701->supplies);
+       regulator_bulk_disable(ARRAY_SIZE(st7701->supplies), st7701->supplies);
 
        return 0;
 }
@@ -310,46 +527,207 @@ static const struct drm_display_mode ts8550b_mode = {
        .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 };
 
-static const char * const ts8550b_supply_names[] = {
-       "VCC",
-       "IOVCC",
-};
-
 static const struct st7701_panel_desc ts8550b_desc = {
        .mode = &ts8550b_mode,
        .lanes = 2,
-       .flags = MIPI_DSI_MODE_VIDEO,
        .format = MIPI_DSI_FMT_RGB888,
-       .supply_names = ts8550b_supply_names,
-       .num_supplies = ARRAY_SIZE(ts8550b_supply_names),
        .panel_sleep_delay = 80, /* panel need extra 80ms for sleep out cmd */
+
+       .pv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x23),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x12),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2b),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
+       .nv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0x2) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x15),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xf),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x13),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x7),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x9),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x22),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x10),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x2c),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x34),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
+       .nlinv = 7,
+       .vop_uv = 4400000,
+       .vcom_uv = 337500,
+       .vgh_mv = 15000,
+       .vgl_mv = -9510,
+       .avdd_mv = 6600,
+       .avcl_mv = -4400,
+       .gamma_op_bias = OP_BIAS_MAX,
+       .input_op_bias = OP_BIAS_MIN,
+       .output_op_bias = OP_BIAS_MIN,
+       .t2d_ns = 1600,
+       .t3d_ns = 10400,
+       .eot_en = true,
+       .gip_sequence = ts8550b_gip_sequence,
+};
+
+static const struct drm_display_mode dmt028vghmcmi_1a_mode = {
+       .clock          = 22325,
+
+       .hdisplay       = 480,
+       .hsync_start    = 480 + 40,
+       .hsync_end      = 480 + 40 + 4,
+       .htotal         = 480 + 40 + 4 + 20,
+
+       .vdisplay       = 640,
+       .vsync_start    = 640 + 2,
+       .vsync_end      = 640 + 2 + 40,
+       .vtotal         = 640 + 2 + 40 + 16,
+
+       .width_mm       = 56,
+       .height_mm      = 78,
+
+       .flags          = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+
+       .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+};
+
+static const struct st7701_panel_desc dmt028vghmcmi_1a_desc = {
+       .mode = &dmt028vghmcmi_1a_mode,
+       .lanes = 2,
+       .format = MIPI_DSI_FMT_RGB888,
+       .panel_sleep_delay = 5, /* panel need extra 5ms for sleep out cmd */
+
+       .pv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0x10),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x17),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xd),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x5),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x7),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x1f),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x11),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0xe),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x29),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
+       .nv_gamma = {
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC0_MASK, 0),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC4_MASK, 0xd),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC8_MASK, 0x14),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC16_MASK, 0xe),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC24_MASK, 0x11),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC52_MASK, 0x6),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC80_MASK, 0x4),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC108_MASK, 0x8),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC147_MASK, 0x8),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC175_MASK, 0x20),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC203_MASK, 0x5),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC231_MASK, 0x13),
+
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC239_MASK, 0x13),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC247_MASK, 0x26),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC251_MASK, 0x30),
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_AJ_MASK, 0) |
+               CFIELD_PREP(DSI_CMD2_BK0_GAMCTRL_VC255_MASK, 0x1f)
+       },
+       .nlinv = 1,
+       .vop_uv = 4800000,
+       .vcom_uv = 1650000,
+       .vgh_mv = 15000,
+       .vgl_mv = -10170,
+       .avdd_mv = 6600,
+       .avcl_mv = -4400,
+       .gamma_op_bias = OP_BIAS_MIDDLE,
+       .input_op_bias = OP_BIAS_MIN,
+       .output_op_bias = OP_BIAS_MIN,
+       .t2d_ns = 1600,
+       .t3d_ns = 10400,
+       .eot_en = true,
+       .gip_sequence = dmt028vghmcmi_1a_gip_sequence,
 };
 
 static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
 {
        const struct st7701_panel_desc *desc;
        struct st7701 *st7701;
-       int ret, i;
+       int ret;
 
        st7701 = devm_kzalloc(&dsi->dev, sizeof(*st7701), GFP_KERNEL);
        if (!st7701)
                return -ENOMEM;
 
        desc = of_device_get_match_data(&dsi->dev);
-       dsi->mode_flags = desc->flags;
+       dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+                         MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
        dsi->format = desc->format;
        dsi->lanes = desc->lanes;
 
-       st7701->supplies = devm_kcalloc(&dsi->dev, desc->num_supplies,
-                                       sizeof(*st7701->supplies),
-                                       GFP_KERNEL);
-       if (!st7701->supplies)
-               return -ENOMEM;
-
-       for (i = 0; i < desc->num_supplies; i++)
-               st7701->supplies[i].supply = desc->supply_names[i];
+       st7701->supplies[0].supply = "VCC";
+       st7701->supplies[1].supply = "IOVCC";
 
-       ret = devm_regulator_bulk_get(&dsi->dev, desc->num_supplies,
+       ret = devm_regulator_bulk_get(&dsi->dev, ARRAY_SIZE(st7701->supplies),
                                      st7701->supplies);
        if (ret < 0)
                return ret;
@@ -387,17 +765,16 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
        return mipi_dsi_attach(dsi);
 }
 
-static int st7701_dsi_remove(struct mipi_dsi_device *dsi)
+static void st7701_dsi_remove(struct mipi_dsi_device *dsi)
 {
        struct st7701 *st7701 = mipi_dsi_get_drvdata(dsi);
 
        mipi_dsi_detach(dsi);
        drm_panel_remove(&st7701->panel);
-
-       return 0;
 }
 
 static const struct of_device_id st7701_of_match[] = {
+       { .compatible = "densitron,dmt028vghmcmi-1a", .data = &dmt028vghmcmi_1a_desc },
        { .compatible = "techstar,ts8550b", .data = &ts8550b_desc },
        { }
 };
index 73f69c929a7566d5d9fe525e7f2781c4eb8c9e20..86a472b01360b358934060bd0193c0c10cc03388 100644 (file)
@@ -598,7 +598,7 @@ static void st7703_shutdown(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
 }
 
-static int st7703_remove(struct mipi_dsi_device *dsi)
+static void st7703_remove(struct mipi_dsi_device *dsi)
 {
        struct st7703 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -612,8 +612,6 @@ static int st7703_remove(struct mipi_dsi_device *dsi)
        drm_panel_remove(&ctx->panel);
 
        st7703_debugfs_remove(ctx);
-
-       return 0;
 }
 
 static const struct of_device_id st7703_of_match[] = {
index 69f07b15fca4f9dd6069e3c39ae7b6d9a3eb1c0e..fa9be3c299c08a01a2113171ed23c6804052150e 100644 (file)
@@ -517,7 +517,7 @@ static int truly_nt35521_probe(struct mipi_dsi_device *dsi)
        return 0;
 }
 
-static int truly_nt35521_remove(struct mipi_dsi_device *dsi)
+static void truly_nt35521_remove(struct mipi_dsi_device *dsi)
 {
        struct truly_nt35521 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -527,8 +527,6 @@ static int truly_nt35521_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id truly_nt35521_of_match[] = {
index 820731be7147092910c2c26430ef77da59f8f929..d8487bc6d61131f819d300ddda21e971b979b312 100644 (file)
@@ -210,7 +210,7 @@ static int tdo_tl070wsh30_panel_probe(struct mipi_dsi_device *dsi)
        return mipi_dsi_attach(dsi);
 }
 
-static int tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi)
+static void tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi)
 {
        struct tdo_tl070wsh30_panel *tdo_tl070wsh30 = mipi_dsi_get_drvdata(dsi);
        int err;
@@ -222,8 +222,6 @@ static int tdo_tl070wsh30_panel_remove(struct mipi_dsi_device *dsi)
        drm_panel_remove(&tdo_tl070wsh30->base);
        drm_panel_disable(&tdo_tl070wsh30->base);
        drm_panel_unprepare(&tdo_tl070wsh30->base);
-
-       return 0;
 }
 
 static void tdo_tl070wsh30_panel_shutdown(struct mipi_dsi_device *dsi)
index 9ca5c7ff41d6547c30b9fe35936a83634e5f98e4..b31cffb660a7720af33aea141bc7579b7a88d2cf 100644 (file)
@@ -616,7 +616,7 @@ err_panel_add:
        return ret;
 }
 
-static int truly_nt35597_remove(struct mipi_dsi_device *dsi)
+static void truly_nt35597_remove(struct mipi_dsi_device *dsi)
 {
        struct truly_nt35597 *ctx = mipi_dsi_get_drvdata(dsi);
 
@@ -628,7 +628,6 @@ static int truly_nt35597_remove(struct mipi_dsi_device *dsi)
        }
 
        drm_panel_remove(&ctx->panel);
-       return 0;
 }
 
 static const struct of_device_id truly_nt35597_of_match[] = {
index db2443ac81d33515b77f132eac4d9fa0c3645f34..ec228c269146f0c5177de3a16ccbe04010ed8339 100644 (file)
@@ -256,7 +256,7 @@ err_dsi_attach:
        return ret;
 }
 
-static int visionox_rm69299_remove(struct mipi_dsi_device *dsi)
+static void visionox_rm69299_remove(struct mipi_dsi_device *dsi)
 {
        struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
 
@@ -264,7 +264,6 @@ static int visionox_rm69299_remove(struct mipi_dsi_device *dsi)
        mipi_dsi_device_unregister(ctx->dsi);
 
        drm_panel_remove(&ctx->panel);
-       return 0;
 }
 
 static const struct of_device_id visionox_rm69299_of_match[] = {
index 8177f5a360fb27c192955ca1547a36aface23053..2c54733ee241a78a9faac91d6cfa08737ee7e459 100644 (file)
@@ -339,7 +339,7 @@ static void xpp055c272_shutdown(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
 }
 
-static int xpp055c272_remove(struct mipi_dsi_device *dsi)
+static void xpp055c272_remove(struct mipi_dsi_device *dsi)
 {
        struct xpp055c272 *ctx = mipi_dsi_get_drvdata(dsi);
        int ret;
@@ -351,8 +351,6 @@ static int xpp055c272_remove(struct mipi_dsi_device *dsi)
                dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);
 
        drm_panel_remove(&ctx->panel);
-
-       return 0;
 }
 
 static const struct of_device_id xpp055c272_of_match[] = {
index 86cdc0ce79e6598010cb63c84440d288dbadf178..079600328be18776adee49954d8d4705fca7296a 100644 (file)
@@ -11,6 +11,7 @@ config DRM_PANFROST
        select DRM_GEM_SHMEM_HELPER
        select PM_DEVFREQ
        select DEVFREQ_GOV_SIMPLE_ONDEMAND
+       select WANT_DEV_COREDUMP
        help
          DRM driver for ARM Mali Midgard (T6xx, T7xx, T8xx) and
          Bifrost (G3x, G5x, G7x) GPUs.
index b719358624179c30ffaea904b09b3050be208492..7da2b3f02ed90c526cc2770210736d67bc0cf5fc 100644 (file)
@@ -9,6 +9,7 @@ panfrost-y := \
        panfrost_gpu.o \
        panfrost_job.o \
        panfrost_mmu.o \
-       panfrost_perfcnt.o
+       panfrost_perfcnt.o \
+       panfrost_dump.o
 
 obj-$(CONFIG_DRM_PANFROST) += panfrost.o
diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c b/drivers/gpu/drm/panfrost/panfrost_dump.c
new file mode 100644 (file)
index 0000000..89056a1
--- /dev/null
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2021 Collabora ltd. */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/devcoredump.h>
+#include <linux/moduleparam.h>
+#include <linux/iosys-map.h>
+#include <drm/panfrost_drm.h>
+#include <drm/drm_device.h>
+
+#include "panfrost_job.h"
+#include "panfrost_gem.h"
+#include "panfrost_regs.h"
+#include "panfrost_dump.h"
+#include "panfrost_device.h"
+
+static bool panfrost_dump_core = true;
+module_param_named(dump_core, panfrost_dump_core, bool, 0600);
+
+struct panfrost_dump_iterator {
+       void *start;
+       struct panfrost_dump_object_header *hdr;
+       void *data;
+};
+
+static const unsigned short panfrost_dump_registers[] = {
+       SHADER_READY_LO,
+       SHADER_READY_HI,
+       TILER_READY_LO,
+       TILER_READY_HI,
+       L2_READY_LO,
+       L2_READY_HI,
+       JOB_INT_MASK,
+       JOB_INT_STAT,
+       JS_HEAD_LO(0),
+       JS_HEAD_HI(0),
+       JS_TAIL_LO(0),
+       JS_TAIL_HI(0),
+       JS_AFFINITY_LO(0),
+       JS_AFFINITY_HI(0),
+       JS_CONFIG(0),
+       JS_STATUS(0),
+       JS_HEAD_NEXT_LO(0),
+       JS_HEAD_NEXT_HI(0),
+       JS_AFFINITY_NEXT_LO(0),
+       JS_AFFINITY_NEXT_HI(0),
+       JS_CONFIG_NEXT(0),
+       MMU_INT_MASK,
+       MMU_INT_STAT,
+       AS_TRANSTAB_LO(0),
+       AS_TRANSTAB_HI(0),
+       AS_MEMATTR_LO(0),
+       AS_MEMATTR_HI(0),
+       AS_FAULTSTATUS(0),
+       AS_FAULTADDRESS_LO(0),
+       AS_FAULTADDRESS_HI(0),
+       AS_STATUS(0),
+};
+
+static void panfrost_core_dump_header(struct panfrost_dump_iterator *iter,
+                                     u32 type, void *data_end)
+{
+       struct panfrost_dump_object_header *hdr = iter->hdr;
+
+       hdr->magic = cpu_to_le32(PANFROSTDUMP_MAGIC);
+       hdr->type = cpu_to_le32(type);
+       hdr->file_offset = cpu_to_le32(iter->data - iter->start);
+       hdr->file_size = cpu_to_le32(data_end - iter->data);
+
+       iter->hdr++;
+       iter->data += le32_to_cpu(hdr->file_size);
+}
+
+static void
+panfrost_core_dump_registers(struct panfrost_dump_iterator *iter,
+                            struct panfrost_device *pfdev,
+                            u32 as_nr, int slot)
+{
+       struct panfrost_dump_registers *dumpreg = iter->data;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(panfrost_dump_registers); i++, dumpreg++) {
+               unsigned int js_as_offset = 0;
+               unsigned int reg;
+
+               if (panfrost_dump_registers[i] >= JS_BASE &&
+                   panfrost_dump_registers[i] <= JS_BASE + JS_SLOT_STRIDE)
+                       js_as_offset = slot * JS_SLOT_STRIDE;
+               else if (panfrost_dump_registers[i] >= MMU_BASE &&
+                        panfrost_dump_registers[i] <= MMU_BASE + MMU_AS_STRIDE)
+                       js_as_offset = (as_nr << MMU_AS_SHIFT);
+
+               reg = panfrost_dump_registers[i] + js_as_offset;
+
+               dumpreg->reg = cpu_to_le32(reg);
+               dumpreg->value = cpu_to_le32(gpu_read(pfdev, reg));
+       }
+
+       panfrost_core_dump_header(iter, PANFROSTDUMP_BUF_REG, dumpreg);
+}
+
+void panfrost_core_dump(struct panfrost_job *job)
+{
+       struct panfrost_device *pfdev = job->pfdev;
+       struct panfrost_dump_iterator iter;
+       struct drm_gem_object *dbo;
+       unsigned int n_obj, n_bomap_pages;
+       __le64 *bomap, *bomap_start;
+       size_t file_size;
+       u32 as_nr;
+       int slot;
+       int ret, i;
+
+       as_nr = job->mmu->as;
+       slot = panfrost_job_get_slot(job);
+
+       /* Only catch the first event, or when manually re-armed */
+       if (!panfrost_dump_core)
+               return;
+       panfrost_dump_core = false;
+
+       /* At least, we dump registers and end marker */
+       n_obj = 2;
+       n_bomap_pages = 0;
+       file_size = ARRAY_SIZE(panfrost_dump_registers) *
+                       sizeof(struct panfrost_dump_registers);
+
+       /* Add in the active buffer objects */
+       for (i = 0; i < job->bo_count; i++) {
+               /*
+                * Even though the CPU could be configured to use 16K or 64K pages, this
+                * is a very unusual situation for most kernel setups on SoCs that have
+                * a Panfrost device. Also many places across the driver make the somewhat
+                * arbitrary assumption that Panfrost's MMU page size is the same as the CPU's,
+                * so let's have a sanity check to ensure that's always the case
+                */
+               dbo = job->bos[i];
+               WARN_ON(!IS_ALIGNED(dbo->size, PAGE_SIZE));
+
+               file_size += dbo->size;
+               n_bomap_pages += dbo->size >> PAGE_SHIFT;
+               n_obj++;
+       }
+
+       /* If we have any buffer objects, add a bomap object */
+       if (n_bomap_pages) {
+               file_size += n_bomap_pages * sizeof(*bomap);
+               n_obj++;
+       }
+
+       /* Add the size of the headers */
+       file_size += sizeof(*iter.hdr) * n_obj;
+
+       /*
+        * Allocate the file in vmalloc memory, it's likely to be big.
+        * The reason behind these GFP flags is that we don't want to trigger the
+        * OOM killer in the event that not enough memory could be found for our
+        * dump file. We also don't want the allocator to do any error reporting,
+        * as the right behaviour is failing gracefully if a big enough buffer
+        * could not be allocated.
+        */
+       iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN |
+                       __GFP_NORETRY);
+       if (!iter.start) {
+               dev_warn(pfdev->dev, "failed to allocate devcoredump file\n");
+               return;
+       }
+
+       /* Point the data member after the headers */
+       iter.hdr = iter.start;
+       iter.data = &iter.hdr[n_obj];
+
+       memset(iter.hdr, 0, iter.data - iter.start);
+
+       /*
+        * For now, we write the job identifier in the register dump header,
+        * so that we can decode the entire dump later with pandecode
+        */
+       iter.hdr->reghdr.jc = cpu_to_le64(job->jc);
+       iter.hdr->reghdr.major = cpu_to_le32(PANFROSTDUMP_MAJOR);
+       iter.hdr->reghdr.minor = cpu_to_le32(PANFROSTDUMP_MINOR);
+       iter.hdr->reghdr.gpu_id = cpu_to_le32(pfdev->features.id);
+       iter.hdr->reghdr.nbos = cpu_to_le64(job->bo_count);
+
+       panfrost_core_dump_registers(&iter, pfdev, as_nr, slot);
+
+       /* Reserve space for the bomap */
+       if (job->bo_count) {
+               bomap_start = bomap = iter.data;
+               memset(bomap, 0, sizeof(*bomap) * n_bomap_pages);
+               panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BOMAP,
+                                         bomap + n_bomap_pages);
+       }
+
+       for (i = 0; i < job->bo_count; i++) {
+               struct iosys_map map;
+               struct panfrost_gem_mapping *mapping;
+               struct panfrost_gem_object *bo;
+               struct sg_page_iter page_iter;
+               void *vaddr;
+
+               bo = to_panfrost_bo(job->bos[i]);
+               mapping = job->mappings[i];
+
+               if (!bo->base.sgt) {
+                       dev_err(pfdev->dev, "Panfrost Dump: BO has no sgt, cannot dump\n");
+                       iter.hdr->bomap.valid = 0;
+                       goto dump_header;
+               }
+
+               ret = drm_gem_shmem_vmap(&bo->base, &map);
+               if (ret) {
+                       dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");
+                       iter.hdr->bomap.valid = 0;
+                       goto dump_header;
+               }
+
+               WARN_ON(!mapping->active);
+
+               iter.hdr->bomap.data[0] = cpu_to_le32((bomap - bomap_start));
+
+               for_each_sgtable_page(bo->base.sgt, &page_iter, 0) {
+                       struct page *page = sg_page_iter_page(&page_iter);
+
+                       if (!IS_ERR(page)) {
+                               *bomap++ = cpu_to_le64(page_to_phys(page));
+                       } else {
+                               dev_err(pfdev->dev, "Panfrost Dump: wrong page\n");
+                               *bomap++ = ~cpu_to_le64(0);
+                       }
+               }
+
+               iter.hdr->bomap.iova = cpu_to_le64(mapping->mmnode.start << PAGE_SHIFT);
+
+               vaddr = map.vaddr;
+               memcpy(iter.data, vaddr, bo->base.base.size);
+
+               drm_gem_shmem_vunmap(&bo->base, &map);
+
+               iter.hdr->bomap.valid = cpu_to_le32(1);
+
+dump_header:   panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_BO, iter.data +
+                                         bo->base.base.size);
+       }
+       panfrost_core_dump_header(&iter, PANFROSTDUMP_BUF_TRAILER, iter.data);
+
+       dev_coredumpv(pfdev->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
+}
diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.h b/drivers/gpu/drm/panfrost/panfrost_dump.h
new file mode 100644 (file)
index 0000000..7d9bcef
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2021 Collabora ltd.
+ */
+
+#ifndef PANFROST_DUMP_H
+#define PANFROST_DUMP_H
+
+struct panfrost_job;
+void panfrost_core_dump(struct panfrost_job *job);
+
+#endif
index 7c4208476fbd34457e3c248eed53f1a9e9a02bbb..dbc597ab46fb9f9260a2232de22d069050bdc72e 100644 (file)
@@ -20,6 +20,7 @@
 #include "panfrost_regs.h"
 #include "panfrost_gpu.h"
 #include "panfrost_mmu.h"
+#include "panfrost_dump.h"
 
 #define JOB_TIMEOUT_MS 500
 
@@ -727,6 +728,8 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
                job_read(pfdev, JS_TAIL_LO(js)),
                sched_job);
 
+       panfrost_core_dump(job);
+
        atomic_set(&pfdev->reset.pending, 1);
        panfrost_reset(pfdev, sched_job);
 
index accb4fa3adb821fb7e9dbed98727694fc2abaaf4..919f44ac853d6ad9e51af50a0a74ae8bdfbae353 100644 (file)
 #define JOB_INT_MASK_DONE(j)           BIT(j)
 
 #define JS_BASE                                0x1800
-#define JS_HEAD_LO(n)                  (JS_BASE + ((n) * 0x80) + 0x00)
-#define JS_HEAD_HI(n)                  (JS_BASE + ((n) * 0x80) + 0x04)
-#define JS_TAIL_LO(n)                  (JS_BASE + ((n) * 0x80) + 0x08)
-#define JS_TAIL_HI(n)                  (JS_BASE + ((n) * 0x80) + 0x0c)
-#define JS_AFFINITY_LO(n)              (JS_BASE + ((n) * 0x80) + 0x10)
-#define JS_AFFINITY_HI(n)              (JS_BASE + ((n) * 0x80) + 0x14)
-#define JS_CONFIG(n)                   (JS_BASE + ((n) * 0x80) + 0x18)
-#define JS_XAFFINITY(n)                        (JS_BASE + ((n) * 0x80) + 0x1c)
-#define JS_COMMAND(n)                  (JS_BASE + ((n) * 0x80) + 0x20)
-#define JS_STATUS(n)                   (JS_BASE + ((n) * 0x80) + 0x24)
-#define JS_HEAD_NEXT_LO(n)             (JS_BASE + ((n) * 0x80) + 0x40)
-#define JS_HEAD_NEXT_HI(n)             (JS_BASE + ((n) * 0x80) + 0x44)
-#define JS_AFFINITY_NEXT_LO(n)         (JS_BASE + ((n) * 0x80) + 0x50)
-#define JS_AFFINITY_NEXT_HI(n)         (JS_BASE + ((n) * 0x80) + 0x54)
-#define JS_CONFIG_NEXT(n)              (JS_BASE + ((n) * 0x80) + 0x58)
-#define JS_COMMAND_NEXT(n)             (JS_BASE + ((n) * 0x80) + 0x60)
-#define JS_FLUSH_ID_NEXT(n)            (JS_BASE + ((n) * 0x80) + 0x70)
+#define JS_SLOT_STRIDE                 0x80
+
+#define JS_HEAD_LO(n)                  (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x00)
+#define JS_HEAD_HI(n)                  (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x04)
+#define JS_TAIL_LO(n)                  (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x08)
+#define JS_TAIL_HI(n)                  (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x0c)
+#define JS_AFFINITY_LO(n)              (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x10)
+#define JS_AFFINITY_HI(n)              (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x14)
+#define JS_CONFIG(n)                   (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x18)
+#define JS_XAFFINITY(n)                        (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x1c)
+#define JS_COMMAND(n)                  (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x20)
+#define JS_STATUS(n)                   (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x24)
+#define JS_HEAD_NEXT_LO(n)             (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x40)
+#define JS_HEAD_NEXT_HI(n)             (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x44)
+#define JS_AFFINITY_NEXT_LO(n)         (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x50)
+#define JS_AFFINITY_NEXT_HI(n)         (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x54)
+#define JS_CONFIG_NEXT(n)              (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x58)
+#define JS_COMMAND_NEXT(n)             (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x60)
+#define JS_FLUSH_ID_NEXT(n)            (JS_BASE + ((n) * JS_SLOT_STRIDE) + 0x70)
 
 /* Possible values of JS_CONFIG and JS_CONFIG_NEXT registers */
 #define JS_CONFIG_START_FLUSH_CLEAN            BIT(8)
 #define AS_COMMAND_FLUSH_MEM           0x05    /* Wait for memory accesses to complete, flush all the L1s cache then
                                                   flush all L2 caches then issue a flush region command to all MMUs */
 
-#define MMU_AS(as)                     (0x2400 + ((as) << 6))
+#define MMU_BASE                       0x2400
+#define MMU_AS_SHIFT                   0x06
+#define MMU_AS(as)                     (MMU_BASE + ((as) << MMU_AS_SHIFT))
 
 #define AS_TRANSTAB_LO(as)             (MMU_AS(as) + 0x00) /* (RW) Translation Table Base Address for address space n, low word */
 #define AS_TRANSTAB_HI(as)             (MMU_AS(as) + 0x04) /* (RW) Translation Table Base Address for address space n, high word */
 #define AS_FAULTEXTRA_LO(as)           (MMU_AS(as) + 0x38) /* (RO) Secondary fault address for address space n, low word */
 #define AS_FAULTEXTRA_HI(as)           (MMU_AS(as) + 0x3C) /* (RO) Secondary fault address for address space n, high word */
 
+#define MMU_AS_STRIDE                  (1 << MMU_AS_SHIFT)
+
 /*
  * Begin LPAE MMU TRANSTAB register values
  */
index 91ee05b013037fb94d212a7ada995064238972d4..ad24cdf1d99280757356f460e8b3417f1dd6c183 100644 (file)
@@ -6,7 +6,7 @@ config DRM_PL111
        depends on VEXPRESS_CONFIG || VEXPRESS_CONFIG=n
        depends on COMMON_CLK
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
        select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
index 6263346f24c6c287319a6cc1efd04f68eb6a2a7c..6afdf260a4e226492637fa1f27f5a6b33de95918 100644 (file)
 #include <linux/media-bus-format.h>
 #include <linux/of_graph.h>
 
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "pl111_drm.h"
@@ -94,7 +94,7 @@ static int pl111_display_check(struct drm_simple_display_pipe *pipe,
                return -EINVAL;
 
        if (fb) {
-               u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
+               u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0);
 
                /* FB base address must be dword aligned. */
                if (offset & 3)
@@ -398,7 +398,7 @@ static void pl111_display_update(struct drm_simple_display_pipe *pipe,
        struct drm_framebuffer *fb = pstate->fb;
 
        if (fb) {
-               u32 addr = drm_fb_cma_get_gem_addr(fb, pstate, 0);
+               u32 addr = drm_fb_dma_get_gem_addr(fb, pstate, 0);
 
                writel(addr, priv->regs + CLCD_UBAS);
        }
index 19a4324bd3565d6e7fe2d86dac8941c88605e92e..eb25eedb5ee008cb5bc2b35ca33694ed3a9627ae 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
@@ -208,10 +207,10 @@ pl111_gem_import_sg_table(struct drm_device *dev,
        if (priv->use_device_memory)
                return ERR_PTR(-EINVAL);
 
-       return drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
+       return drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(drm_fops);
 
 static const struct drm_driver pl111_drm_driver = {
        .driver_features =
@@ -224,7 +223,7 @@ static const struct drm_driver pl111_drm_driver = {
        .major = 1,
        .minor = 0,
        .patchlevel = 0,
-       .dumb_create = drm_gem_cma_dumb_create,
+       .dumb_create = drm_gem_dma_dumb_create,
        .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
        .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_import_sg_table = pl111_gem_import_sg_table,
index efb01a5545740f52367f1b9b376e6fc01a7e76e9..1b436b75fd396f2bf71ab067a873873ccd484fd5 100644 (file)
@@ -404,6 +404,7 @@ static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np,
                if (of_device_is_compatible(child, "arm,pl111")) {
                        has_coretile_clcd = true;
                        ct_clcd = child;
+                       of_node_put(child);
                        break;
                }
                if (of_device_is_compatible(child, "arm,hdlcd")) {
index 2e8949863d6b688db01d91e16763e7b0a9b8be7c..a152a7c6db21574b95436d8586416cec860fbf32 100644 (file)
@@ -902,7 +902,7 @@ static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = {
 static const struct drm_plane_funcs qxl_cursor_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset          = drm_atomic_helper_plane_reset,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
@@ -924,7 +924,7 @@ static const struct drm_plane_helper_funcs primary_helper_funcs = {
 static const struct drm_plane_funcs qxl_primary_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset          = drm_atomic_helper_plane_reset,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
index b42a657e4c2ff231bf43609eeeba4da815a0595d..695d9308d1f08b8aa0bbfc518a63a696dcd995b1 100644 (file)
@@ -141,7 +141,7 @@ int qxl_bo_create(struct qxl_device *qdev, unsigned long size,
        qxl_ttm_placement_from_domain(bo, domain);
 
        bo->tbo.priority = priority;
-       r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, size, type,
+       r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, type,
                                 &bo->placement, 0, &ctx, NULL, NULL,
                                 &qxl_ttm_bo_destroy);
        if (unlikely(r != 0)) {
index f12675e3d261663b9ed3d003e6dea098b22ba649..ca5598ae8bfcf749b74e4dccc02fc5afb374877c 100644 (file)
@@ -38,7 +38,6 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 #include <drm/radeon_drm.h>
index 6c4a6802ca9680289259f8bee4d5f91aedfbd610..00c33b24d5d3498fdbcaa961f1d02d9fc5798794 100644 (file)
@@ -202,9 +202,9 @@ int radeon_bo_create(struct radeon_device *rdev,
        radeon_ttm_placement_from_domain(bo, domain);
        /* Kernel allocation are uninterruptible */
        down_read(&rdev->pm.mclk_lock);
-       r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
-                       &bo->placement, page_align, !kernel, sg, resv,
-                       &radeon_ttm_bo_destroy);
+       r = ttm_bo_init_validate(&rdev->mman.bdev, &bo->tbo, type,
+                                &bo->placement, page_align, !kernel, sg, resv,
+                                &radeon_ttm_bo_destroy);
        up_read(&rdev->pm.mclk_lock);
        if (unlikely(r != 0)) {
                return r;
index f6e6a6d5d987bf95d2954a4268fe04389d568ebf..c959e8c6be7d4e5c39e56c548d6c55d6b6c37710 100644 (file)
@@ -5,7 +5,7 @@ config DRM_RCAR_DU
        depends on ARM || ARM64
        depends on ARCH_RENESAS || COMPILE_TEST
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VIDEOMODE_HELPERS
        help
          Choose this option if you have an R-Car chipset.
index 621bbccb95d48aa33859355c0b63dfcc54767d24..fd3b94649a01d15f39a1b909871b1194e0f38a33 100644 (file)
@@ -17,9 +17,7 @@
 #include <drm/drm_bridge.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "rcar_cmm.h"
index 70d85610d720d56e45b1f38a7565277b06c1b72b..00ac233a115e7ba65675f759c308c471c7c94e51 100644 (file)
@@ -20,9 +20,8 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
 
@@ -579,7 +578,7 @@ const char *rcar_du_output_name(enum rcar_du_output output)
  * DRM operations
  */
 
-DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
+DEFINE_DRM_GEM_DMA_FOPS(rcar_du_fops);
 
 static const struct drm_driver rcar_du_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
index 761451ee52633eda5cc6e9d50c056a83001f0f6c..21881fb5e84ad73023d83f96fcea5238d7122278 100644 (file)
@@ -11,9 +11,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_probe_helper.h>
@@ -328,12 +327,12 @@ const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)
  */
 
 static const struct drm_gem_object_funcs rcar_du_gem_funcs = {
-       .free = drm_gem_cma_object_free,
-       .print_info = drm_gem_cma_object_print_info,
-       .get_sg_table = drm_gem_cma_object_get_sg_table,
-       .vmap = drm_gem_cma_object_vmap,
-       .mmap = drm_gem_cma_object_mmap,
-       .vm_ops = &drm_gem_cma_vm_ops,
+       .free = drm_gem_dma_object_free,
+       .print_info = drm_gem_dma_object_print_info,
+       .get_sg_table = drm_gem_dma_object_get_sg_table,
+       .vmap = drm_gem_dma_object_vmap,
+       .mmap = drm_gem_dma_object_mmap,
+       .vm_ops = &drm_gem_dma_vm_ops,
 };
 
 struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev,
@@ -341,33 +340,33 @@ struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct drm_device *dev,
                                struct sg_table *sgt)
 {
        struct rcar_du_device *rcdu = to_rcar_du_device(dev);
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct drm_gem_object *gem_obj;
        int ret;
 
        if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
-               return drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
+               return drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
 
-       /* Create a CMA GEM buffer. */
-       cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
-       if (!cma_obj)
+       /* Create a DMA GEM buffer. */
+       dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);
+       if (!dma_obj)
                return ERR_PTR(-ENOMEM);
 
-       gem_obj = &cma_obj->base;
+       gem_obj = &dma_obj->base;
        gem_obj->funcs = &rcar_du_gem_funcs;
 
        drm_gem_private_object_init(dev, gem_obj, attach->dmabuf->size);
-       cma_obj->map_noncoherent = false;
+       dma_obj->map_noncoherent = false;
 
        ret = drm_gem_create_mmap_offset(gem_obj);
        if (ret) {
                drm_gem_object_release(gem_obj);
-               kfree(cma_obj);
+               kfree(dma_obj);
                return ERR_PTR(ret);
        }
 
-       cma_obj->paddr = 0;
-       cma_obj->sgt = sgt;
+       dma_obj->dma_addr = 0;
+       dma_obj->sgt = sgt;
 
        return gem_obj;
 }
@@ -390,7 +389,7 @@ int rcar_du_dumb_create(struct drm_file *file, struct drm_device *dev,
 
        args->pitch = roundup(min_pitch, align);
 
-       return drm_gem_cma_dumb_create_internal(file, dev, args);
+       return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
 
 static struct drm_framebuffer *
index 501d79367e3efce6544e9f14810ddabaa393472b..9e1f0cbbf642df43743fd37b101ae2e91cbefeeb 100644 (file)
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "rcar_du_drv.h"
 #include "rcar_du_group.h"
@@ -342,7 +341,7 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
 
        if (state->source == RCAR_DU_PLANE_MEMORY) {
                struct drm_framebuffer *fb = state->state.fb;
-               struct drm_gem_cma_object *gem;
+               struct drm_gem_dma_object *gem;
                unsigned int i;
 
                if (state->format->planes == 2)
@@ -351,8 +350,8 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_group *rgrp,
                        pitch = fb->pitches[0] * 8 / state->format->bpp;
 
                for (i = 0; i < state->format->planes; ++i) {
-                       gem = drm_fb_cma_get_gem_obj(fb, i);
-                       dma[i] = gem->paddr + fb->offsets[i];
+                       gem = drm_fb_dma_get_gem_obj(fb, i);
+                       dma[i] = gem->dma_addr + fb->offsets[i];
                }
        } else {
                pitch = drm_rect_width(&state->state.src) >> 16;
@@ -607,8 +606,8 @@ int __rcar_du_plane_atomic_check(struct drm_plane *plane,
                return PTR_ERR(crtc_state);
 
        ret = drm_atomic_helper_check_plane_state(state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        if (ret < 0)
                return ret;
index dbc68cdabcff95f79be9c1e762b72c1462ab0c4e..10b7f1d0877ab1489b115c8d1bd5901dc6439ca6 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include <linux/bitops.h>
@@ -184,7 +183,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb,
        int ret;
 
        for (i = 0; i < fb->format->num_planes; ++i) {
-               struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
+               struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
                struct sg_table *sgt = &sg_tables[i];
 
                if (gem->sgt) {
@@ -213,7 +212,7 @@ int rcar_du_vsp_map_fb(struct rcar_du_vsp *vsp, struct drm_framebuffer *fb,
                        }
                } else {
                        ret = dma_get_sgtable(rcdu->dev, sgt, gem->vaddr,
-                                             gem->paddr, gem->base.size);
+                                             gem->dma_addr, gem->base.size);
                        if (ret)
                                goto fail;
                }
index 53c2d9980d48bb424b0a849896d334932a032ffc..1bf3e2829cd07b6b0023a2f1e4ca6d75846fb44e 100644 (file)
@@ -2,7 +2,7 @@
 config DRM_ROCKCHIP
        tristate "DRM Support for Rockchip"
        depends on DRM && ROCKCHIP_IOMMU
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_PANEL
        select VIDEOMODE_HELPERS
index 13ed33e7445781a995e70eab7beb96574b287415..813f9f8c86982eee793b53041d477459d9d7ff9e 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_aperture.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
index 985584147da10f4cb9685dee052854e04ff2cc99..614e97aaac805464205473b2320dc573349d1b1a 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <drm/drm.h>
 #include <drm/drm_gem.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_prime.h>
 #include <drm/drm_vma_manager.h>
 
@@ -279,7 +279,7 @@ static const struct drm_gem_object_funcs rockchip_gem_object_funcs = {
        .vmap = rockchip_gem_prime_vmap,
        .vunmap = rockchip_gem_prime_vunmap,
        .mmap = rockchip_drm_gem_object_mmap,
-       .vm_ops = &drm_gem_cma_vm_ops,
+       .vm_ops = &drm_gem_dma_vm_ops,
 };
 
 static struct rockchip_gem_object *
index ad3958b6f8bf37c77894410d7154f8d7c53ec126..bdd48f87d098e4d1b8d249bb7221f0cbe5d46bf2 100644 (file)
@@ -27,7 +27,6 @@
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_self_refresh_helper.h>
 #include <drm/drm_vblank.h>
@@ -809,9 +808,9 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
        const struct vop_win_data *win = vop_win->data;
        int ret;
        int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
-                                       DRM_PLANE_HELPER_NO_SCALING;
+                                       DRM_PLANE_NO_SCALING;
        int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
-                                       DRM_PLANE_HELPER_NO_SCALING;
+                                       DRM_PLANE_NO_SCALING;
 
        if (!crtc || WARN_ON(!fb))
                return 0;
@@ -1060,9 +1059,9 @@ static int vop_plane_atomic_async_check(struct drm_plane *plane,
        struct vop_win *vop_win = to_vop_win(plane);
        const struct vop_win_data *win = vop_win->data;
        int min_scale = win->phy->scl ? FRAC_16_16(1, 8) :
-                                       DRM_PLANE_HELPER_NO_SCALING;
+                                       DRM_PLANE_NO_SCALING;
        int max_scale = win->phy->scl ? FRAC_16_16(8, 1) :
-                                       DRM_PLANE_HELPER_NO_SCALING;
+                                       DRM_PLANE_NO_SCALING;
        struct drm_crtc_state *crtc_state;
 
        if (plane != new_plane_state->crtc->cursor)
index e4631f515ba42a33e2a359ba83844bbce606095a..552426d5d3a2aba1a72044b43cabe8f82e227130 100644 (file)
@@ -29,7 +29,6 @@
 #include <drm/drm_debugfs.h>
 #include <drm/drm_flip_work.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
index 68317d3a7a27707dee2bbf26ff26adda0a13dbc9..e0ab14e0fb6b2ddc5e8cb79bc0f3eb85eb9a7ae6 100644 (file)
@@ -592,7 +592,6 @@ int drm_sched_job_init(struct drm_sched_job *job,
                       struct drm_sched_entity *entity,
                       void *owner)
 {
-       drm_sched_entity_select_rq(entity);
        if (!entity->rq)
                return -ENOENT;
 
@@ -628,7 +627,7 @@ void drm_sched_job_arm(struct drm_sched_job *job)
        struct drm_sched_entity *entity = job->entity;
 
        BUG_ON(!entity);
-
+       drm_sched_entity_select_rq(entity);
        sched = entity->rq->sched;
 
        job->sched = sched;
diff --git a/drivers/gpu/drm/selftests/Makefile b/drivers/gpu/drm/selftests/Makefile
deleted file mode 100644 (file)
index 5ba5f91..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
-                      test-drm_format.o test-drm_framebuffer.o \
-                     test-drm_damage_helper.o test-drm_dp_mst_helper.o \
-                     test-drm_rect.o
-
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o test-drm_cmdline_parser.o \
-                                   test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
deleted file mode 100644 (file)
index 455b756..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(name, function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_buddy
- */
-selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
-selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
-selftest(buddy_alloc_range, igt_buddy_alloc_range)
-selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
-selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
-selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
-selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
deleted file mode 100644 (file)
index 29e367d..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_mm
- */
-
-#define cmdline_test(test)     selftest(test, test)
-
-cmdline_test(drm_cmdline_test_force_d_only)
-cmdline_test(drm_cmdline_test_force_D_only_dvi)
-cmdline_test(drm_cmdline_test_force_D_only_hdmi)
-cmdline_test(drm_cmdline_test_force_D_only_not_digital)
-cmdline_test(drm_cmdline_test_force_e_only)
-cmdline_test(drm_cmdline_test_margin_only)
-cmdline_test(drm_cmdline_test_interlace_only)
-cmdline_test(drm_cmdline_test_res)
-cmdline_test(drm_cmdline_test_res_missing_x)
-cmdline_test(drm_cmdline_test_res_missing_y)
-cmdline_test(drm_cmdline_test_res_bad_y)
-cmdline_test(drm_cmdline_test_res_missing_y_bpp)
-cmdline_test(drm_cmdline_test_res_vesa)
-cmdline_test(drm_cmdline_test_res_vesa_rblank)
-cmdline_test(drm_cmdline_test_res_rblank)
-cmdline_test(drm_cmdline_test_res_bpp)
-cmdline_test(drm_cmdline_test_res_bad_bpp)
-cmdline_test(drm_cmdline_test_res_refresh)
-cmdline_test(drm_cmdline_test_res_bad_refresh)
-cmdline_test(drm_cmdline_test_res_bpp_refresh)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_margins)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_off)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_off)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_analog)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_digital)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on)
-cmdline_test(drm_cmdline_test_res_margins_force_on)
-cmdline_test(drm_cmdline_test_res_vesa_margins)
-cmdline_test(drm_cmdline_test_res_invalid_mode)
-cmdline_test(drm_cmdline_test_res_bpp_wrong_place_mode)
-cmdline_test(drm_cmdline_test_name)
-cmdline_test(drm_cmdline_test_name_bpp)
-cmdline_test(drm_cmdline_test_name_refresh)
-cmdline_test(drm_cmdline_test_name_bpp_refresh)
-cmdline_test(drm_cmdline_test_name_refresh_wrong_mode)
-cmdline_test(drm_cmdline_test_name_refresh_invalid_mode)
-cmdline_test(drm_cmdline_test_name_option)
-cmdline_test(drm_cmdline_test_name_bpp_option)
-cmdline_test(drm_cmdline_test_rotate_0)
-cmdline_test(drm_cmdline_test_rotate_90)
-cmdline_test(drm_cmdline_test_rotate_180)
-cmdline_test(drm_cmdline_test_rotate_270)
-cmdline_test(drm_cmdline_test_rotate_multiple)
-cmdline_test(drm_cmdline_test_rotate_invalid_val)
-cmdline_test(drm_cmdline_test_rotate_truncated)
-cmdline_test(drm_cmdline_test_hmirror)
-cmdline_test(drm_cmdline_test_vmirror)
-cmdline_test(drm_cmdline_test_margin_options)
-cmdline_test(drm_cmdline_test_multiple_options)
-cmdline_test(drm_cmdline_test_invalid_option)
-cmdline_test(drm_cmdline_test_bpp_extra_and_option)
-cmdline_test(drm_cmdline_test_extra_and_option)
-cmdline_test(drm_cmdline_test_freestanding_options)
-cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
-cmdline_test(drm_cmdline_test_panel_orientation)
diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h b/drivers/gpu/drm/selftests/drm_mm_selftests.h
deleted file mode 100644 (file)
index 8c87c96..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(name, function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_mm
- */
-selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
-selftest(init, igt_init)
-selftest(debug, igt_debug)
-selftest(reserve, igt_reserve)
-selftest(insert, igt_insert)
-selftest(replace, igt_replace)
-selftest(insert_range, igt_insert_range)
-selftest(align, igt_align)
-selftest(frag, igt_frag)
-selftest(align32, igt_align32)
-selftest(align64, igt_align64)
-selftest(evict, igt_evict)
-selftest(evict_range, igt_evict_range)
-selftest(bottomup, igt_bottomup)
-selftest(lowest, igt_lowest)
-selftest(topdown, igt_topdown)
-selftest(highest, igt_highest)
-selftest(color, igt_color)
-selftest(color_evict, igt_color_evict)
-selftest(color_evict_range, igt_color_evict_range)
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
deleted file mode 100644 (file)
index 782e285..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(name, function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_selftests_helper
- */
-selftest(drm_rect_clip_scaled_div_by_zero, igt_drm_rect_clip_scaled_div_by_zero)
-selftest(drm_rect_clip_scaled_not_clipped, igt_drm_rect_clip_scaled_not_clipped)
-selftest(drm_rect_clip_scaled_clipped, igt_drm_rect_clip_scaled_clipped)
-selftest(drm_rect_clip_scaled_signed_vs_unsigned, igt_drm_rect_clip_scaled_signed_vs_unsigned)
-selftest(check_plane_state, igt_check_plane_state)
-selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
-selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
-selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch)
-selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
-selftest(damage_iter_no_damage, igt_damage_iter_no_damage)
-selftest(damage_iter_no_damage_fractional_src, igt_damage_iter_no_damage_fractional_src)
-selftest(damage_iter_no_damage_src_moved, igt_damage_iter_no_damage_src_moved)
-selftest(damage_iter_no_damage_fractional_src_moved, igt_damage_iter_no_damage_fractional_src_moved)
-selftest(damage_iter_no_damage_not_visible, igt_damage_iter_no_damage_not_visible)
-selftest(damage_iter_no_damage_no_crtc, igt_damage_iter_no_damage_no_crtc)
-selftest(damage_iter_no_damage_no_fb, igt_damage_iter_no_damage_no_fb)
-selftest(damage_iter_simple_damage, igt_damage_iter_simple_damage)
-selftest(damage_iter_single_damage, igt_damage_iter_single_damage)
-selftest(damage_iter_single_damage_intersect_src, igt_damage_iter_single_damage_intersect_src)
-selftest(damage_iter_single_damage_outside_src, igt_damage_iter_single_damage_outside_src)
-selftest(damage_iter_single_damage_fractional_src, igt_damage_iter_single_damage_fractional_src)
-selftest(damage_iter_single_damage_intersect_fractional_src, igt_damage_iter_single_damage_intersect_fractional_src)
-selftest(damage_iter_single_damage_outside_fractional_src, igt_damage_iter_single_damage_outside_fractional_src)
-selftest(damage_iter_single_damage_src_moved, igt_damage_iter_single_damage_src_moved)
-selftest(damage_iter_single_damage_fractional_src_moved, igt_damage_iter_single_damage_fractional_src_moved)
-selftest(damage_iter_damage, igt_damage_iter_damage)
-selftest(damage_iter_damage_one_intersect, igt_damage_iter_damage_one_intersect)
-selftest(damage_iter_damage_one_outside, igt_damage_iter_damage_one_outside)
-selftest(damage_iter_damage_src_moved, igt_damage_iter_damage_src_moved)
-selftest(damage_iter_damage_not_visible, igt_damage_iter_damage_not_visible)
-selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
-selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/drm_selftest.c b/drivers/gpu/drm/selftests/drm_selftest.c
deleted file mode 100644 (file)
index e29ed9f..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright Â© 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <linux/compiler.h>
-
-#define selftest(name, func) __idx_##name,
-enum {
-#include TESTS
-};
-#undef selftest
-
-#define selftest(n, f) [__idx_##n] = { .name = #n, .func = f },
-static struct drm_selftest {
-       bool enabled;
-       const char *name;
-       int (*func)(void *);
-} selftests[] = {
-#include TESTS
-};
-#undef selftest
-
-/* Embed the line number into the parameter name so that we can order tests */
-#define param(n) __PASTE(igt__, __PASTE(__PASTE(__LINE__, __), n))
-#define selftest_0(n, func, id) \
-module_param_named(id, selftests[__idx_##n].enabled, bool, 0400);
-#define selftest(n, func) selftest_0(n, func, param(n))
-#include TESTS
-#undef selftest
-
-static void set_default_test_all(struct drm_selftest *st, unsigned long count)
-{
-       unsigned long i;
-
-       for (i = 0; i < count; i++)
-               if (st[i].enabled)
-                       return;
-
-       for (i = 0; i < count; i++)
-               st[i].enabled = true;
-}
-
-static int run_selftests(struct drm_selftest *st,
-                        unsigned long count,
-                        void *data)
-{
-       int err = 0;
-
-       set_default_test_all(st, count);
-
-       /* Tests are listed in natural order in drm_*_selftests.h */
-       for (; count--; st++) {
-               if (!st->enabled)
-                       continue;
-
-               pr_debug("drm: Running %s\n", st->name);
-               err = st->func(data);
-               if (err)
-                       break;
-       }
-
-       if (WARN(err > 0 || err == -ENOTTY,
-                "%s returned %d, conflicting with selftest's magic values!\n",
-                st->name, err))
-               err = -1;
-
-       rcu_barrier();
-       return err;
-}
-
-static int __maybe_unused
-__drm_subtests(const char *caller,
-              const struct drm_subtest *st,
-              int count,
-              void *data)
-{
-       int err;
-
-       for (; count--; st++) {
-               pr_debug("Running %s/%s\n", caller, st->name);
-               err = st->func(data);
-               if (err) {
-                       pr_err("%s: %s failed with error %d\n",
-                              caller, st->name, err);
-                       return err;
-               }
-       }
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/drm_selftest.h b/drivers/gpu/drm/selftests/drm_selftest.h
deleted file mode 100644 (file)
index c784ec0..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright Â© 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef __DRM_SELFTEST_H__
-#define __DRM_SELFTEST_H__
-
-struct drm_subtest {
-       int (*func)(void *data);
-       const char *name;
-};
-
-static int __drm_subtests(const char *caller,
-                         const struct drm_subtest *st,
-                         int count,
-                         void *data);
-#define drm_subtests(T, data) \
-       __drm_subtests(__func__, T, ARRAY_SIZE(T), data)
-
-#define SUBTEST(x) { x, #x }
-
-#endif /* __DRM_SELFTEST_H__ */
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c
deleted file mode 100644 (file)
index aca0c49..0000000
+++ /dev/null
@@ -1,994 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright Â© 2019 Intel Corporation
- */
-
-#define pr_fmt(fmt) "drm_buddy: " fmt
-
-#include <linux/module.h>
-#include <linux/prime_numbers.h>
-#include <linux/sched/signal.h>
-
-#include <drm/drm_buddy.h>
-
-#include "../lib/drm_random.h"
-
-#define TESTS "drm_buddy_selftests.h"
-#include "drm_selftest.h"
-
-#define IGT_TIMEOUT(name__) \
-       unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
-
-static unsigned int random_seed;
-
-static inline u64 get_size(int order, u64 chunk_size)
-{
-       return (1 << order) * chunk_size;
-}
-
-__printf(2, 3)
-static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
-{
-       va_list va;
-
-       if (!signal_pending(current)) {
-               cond_resched();
-               if (time_before(jiffies, timeout))
-                       return false;
-       }
-
-       if (fmt) {
-               va_start(va, fmt);
-               vprintk(fmt, va);
-               va_end(va);
-       }
-
-       return true;
-}
-
-static inline const char *yesno(bool v)
-{
-       return v ? "yes" : "no";
-}
-
-static void __igt_dump_block(struct drm_buddy *mm,
-                            struct drm_buddy_block *block,
-                            bool buddy)
-{
-       pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n",
-              block->header,
-              drm_buddy_block_state(block),
-              drm_buddy_block_order(block),
-              drm_buddy_block_offset(block),
-              drm_buddy_block_size(mm, block),
-              yesno(!block->parent),
-              yesno(buddy));
-}
-
-static void igt_dump_block(struct drm_buddy *mm,
-                          struct drm_buddy_block *block)
-{
-       struct drm_buddy_block *buddy;
-
-       __igt_dump_block(mm, block, false);
-
-       buddy = drm_get_buddy(block);
-       if (buddy)
-               __igt_dump_block(mm, buddy, true);
-}
-
-static int igt_check_block(struct drm_buddy *mm,
-                          struct drm_buddy_block *block)
-{
-       struct drm_buddy_block *buddy;
-       unsigned int block_state;
-       u64 block_size;
-       u64 offset;
-       int err = 0;
-
-       block_state = drm_buddy_block_state(block);
-
-       if (block_state != DRM_BUDDY_ALLOCATED &&
-           block_state != DRM_BUDDY_FREE &&
-           block_state != DRM_BUDDY_SPLIT) {
-               pr_err("block state mismatch\n");
-               err = -EINVAL;
-       }
-
-       block_size = drm_buddy_block_size(mm, block);
-       offset = drm_buddy_block_offset(block);
-
-       if (block_size < mm->chunk_size) {
-               pr_err("block size smaller than min size\n");
-               err = -EINVAL;
-       }
-
-       if (!is_power_of_2(block_size)) {
-               pr_err("block size not power of two\n");
-               err = -EINVAL;
-       }
-
-       if (!IS_ALIGNED(block_size, mm->chunk_size)) {
-               pr_err("block size not aligned to min size\n");
-               err = -EINVAL;
-       }
-
-       if (!IS_ALIGNED(offset, mm->chunk_size)) {
-               pr_err("block offset not aligned to min size\n");
-               err = -EINVAL;
-       }
-
-       if (!IS_ALIGNED(offset, block_size)) {
-               pr_err("block offset not aligned to block size\n");
-               err = -EINVAL;
-       }
-
-       buddy = drm_get_buddy(block);
-
-       if (!buddy && block->parent) {
-               pr_err("buddy has gone fishing\n");
-               err = -EINVAL;
-       }
-
-       if (buddy) {
-               if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
-                       pr_err("buddy has wrong offset\n");
-                       err = -EINVAL;
-               }
-
-               if (drm_buddy_block_size(mm, buddy) != block_size) {
-                       pr_err("buddy size mismatch\n");
-                       err = -EINVAL;
-               }
-
-               if (drm_buddy_block_state(buddy) == block_state &&
-                   block_state == DRM_BUDDY_FREE) {
-                       pr_err("block and its buddy are free\n");
-                       err = -EINVAL;
-               }
-       }
-
-       return err;
-}
-
-static int igt_check_blocks(struct drm_buddy *mm,
-                           struct list_head *blocks,
-                           u64 expected_size,
-                           bool is_contiguous)
-{
-       struct drm_buddy_block *block;
-       struct drm_buddy_block *prev;
-       u64 total;
-       int err = 0;
-
-       block = NULL;
-       prev = NULL;
-       total = 0;
-
-       list_for_each_entry(block, blocks, link) {
-               err = igt_check_block(mm, block);
-
-               if (!drm_buddy_block_is_allocated(block)) {
-                       pr_err("block not allocated\n"),
-                              err = -EINVAL;
-               }
-
-               if (is_contiguous && prev) {
-                       u64 prev_block_size;
-                       u64 prev_offset;
-                       u64 offset;
-
-                       prev_offset = drm_buddy_block_offset(prev);
-                       prev_block_size = drm_buddy_block_size(mm, prev);
-                       offset = drm_buddy_block_offset(block);
-
-                       if (offset != (prev_offset + prev_block_size)) {
-                               pr_err("block offset mismatch\n");
-                               err = -EINVAL;
-                       }
-               }
-
-               if (err)
-                       break;
-
-               total += drm_buddy_block_size(mm, block);
-               prev = block;
-       }
-
-       if (!err) {
-               if (total != expected_size) {
-                       pr_err("size mismatch, expected=%llx, found=%llx\n",
-                              expected_size, total);
-                       err = -EINVAL;
-               }
-               return err;
-       }
-
-       if (prev) {
-               pr_err("prev block, dump:\n");
-               igt_dump_block(mm, prev);
-       }
-
-       pr_err("bad block, dump:\n");
-       igt_dump_block(mm, block);
-
-       return err;
-}
-
-static int igt_check_mm(struct drm_buddy *mm)
-{
-       struct drm_buddy_block *root;
-       struct drm_buddy_block *prev;
-       unsigned int i;
-       u64 total;
-       int err = 0;
-
-       if (!mm->n_roots) {
-               pr_err("n_roots is zero\n");
-               return -EINVAL;
-       }
-
-       if (mm->n_roots != hweight64(mm->size)) {
-               pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n",
-                      mm->n_roots, hweight64(mm->size));
-               return -EINVAL;
-       }
-
-       root = NULL;
-       prev = NULL;
-       total = 0;
-
-       for (i = 0; i < mm->n_roots; ++i) {
-               struct drm_buddy_block *block;
-               unsigned int order;
-
-               root = mm->roots[i];
-               if (!root) {
-                       pr_err("root(%u) is NULL\n", i);
-                       err = -EINVAL;
-                       break;
-               }
-
-               err = igt_check_block(mm, root);
-
-               if (!drm_buddy_block_is_free(root)) {
-                       pr_err("root not free\n");
-                       err = -EINVAL;
-               }
-
-               order = drm_buddy_block_order(root);
-
-               if (!i) {
-                       if (order != mm->max_order) {
-                               pr_err("max order root missing\n");
-                               err = -EINVAL;
-                       }
-               }
-
-               if (prev) {
-                       u64 prev_block_size;
-                       u64 prev_offset;
-                       u64 offset;
-
-                       prev_offset = drm_buddy_block_offset(prev);
-                       prev_block_size = drm_buddy_block_size(mm, prev);
-                       offset = drm_buddy_block_offset(root);
-
-                       if (offset != (prev_offset + prev_block_size)) {
-                               pr_err("root offset mismatch\n");
-                               err = -EINVAL;
-                       }
-               }
-
-               block = list_first_entry_or_null(&mm->free_list[order],
-                                                struct drm_buddy_block,
-                                                link);
-               if (block != root) {
-                       pr_err("root mismatch at order=%u\n", order);
-                       err = -EINVAL;
-               }
-
-               if (err)
-                       break;
-
-               prev = root;
-               total += drm_buddy_block_size(mm, root);
-       }
-
-       if (!err) {
-               if (total != mm->size) {
-                       pr_err("expected mm size=%llx, found=%llx\n", mm->size,
-                              total);
-                       err = -EINVAL;
-               }
-               return err;
-       }
-
-       if (prev) {
-               pr_err("prev root(%u), dump:\n", i - 1);
-               igt_dump_block(mm, prev);
-       }
-
-       if (root) {
-               pr_err("bad root(%u), dump:\n", i);
-               igt_dump_block(mm, root);
-       }
-
-       return err;
-}
-
-static void igt_mm_config(u64 *size, u64 *chunk_size)
-{
-       DRM_RND_STATE(prng, random_seed);
-       u32 s, ms;
-
-       /* Nothing fancy, just try to get an interesting bit pattern */
-
-       prandom_seed_state(&prng, random_seed);
-
-       /* Let size be a random number of pages up to 8 GB (2M pages) */
-       s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
-       /* Let the chunk size be a random power of 2 less than size */
-       ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
-       /* Round size down to the chunk size */
-       s &= -ms;
-
-       /* Convert from pages to bytes */
-       *chunk_size = (u64)ms << 12;
-       *size = (u64)s << 12;
-}
-
-static int igt_buddy_alloc_pathological(void *arg)
-{
-       u64 mm_size, size, min_page_size, start = 0;
-       struct drm_buddy_block *block;
-       const int max_order = 3;
-       unsigned long flags = 0;
-       int order, top, err;
-       struct drm_buddy mm;
-       LIST_HEAD(blocks);
-       LIST_HEAD(holes);
-       LIST_HEAD(tmp);
-
-       /*
-        * Create a pot-sized mm, then allocate one of each possible
-        * order within. This should leave the mm with exactly one
-        * page left. Free the largest block, then whittle down again.
-        * Eventually we will have a fully 50% fragmented mm.
-        */
-
-       mm_size = PAGE_SIZE << max_order;
-       err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
-       if (err) {
-               pr_err("buddy_init failed(%d)\n", err);
-               return err;
-       }
-       BUG_ON(mm.max_order != max_order);
-
-       for (top = max_order; top; top--) {
-               /* Make room by freeing the largest allocated block */
-               block = list_first_entry_or_null(&blocks, typeof(*block), link);
-               if (block) {
-                       list_del(&block->link);
-                       drm_buddy_free_block(&mm, block);
-               }
-
-               for (order = top; order--; ) {
-                       size = min_page_size = get_size(order, PAGE_SIZE);
-                       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
-                                                    min_page_size, &tmp, flags);
-                       if (err) {
-                               pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
-                                       order, top);
-                               goto err;
-                       }
-
-                       block = list_first_entry_or_null(&tmp,
-                                                        struct drm_buddy_block,
-                                                        link);
-                       if (!block) {
-                               pr_err("alloc_blocks has no blocks\n");
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       list_move_tail(&block->link, &blocks);
-               }
-
-               /* There should be one final page for this sub-allocation */
-               size = min_page_size = get_size(0, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (err) {
-                       pr_info("buddy_alloc hit -ENOMEM for hole\n");
-                       goto err;
-               }
-
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_blocks has no blocks\n");
-                       err = -EINVAL;
-                       goto err;
-               }
-
-               list_move_tail(&block->link, &holes);
-
-               size = min_page_size = get_size(top, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (!err) {
-                       pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
-                               top, max_order);
-                       block = list_first_entry_or_null(&tmp,
-                                                        struct drm_buddy_block,
-                                                        link);
-                       if (!block) {
-                               pr_err("alloc_blocks has no blocks\n");
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       list_move_tail(&block->link, &blocks);
-                       err = -EINVAL;
-                       goto err;
-               }
-       }
-
-       drm_buddy_free_list(&mm, &holes);
-
-       /* Nothing larger than blocks of chunk_size now available */
-       for (order = 1; order <= max_order; order++) {
-               size = min_page_size = get_size(order, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (!err) {
-                       pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
-                               order);
-                       block = list_first_entry_or_null(&tmp,
-                                                        struct drm_buddy_block,
-                                                        link);
-                       if (!block) {
-                               pr_err("alloc_blocks has no blocks\n");
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       list_move_tail(&block->link, &blocks);
-                       err = -EINVAL;
-                       goto err;
-               }
-       }
-
-       if (err)
-               err = 0;
-
-err:
-       list_splice_tail(&holes, &blocks);
-       drm_buddy_free_list(&mm, &blocks);
-       drm_buddy_fini(&mm);
-       return err;
-}
-
-static int igt_buddy_alloc_smoke(void *arg)
-{
-       u64 mm_size, min_page_size, chunk_size, start = 0;
-       unsigned long flags = 0;
-       struct drm_buddy mm;
-       int *order;
-       int err, i;
-
-       DRM_RND_STATE(prng, random_seed);
-       IGT_TIMEOUT(end_time);
-
-       igt_mm_config(&mm_size, &chunk_size);
-
-       err = drm_buddy_init(&mm, mm_size, chunk_size);
-       if (err) {
-               pr_err("buddy_init failed(%d)\n", err);
-               return err;
-       }
-
-       order = drm_random_order(mm.max_order + 1, &prng);
-       if (!order) {
-               err = -ENOMEM;
-               goto out_fini;
-       }
-
-       for (i = 0; i <= mm.max_order; ++i) {
-               struct drm_buddy_block *block;
-               int max_order = order[i];
-               bool timeout = false;
-               LIST_HEAD(blocks);
-               u64 total, size;
-               LIST_HEAD(tmp);
-               int order;
-
-               err = igt_check_mm(&mm);
-               if (err) {
-                       pr_err("pre-mm check failed, abort\n");
-                       break;
-               }
-
-               order = max_order;
-               total = 0;
-
-               do {
-retry:
-                       size = min_page_size = get_size(order, chunk_size);
-                       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size,
-                                                    min_page_size, &tmp, flags);
-                       if (err) {
-                               if (err == -ENOMEM) {
-                                       pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
-                                               order);
-                               } else {
-                                       if (order--) {
-                                               err = 0;
-                                               goto retry;
-                                       }
-
-                                       pr_err("buddy_alloc with order=%d failed(%d)\n",
-                                              order, err);
-                               }
-
-                               break;
-                       }
-
-                       block = list_first_entry_or_null(&tmp,
-                                                        struct drm_buddy_block,
-                                                        link);
-                       if (!block) {
-                               pr_err("alloc_blocks has no blocks\n");
-                               err = -EINVAL;
-                               break;
-                       }
-
-                       list_move_tail(&block->link, &blocks);
-
-                       if (drm_buddy_block_order(block) != order) {
-                               pr_err("buddy_alloc order mismatch\n");
-                               err = -EINVAL;
-                               break;
-                       }
-
-                       total += drm_buddy_block_size(&mm, block);
-
-                       if (__igt_timeout(end_time, NULL)) {
-                               timeout = true;
-                               break;
-                       }
-               } while (total < mm.size);
-
-               if (!err)
-                       err = igt_check_blocks(&mm, &blocks, total, false);
-
-               drm_buddy_free_list(&mm, &blocks);
-
-               if (!err) {
-                       err = igt_check_mm(&mm);
-                       if (err)
-                               pr_err("post-mm check failed\n");
-               }
-
-               if (err || timeout)
-                       break;
-
-               cond_resched();
-       }
-
-       if (err == -ENOMEM)
-               err = 0;
-
-       kfree(order);
-out_fini:
-       drm_buddy_fini(&mm);
-
-       return err;
-}
-
-static int igt_buddy_alloc_pessimistic(void *arg)
-{
-       u64 mm_size, size, min_page_size, start = 0;
-       struct drm_buddy_block *block, *bn;
-       const unsigned int max_order = 16;
-       unsigned long flags = 0;
-       struct drm_buddy mm;
-       unsigned int order;
-       LIST_HEAD(blocks);
-       LIST_HEAD(tmp);
-       int err;
-
-       /*
-        * Create a pot-sized mm, then allocate one of each possible
-        * order within. This should leave the mm with exactly one
-        * page left.
-        */
-
-       mm_size = PAGE_SIZE << max_order;
-       err = drm_buddy_init(&mm, mm_size, PAGE_SIZE);
-       if (err) {
-               pr_err("buddy_init failed(%d)\n", err);
-               return err;
-       }
-       BUG_ON(mm.max_order != max_order);
-
-       for (order = 0; order < max_order; order++) {
-               size = min_page_size = get_size(order, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (err) {
-                       pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
-                               order);
-                       goto err;
-               }
-
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_blocks has no blocks\n");
-                       err = -EINVAL;
-                       goto err;
-               }
-
-               list_move_tail(&block->link, &blocks);
-       }
-
-       /* And now the last remaining block available */
-       size = min_page_size = get_size(0, PAGE_SIZE);
-       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-       if (err) {
-               pr_info("buddy_alloc hit -ENOMEM on final alloc\n");
-               goto err;
-       }
-
-       block = list_first_entry_or_null(&tmp,
-                                        struct drm_buddy_block,
-                                        link);
-       if (!block) {
-               pr_err("alloc_blocks has no blocks\n");
-               err = -EINVAL;
-               goto err;
-       }
-
-       list_move_tail(&block->link, &blocks);
-
-       /* Should be completely full! */
-       for (order = max_order; order--; ) {
-               size = min_page_size = get_size(order, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (!err) {
-                       pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!",
-                               order);
-                       block = list_first_entry_or_null(&tmp,
-                                                        struct drm_buddy_block,
-                                                        link);
-                       if (!block) {
-                               pr_err("alloc_blocks has no blocks\n");
-                               err = -EINVAL;
-                               goto err;
-                       }
-
-                       list_move_tail(&block->link, &blocks);
-                       err = -EINVAL;
-                       goto err;
-               }
-       }
-
-       block = list_last_entry(&blocks, typeof(*block), link);
-       list_del(&block->link);
-       drm_buddy_free_block(&mm, block);
-
-       /* As we free in increasing size, we make available larger blocks */
-       order = 1;
-       list_for_each_entry_safe(block, bn, &blocks, link) {
-               list_del(&block->link);
-               drm_buddy_free_block(&mm, block);
-
-               size = min_page_size = get_size(order, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (err) {
-                       pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
-                               order);
-                       goto err;
-               }
-
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_blocks has no blocks\n");
-                       err = -EINVAL;
-                       goto err;
-               }
-
-               list_del(&block->link);
-               drm_buddy_free_block(&mm, block);
-               order++;
-       }
-
-       /* To confirm, now the whole mm should be available */
-       size = min_page_size = get_size(max_order, PAGE_SIZE);
-       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-       if (err) {
-               pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
-                       max_order);
-               goto err;
-       }
-
-       block = list_first_entry_or_null(&tmp,
-                                        struct drm_buddy_block,
-                                        link);
-       if (!block) {
-               pr_err("alloc_blocks has no blocks\n");
-               err = -EINVAL;
-               goto err;
-       }
-
-       list_del(&block->link);
-       drm_buddy_free_block(&mm, block);
-
-err:
-       drm_buddy_free_list(&mm, &blocks);
-       drm_buddy_fini(&mm);
-       return err;
-}
-
-static int igt_buddy_alloc_optimistic(void *arg)
-{
-       u64 mm_size, size, min_page_size, start = 0;
-       struct drm_buddy_block *block;
-       unsigned long flags = 0;
-       const int max_order = 16;
-       struct drm_buddy mm;
-       LIST_HEAD(blocks);
-       LIST_HEAD(tmp);
-       int order, err;
-
-       /*
-        * Create a mm with one block of each order available, and
-        * try to allocate them all.
-        */
-
-       mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1);
-       err = drm_buddy_init(&mm,
-                            mm_size,
-                            PAGE_SIZE);
-       if (err) {
-               pr_err("buddy_init failed(%d)\n", err);
-               return err;
-       }
-
-       BUG_ON(mm.max_order != max_order);
-
-       for (order = 0; order <= max_order; order++) {
-               size = min_page_size = get_size(order, PAGE_SIZE);
-               err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-               if (err) {
-                       pr_info("buddy_alloc hit -ENOMEM with order=%d\n",
-                               order);
-                       goto err;
-               }
-
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_blocks has no blocks\n");
-                       err = -EINVAL;
-                       goto err;
-               }
-
-               list_move_tail(&block->link, &blocks);
-       }
-
-       /* Should be completely full! */
-       size = min_page_size = get_size(0, PAGE_SIZE);
-       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, min_page_size, &tmp, flags);
-       if (!err) {
-               pr_info("buddy_alloc unexpectedly succeeded, it should be full!");
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_blocks has no blocks\n");
-                       err = -EINVAL;
-                       goto err;
-               }
-
-               list_move_tail(&block->link, &blocks);
-               err = -EINVAL;
-               goto err;
-       } else {
-               err = 0;
-       }
-
-err:
-       drm_buddy_free_list(&mm, &blocks);
-       drm_buddy_fini(&mm);
-       return err;
-}
-
-static int igt_buddy_alloc_range(void *arg)
-{
-       unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
-       u64 offset, size, rem, chunk_size, end;
-       unsigned long page_num;
-       struct drm_buddy mm;
-       LIST_HEAD(blocks);
-       int err;
-
-       igt_mm_config(&size, &chunk_size);
-
-       err = drm_buddy_init(&mm, size, chunk_size);
-       if (err) {
-               pr_err("buddy_init failed(%d)\n", err);
-               return err;
-       }
-
-       err = igt_check_mm(&mm);
-       if (err) {
-               pr_err("pre-mm check failed, abort, abort, abort!\n");
-               goto err_fini;
-       }
-
-       rem = mm.size;
-       offset = 0;
-
-       for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
-               struct drm_buddy_block *block;
-               LIST_HEAD(tmp);
-
-               size = min(page_num * mm.chunk_size, rem);
-               end = offset + size;
-
-               err = drm_buddy_alloc_blocks(&mm, offset, end, size, mm.chunk_size, &tmp, flags);
-               if (err) {
-                       if (err == -ENOMEM) {
-                               pr_info("alloc_range hit -ENOMEM with size=%llx\n",
-                                       size);
-                       } else {
-                               pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n",
-                                      offset, size, err);
-                       }
-
-                       break;
-               }
-
-               block = list_first_entry_or_null(&tmp,
-                                                struct drm_buddy_block,
-                                                link);
-               if (!block) {
-                       pr_err("alloc_range has no blocks\n");
-                       err = -EINVAL;
-                       break;
-               }
-
-               if (drm_buddy_block_offset(block) != offset) {
-                       pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n",
-                              drm_buddy_block_offset(block), offset);
-                       err = -EINVAL;
-               }
-
-               if (!err)
-                       err = igt_check_blocks(&mm, &tmp, size, true);
-
-               list_splice_tail(&tmp, &blocks);
-
-               if (err)
-                       break;
-
-               offset += size;
-
-               rem -= size;
-               if (!rem)
-                       break;
-
-               cond_resched();
-       }
-
-       if (err == -ENOMEM)
-               err = 0;
-
-       drm_buddy_free_list(&mm, &blocks);
-
-       if (!err) {
-               err = igt_check_mm(&mm);
-               if (err)
-                       pr_err("post-mm check failed\n");
-       }
-
-err_fini:
-       drm_buddy_fini(&mm);
-
-       return err;
-}
-
-static int igt_buddy_alloc_limit(void *arg)
-{
-       u64 size = U64_MAX, start = 0;
-       struct drm_buddy_block *block;
-       unsigned long flags = 0;
-       LIST_HEAD(allocated);
-       struct drm_buddy mm;
-       int err;
-
-       err = drm_buddy_init(&mm, size, PAGE_SIZE);
-       if (err)
-               return err;
-
-       if (mm.max_order != DRM_BUDDY_MAX_ORDER) {
-               pr_err("mm.max_order(%d) != %d\n",
-                      mm.max_order, DRM_BUDDY_MAX_ORDER);
-               err = -EINVAL;
-               goto out_fini;
-       }
-
-       size = mm.chunk_size << mm.max_order;
-       err = drm_buddy_alloc_blocks(&mm, start, size, size,
-                                    PAGE_SIZE, &allocated, flags);
-
-       if (unlikely(err))
-               goto out_free;
-
-       block = list_first_entry_or_null(&allocated,
-                                        struct drm_buddy_block,
-                                        link);
-
-       if (!block) {
-               err = -EINVAL;
-               goto out_fini;
-       }
-
-       if (drm_buddy_block_order(block) != mm.max_order) {
-               pr_err("block order(%d) != %d\n",
-                      drm_buddy_block_order(block), mm.max_order);
-               err = -EINVAL;
-               goto out_free;
-       }
-
-       if (drm_buddy_block_size(&mm, block) !=
-           BIT_ULL(mm.max_order) * PAGE_SIZE) {
-               pr_err("block size(%llu) != %llu\n",
-                      drm_buddy_block_size(&mm, block),
-                      BIT_ULL(mm.max_order) * PAGE_SIZE);
-               err = -EINVAL;
-               goto out_free;
-       }
-
-out_free:
-       drm_buddy_free_list(&mm, &allocated);
-out_fini:
-       drm_buddy_fini(&mm);
-       return err;
-}
-
-static int igt_sanitycheck(void *ignored)
-{
-       pr_info("%s - ok!\n", __func__);
-       return 0;
-}
-
-#include "drm_selftest.c"
-
-static int __init test_drm_buddy_init(void)
-{
-       int err;
-
-       while (!random_seed)
-               random_seed = get_random_int();
-
-       pr_info("Testing DRM buddy manager (struct drm_buddy), with random_seed=0x%x\n",
-               random_seed);
-       err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
-
-       return err > 0 ? 0 : err;
-}
-
-static void __exit test_drm_buddy_exit(void)
-{
-}
-
-module_init(test_drm_buddy_init);
-module_exit(test_drm_buddy_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c b/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
deleted file mode 100644 (file)
index d96cd89..0000000
+++ /dev/null
@@ -1,1141 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2019 Bootlin
- */
-
-#define pr_fmt(fmt) "drm_cmdline: " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-#include <drm/drm_connector.h>
-#include <drm/drm_modes.h>
-
-#define TESTS "drm_cmdline_selftests.h"
-#include "drm_selftest.h"
-#include "test-drm_modeset_common.h"
-
-static const struct drm_connector no_connector = {};
-
-static int drm_cmdline_test_force_e_only(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("e",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_force_D_only_not_digital(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static const struct drm_connector connector_hdmi = {
-       .connector_type = DRM_MODE_CONNECTOR_HDMIB,
-};
-
-static int drm_cmdline_test_force_D_only_hdmi(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
-                                                          &connector_hdmi,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
-
-       return 0;
-}
-
-static const struct drm_connector connector_dvi = {
-       .connector_type = DRM_MODE_CONNECTOR_DVII,
-};
-
-static int drm_cmdline_test_force_D_only_dvi(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("D",
-                                                          &connector_dvi,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
-
-       return 0;
-}
-
-static int drm_cmdline_test_force_d_only(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("d",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_OFF);
-
-       return 0;
-}
-
-static int drm_cmdline_test_margin_only(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("m",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_interlace_only(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("i",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_missing_x(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("x480",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_missing_y(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("1024x",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bad_y(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("1024xtest",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_missing_y_bpp(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("1024x-24",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_vesa(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480M",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(!mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_vesa_rblank(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480MR",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(!mode.rb);
-       FAIL_ON(!mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_rblank(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480R",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(!mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bad_bpp(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-test",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_refresh(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480@60",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bad_refresh(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480@refresh",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_interlaced(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60i",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(!mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_margins(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60m",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(!mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_force_off(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60d",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_OFF);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_force_on_off(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480-24@60de",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_force_on(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60e",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_force_on_analog(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_force_on_digital(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-       static const struct drm_connector connector = {
-               .connector_type = DRM_MODE_CONNECTOR_DVII,
-       };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60D",
-                                                          &connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON_DIGITAL);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24@60ime",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(!mode.refresh_specified);
-       FAIL_ON(mode.refresh != 60);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(!mode.interlace);
-       FAIL_ON(!mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_margins_force_on(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480me",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(!mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_vesa_margins(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480Mm",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(!mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(!mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_invalid_mode(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480f",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_res_bpp_wrong_place_mode(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480e-24",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_name(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(strcmp(mode.name, "NTSC"));
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_bpp(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(strcmp(mode.name, "NTSC"));
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_bpp_refresh(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC-24@60",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_refresh(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_refresh_wrong_mode(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60m",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_refresh_invalid_mode(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("NTSC@60f",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_option(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC,rotate=180",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(strcmp(mode.name, "NTSC"));
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
-
-       return 0;
-}
-
-static int drm_cmdline_test_name_bpp_option(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("NTSC-24,rotate=180",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(strcmp(mode.name, "NTSC"));
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_0(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=0",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_0);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_90(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=90",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_90);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_180(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=180",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_270(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_270);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_multiple(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_invalid_val(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=42",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_rotate_truncated(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_hmirror(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_x",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X));
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_vmirror(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,reflect_y",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y));
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_margin_options(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.tv_margins.right != 14);
-       FAIL_ON(mode.tv_margins.left != 24);
-       FAIL_ON(mode.tv_margins.bottom != 36);
-       FAIL_ON(mode.tv_margins.top != 42);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_multiple_options(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480,rotate=270,reflect_x",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X));
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_invalid_option(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,test=42",
-                                                         &no_connector,
-                                                         &mode));
-
-       return 0;
-}
-
-static int drm_cmdline_test_bpp_extra_and_option(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480-24e,rotate=180",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
-
-       FAIL_ON(mode.refresh_specified);
-
-       FAIL_ON(!mode.bpp_specified);
-       FAIL_ON(mode.bpp != 24);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_extra_and_option(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("720x480e,rotate=180",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(!mode.specified);
-       FAIL_ON(mode.xres != 720);
-       FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_ROTATE_180);
-
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_freestanding_options(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.tv_margins.right != 14);
-       FAIL_ON(mode.tv_margins.left != 24);
-       FAIL_ON(mode.tv_margins.bottom != 36);
-       FAIL_ON(mode.tv_margins.top != 42);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-static int drm_cmdline_test_freestanding_force_e_and_options(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.tv_margins.right != 14);
-       FAIL_ON(mode.tv_margins.left != 24);
-       FAIL_ON(mode.tv_margins.bottom != 36);
-       FAIL_ON(mode.tv_margins.top != 42);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_ON);
-
-       return 0;
-}
-
-static int drm_cmdline_test_panel_orientation(void *ignored)
-{
-       struct drm_cmdline_mode mode = { };
-
-       FAIL_ON(!drm_mode_parse_command_line_for_connector("panel_orientation=upside_down",
-                                                          &no_connector,
-                                                          &mode));
-       FAIL_ON(mode.specified);
-       FAIL_ON(mode.refresh_specified);
-       FAIL_ON(mode.bpp_specified);
-
-       FAIL_ON(mode.panel_orientation != DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
-
-       FAIL_ON(mode.rb);
-       FAIL_ON(mode.cvt);
-       FAIL_ON(mode.interlace);
-       FAIL_ON(mode.margins);
-       FAIL_ON(mode.force != DRM_FORCE_UNSPECIFIED);
-
-       return 0;
-}
-
-#include "drm_selftest.c"
-
-static int __init test_drm_cmdline_init(void)
-{
-       int err;
-
-       err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
-
-       return err > 0 ? 0 : err;
-}
-module_init(test_drm_cmdline_init);
-
-MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
deleted file mode 100644 (file)
index 816e146..0000000
+++ /dev/null
@@ -1,668 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test case for drm_damage_helper functions
- */
-
-#define pr_fmt(fmt) "drm_damage_helper: " fmt
-
-#include <drm/drm_damage_helper.h>
-#include <drm/drm_framebuffer.h>
-#include <drm/drm_plane.h>
-#include <drm/drm_drv.h>
-
-#include "test-drm_modeset_common.h"
-
-struct drm_driver mock_driver;
-static struct drm_device mock_device;
-static struct drm_object_properties mock_obj_props;
-static struct drm_plane mock_plane;
-static struct drm_property mock_prop;
-
-static void mock_setup(struct drm_plane_state *state)
-{
-       static bool setup_done = false;
-
-       state->plane = &mock_plane;
-
-       if (setup_done)
-               return;
-
-       /* just enough so that drm_plane_enable_fb_damage_clips() works */
-       mock_device.driver = &mock_driver;
-       mock_device.mode_config.prop_fb_damage_clips = &mock_prop;
-       mock_plane.dev = &mock_device;
-       mock_obj_props.count = 0;
-       mock_plane.base.properties = &mock_obj_props;
-       mock_prop.base.id = 1; /* 0 is an invalid id */
-       mock_prop.dev = &mock_device;
-
-       drm_plane_enable_fb_damage_clips(&mock_plane);
-}
-
-static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
-                         int y2)
-{
-       state->src.x1 = x1;
-       state->src.y1 = y1;
-       state->src.x2 = x2;
-       state->src.y2 = y2;
-}
-
-static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2,
-                           int y2)
-{
-       r->x1 = x1;
-       r->y1 = y1;
-       r->x2 = x2;
-       r->y2 = y2;
-}
-
-static void set_damage_blob(struct drm_property_blob *damage_blob,
-                           struct drm_mode_rect *r, uint32_t size)
-{
-       damage_blob->length = size;
-       damage_blob->data = r;
-}
-
-static void set_plane_damage(struct drm_plane_state *state,
-                            struct drm_property_blob *damage_blob)
-{
-       state->fb_damage_clips = damage_blob;
-}
-
-static bool check_damage_clip(struct drm_plane_state *state, struct drm_rect *r,
-                             int x1, int y1, int x2, int y2)
-{
-       /*
-        * Round down x1/y1 and round up x2/y2. This is because damage is not in
-        * 16.16 fixed point so to catch all pixels.
-        */
-       int src_x1 = state->src.x1 >> 16;
-       int src_y1 = state->src.y1 >> 16;
-       int src_x2 = (state->src.x2 >> 16) + !!(state->src.x2 & 0xFFFF);
-       int src_y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
-
-       if (x1 >= x2 || y1 >= y2) {
-               pr_err("Cannot have damage clip with no dimension.\n");
-               return false;
-       }
-
-       if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2) {
-               pr_err("Damage cannot be outside rounded plane src.\n");
-               return false;
-       }
-
-       if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2) {
-               pr_err("Damage = %d %d %d %d\n", r->x1, r->y1, r->x2, r->y2);
-               return false;
-       }
-
-       return true;
-}
-
-const struct drm_framebuffer fb = {
-       .width = 2048,
-       .height = 2048
-};
-
-/* common mocked structs many tests need */
-#define MOCK_VARIABLES() \
-       struct drm_plane_state old_state; \
-       struct drm_plane_state state = { \
-               .crtc = ZERO_SIZE_PTR, \
-               .fb = (struct drm_framebuffer *) &fb, \
-               .visible = true, \
-       }; \
-       mock_setup(&old_state); \
-       mock_setup(&state);
-
-int igt_damage_iter_no_damage(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src same as fb size. */
-       set_plane_src(&old_state, 0, 0, fb.width << 16, fb.height << 16);
-       set_plane_src(&state, 0, 0, fb.width << 16, fb.height << 16);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 2048, 2048));
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_fractional_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src has fractional part. */
-       set_plane_src(&old_state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       set_plane_src(&state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return rounded off plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_src_moved(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src moved since old plane state. */
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 10 << 16, 10 << 16,
-                     (10 + 1024) << 16, (10 + 768) << 16);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_fractional_src_moved(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src has fractional part and it moved since old plane state. */
-       set_plane_src(&old_state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_not_visible(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       state.visible = false;
-
-       mock_setup(&old_state);
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should have no damage.");
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_no_crtc(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       state.crtc = NULL;
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should have no damage.");
-
-       return 0;
-}
-
-int igt_damage_iter_no_damage_no_fb(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_plane_state old_state;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       struct drm_plane_state state = {
-               .crtc = ZERO_SIZE_PTR,
-               .fb = 0,
-       };
-
-       mock_setup(&old_state);
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should have no damage.");
-
-       return 0;
-}
-
-int igt_damage_iter_simple_damage(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       /* Damage set to plane src */
-       set_damage_clip(&damage, 0, 0, 1024, 768);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage when set.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 0, 0, 1024, 768));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       set_damage_clip(&damage, 256, 192, 768, 576);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage when set.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 768, 576));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_intersect_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       /* Damage intersect with plane src. */
-       set_damage_clip(&damage, 256, 192, 1360, 768);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage clipped to src.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 256, 192, 1024, 768));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_outside_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       /* Damage clip outside plane src */
-       set_damage_clip(&damage, 1360, 1360, 1380, 1380);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should have no damage.");
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_fractional_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src has fractional part. */
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_damage_clip(&damage, 10, 10, 256, 330);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage when set.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 256, 330));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src has fractional part. */
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       /* Damage intersect with plane src. */
-       set_damage_clip(&damage, 10, 1, 1360, 330);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage clipped to rounded off src.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 10, 4, 1029, 330));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_outside_fractional_src(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src has fractional part. */
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       /* Damage clip outside plane src */
-       set_damage_clip(&damage, 1360, 1360, 1380, 1380);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should have no damage.");
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_src_moved(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src moved since old plane state. */
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 10 << 16, 10 << 16,
-                     (10 + 1024) << 16, (10 + 768) << 16);
-       set_damage_clip(&damage, 20, 30, 256, 256);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 10, 10, 1034, 778));
-
-       return 0;
-}
-
-int igt_damage_iter_single_damage_fractional_src_moved(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage;
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       /* Plane src with fractional part moved since old plane state. */
-       set_plane_src(&old_state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       /* Damage intersect with plane src. */
-       set_damage_clip(&damage, 20, 30, 1360, 256);
-       set_damage_blob(&damage_blob, &damage, sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return rounded off plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
-
-       return 0;
-}
-
-int igt_damage_iter_damage(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage[2];
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       /* 2 damage clips. */
-       set_damage_clip(&damage[0], 20, 30, 200, 180);
-       set_damage_clip(&damage[1], 240, 200, 280, 250);
-       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip) {
-               if (num_hits == 0)
-                       FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180));
-               if (num_hits == 1)
-                       FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250));
-               num_hits++;
-       }
-
-       FAIL(num_hits != 2, "Should return damage when set.");
-
-       return 0;
-}
-
-int igt_damage_iter_damage_one_intersect(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage[2];
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       /* 2 damage clips, one intersect plane src. */
-       set_damage_clip(&damage[0], 20, 30, 200, 180);
-       set_damage_clip(&damage[1], 2, 2, 1360, 1360);
-       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip) {
-               if (num_hits == 0)
-                       FAIL_ON(!check_damage_clip(&state, &clip, 20, 30, 200, 180));
-               if (num_hits == 1)
-                       FAIL_ON(!check_damage_clip(&state, &clip, 4, 4, 1029, 773));
-               num_hits++;
-       }
-
-       FAIL(num_hits != 2, "Should return damage when set.");
-
-       return 0;
-}
-
-int igt_damage_iter_damage_one_outside(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage[2];
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0, 0, 1024 << 16, 768 << 16);
-       set_plane_src(&state, 0, 0, 1024 << 16, 768 << 16);
-       /* 2 damage clips, one outside plane src. */
-       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
-       set_damage_clip(&damage[1], 240, 200, 280, 250);
-       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return damage when set.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 240, 200, 280, 250));
-
-       return 0;
-}
-
-int igt_damage_iter_damage_src_moved(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage[2];
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       /* 2 damage clips, one outside plane src. */
-       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
-       set_damage_clip(&damage[1], 240, 200, 280, 250);
-       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 1, "Should return round off plane src as damage.");
-       FAIL_ON(!check_damage_clip(&state, &clip, 3, 3, 1028, 772));
-
-       return 0;
-}
-
-int igt_damage_iter_damage_not_visible(void *ignored)
-{
-       struct drm_atomic_helper_damage_iter iter;
-       struct drm_property_blob damage_blob;
-       struct drm_mode_rect damage[2];
-       struct drm_rect clip;
-       uint32_t num_hits = 0;
-
-       MOCK_VARIABLES();
-
-       state.visible = false;
-
-       set_plane_src(&old_state, 0x40002, 0x40002,
-                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
-       set_plane_src(&state, 0x3fffe, 0x3fffe,
-                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
-       /* 2 damage clips, one outside plane src. */
-       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
-       set_damage_clip(&damage[1], 240, 200, 280, 250);
-       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
-       set_plane_damage(&state, &damage_blob);
-       drm_atomic_helper_damage_iter_init(&iter, &old_state, &state);
-       drm_atomic_for_each_plane_damage(&iter, &clip)
-               num_hits++;
-
-       FAIL(num_hits != 0, "Should not return any damage.");
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c b/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
deleted file mode 100644 (file)
index 4caa9be..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Test cases for the DRM DP MST helpers
- */
-
-#define PREFIX_STR "[drm_dp_mst_helper]"
-
-#include <linux/random.h>
-
-#include <drm/display/drm_dp_mst_helper.h>
-#include <drm/drm_print.h>
-
-#include "../display/drm_dp_mst_topology_internal.h"
-#include "test-drm_modeset_common.h"
-
-int igt_dp_mst_calc_pbn_mode(void *ignored)
-{
-       int pbn, i;
-       const struct {
-               int rate;
-               int bpp;
-               int expected;
-               bool dsc;
-       } test_params[] = {
-               { 154000, 30, 689, false },
-               { 234000, 30, 1047, false },
-               { 297000, 24, 1063, false },
-               { 332880, 24, 50, true },
-               { 324540, 24, 49, true },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(test_params); i++) {
-               pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
-                                          test_params[i].bpp,
-                                          test_params[i].dsc);
-               FAIL(pbn != test_params[i].expected,
-                    "Expected PBN %d for clock %d bpp %d, got %d\n",
-                    test_params[i].expected, test_params[i].rate,
-                    test_params[i].bpp, pbn);
-       }
-
-       return 0;
-}
-
-static bool
-sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
-                      const struct drm_dp_sideband_msg_req_body *out)
-{
-       const struct drm_dp_remote_i2c_read_tx *txin, *txout;
-       int i;
-
-       if (in->req_type != out->req_type)
-               return false;
-
-       switch (in->req_type) {
-       /*
-        * Compare struct members manually for request types which can't be
-        * compared simply using memcmp(). This is because said request types
-        * contain pointers to other allocated structs
-        */
-       case DP_REMOTE_I2C_READ:
-#define IN in->u.i2c_read
-#define OUT out->u.i2c_read
-               if (IN.num_bytes_read != OUT.num_bytes_read ||
-                   IN.num_transactions != OUT.num_transactions ||
-                   IN.port_number != OUT.port_number ||
-                   IN.read_i2c_device_id != OUT.read_i2c_device_id)
-                       return false;
-
-               for (i = 0; i < IN.num_transactions; i++) {
-                       txin = &IN.transactions[i];
-                       txout = &OUT.transactions[i];
-
-                       if (txin->i2c_dev_id != txout->i2c_dev_id ||
-                           txin->no_stop_bit != txout->no_stop_bit ||
-                           txin->num_bytes != txout->num_bytes ||
-                           txin->i2c_transaction_delay !=
-                           txout->i2c_transaction_delay)
-                               return false;
-
-                       if (memcmp(txin->bytes, txout->bytes,
-                                  txin->num_bytes) != 0)
-                               return false;
-               }
-               break;
-#undef IN
-#undef OUT
-
-       case DP_REMOTE_DPCD_WRITE:
-#define IN in->u.dpcd_write
-#define OUT out->u.dpcd_write
-               if (IN.dpcd_address != OUT.dpcd_address ||
-                   IN.num_bytes != OUT.num_bytes ||
-                   IN.port_number != OUT.port_number)
-                       return false;
-
-               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
-#undef IN
-#undef OUT
-
-       case DP_REMOTE_I2C_WRITE:
-#define IN in->u.i2c_write
-#define OUT out->u.i2c_write
-               if (IN.port_number != OUT.port_number ||
-                   IN.write_i2c_device_id != OUT.write_i2c_device_id ||
-                   IN.num_bytes != OUT.num_bytes)
-                       return false;
-
-               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
-#undef IN
-#undef OUT
-
-       default:
-               return memcmp(in, out, sizeof(*in)) == 0;
-       }
-
-       return true;
-}
-
-static bool
-sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
-{
-       struct drm_dp_sideband_msg_req_body *out;
-       struct drm_printer p = drm_err_printer(PREFIX_STR);
-       struct drm_dp_sideband_msg_tx *txmsg;
-       int i, ret;
-       bool result = true;
-
-       out = kzalloc(sizeof(*out), GFP_KERNEL);
-       if (!out)
-               return false;
-
-       txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
-       if (!txmsg) {
-               kfree(out);
-               return false;
-       }
-
-       drm_dp_encode_sideband_req(in, txmsg);
-       ret = drm_dp_decode_sideband_req(txmsg, out);
-       if (ret < 0) {
-               drm_printf(&p, "Failed to decode sideband request: %d\n",
-                          ret);
-               result = false;
-               goto out;
-       }
-
-       if (!sideband_msg_req_equal(in, out)) {
-               drm_printf(&p, "Encode/decode failed, expected:\n");
-               drm_dp_dump_sideband_msg_req_body(in, 1, &p);
-               drm_printf(&p, "Got:\n");
-               drm_dp_dump_sideband_msg_req_body(out, 1, &p);
-               result = false;
-               goto out;
-       }
-
-       switch (in->req_type) {
-       case DP_REMOTE_DPCD_WRITE:
-               kfree(out->u.dpcd_write.bytes);
-               break;
-       case DP_REMOTE_I2C_READ:
-               for (i = 0; i < out->u.i2c_read.num_transactions; i++)
-                       kfree(out->u.i2c_read.transactions[i].bytes);
-               break;
-       case DP_REMOTE_I2C_WRITE:
-               kfree(out->u.i2c_write.bytes);
-               break;
-       }
-
-       /* Clear everything but the req_type for the input */
-       memset(&in->u, 0, sizeof(in->u));
-
-out:
-       kfree(out);
-       kfree(txmsg);
-       return result;
-}
-
-int igt_dp_mst_sideband_msg_req_decode(void *unused)
-{
-       struct drm_dp_sideband_msg_req_body in = { 0 };
-       u8 data[] = { 0xff, 0x0, 0xdd };
-       int i;
-
-#define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
-
-       in.req_type = DP_ENUM_PATH_RESOURCES;
-       in.u.port_num.port_number = 5;
-       DO_TEST();
-
-       in.req_type = DP_POWER_UP_PHY;
-       in.u.port_num.port_number = 5;
-       DO_TEST();
-
-       in.req_type = DP_POWER_DOWN_PHY;
-       in.u.port_num.port_number = 5;
-       DO_TEST();
-
-       in.req_type = DP_ALLOCATE_PAYLOAD;
-       in.u.allocate_payload.number_sdp_streams = 3;
-       for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
-               in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
-       DO_TEST();
-       in.u.allocate_payload.port_number = 0xf;
-       DO_TEST();
-       in.u.allocate_payload.vcpi = 0x7f;
-       DO_TEST();
-       in.u.allocate_payload.pbn = U16_MAX;
-       DO_TEST();
-
-       in.req_type = DP_QUERY_PAYLOAD;
-       in.u.query_payload.port_number = 0xf;
-       DO_TEST();
-       in.u.query_payload.vcpi = 0x7f;
-       DO_TEST();
-
-       in.req_type = DP_REMOTE_DPCD_READ;
-       in.u.dpcd_read.port_number = 0xf;
-       DO_TEST();
-       in.u.dpcd_read.dpcd_address = 0xfedcb;
-       DO_TEST();
-       in.u.dpcd_read.num_bytes = U8_MAX;
-       DO_TEST();
-
-       in.req_type = DP_REMOTE_DPCD_WRITE;
-       in.u.dpcd_write.port_number = 0xf;
-       DO_TEST();
-       in.u.dpcd_write.dpcd_address = 0xfedcb;
-       DO_TEST();
-       in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
-       in.u.dpcd_write.bytes = data;
-       DO_TEST();
-
-       in.req_type = DP_REMOTE_I2C_READ;
-       in.u.i2c_read.port_number = 0xf;
-       DO_TEST();
-       in.u.i2c_read.read_i2c_device_id = 0x7f;
-       DO_TEST();
-       in.u.i2c_read.num_transactions = 3;
-       in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
-       for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
-               in.u.i2c_read.transactions[i].bytes = data;
-               in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
-               in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
-               in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
-       }
-       DO_TEST();
-
-       in.req_type = DP_REMOTE_I2C_WRITE;
-       in.u.i2c_write.port_number = 0xf;
-       DO_TEST();
-       in.u.i2c_write.write_i2c_device_id = 0x7f;
-       DO_TEST();
-       in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
-       in.u.i2c_write.bytes = data;
-       DO_TEST();
-
-       in.req_type = DP_QUERY_STREAM_ENC_STATUS;
-       in.u.enc_status.stream_id = 1;
-       DO_TEST();
-       get_random_bytes(in.u.enc_status.client_id,
-                        sizeof(in.u.enc_status.client_id));
-       DO_TEST();
-       in.u.enc_status.stream_event = 3;
-       DO_TEST();
-       in.u.enc_status.valid_stream_event = 0;
-       DO_TEST();
-       in.u.enc_status.stream_behavior = 3;
-       DO_TEST();
-       in.u.enc_status.valid_stream_behavior = 1;
-       DO_TEST();
-
-#undef DO_TEST
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_format.c b/drivers/gpu/drm/selftests/test-drm_format.c
deleted file mode 100644 (file)
index c5e212a..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_format functions
- */
-
-#define pr_fmt(fmt) "drm_format: " fmt
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-
-#include <drm/drm_fourcc.h>
-
-#include "test-drm_modeset_common.h"
-
-int igt_check_drm_format_block_width(void *ignored)
-{
-       const struct drm_format_info *info = NULL;
-
-       /* Test invalid arguments */
-       FAIL_ON(drm_format_info_block_width(info, 0) != 0);
-       FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-       FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-
-       /* Test 1 plane format */
-       info = drm_format_info(DRM_FORMAT_XRGB4444);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-       FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-       /* Test 2 planes format */
-       info = drm_format_info(DRM_FORMAT_NV12);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 1) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 2) != 0);
-       FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-       /* Test 3 planes format */
-       info = drm_format_info(DRM_FORMAT_YUV422);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 1) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 2) != 1);
-       FAIL_ON(drm_format_info_block_width(info, 3) != 0);
-       FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-       /* Test a tiled format */
-       info = drm_format_info(DRM_FORMAT_X0L0);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_width(info, 0) != 2);
-       FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-       FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-       return 0;
-}
-
-int igt_check_drm_format_block_height(void *ignored)
-{
-       const struct drm_format_info *info = NULL;
-
-       /* Test invalid arguments */
-       FAIL_ON(drm_format_info_block_height(info, 0) != 0);
-       FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-       FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-
-       /* Test 1 plane format */
-       info = drm_format_info(DRM_FORMAT_XRGB4444);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_height(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-       FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
-       /* Test 2 planes format */
-       info = drm_format_info(DRM_FORMAT_NV12);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_height(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 1) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 2) != 0);
-       FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
-       /* Test 3 planes format */
-       info = drm_format_info(DRM_FORMAT_YUV422);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_height(info, 0) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 1) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 2) != 1);
-       FAIL_ON(drm_format_info_block_height(info, 3) != 0);
-       FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
-       /* Test a tiled format */
-       info = drm_format_info(DRM_FORMAT_X0L0);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_block_height(info, 0) != 2);
-       FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-       FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-
-       return 0;
-}
-
-int igt_check_drm_format_min_pitch(void *ignored)
-{
-       const struct drm_format_info *info = NULL;
-
-       /* Test invalid arguments */
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       /* Test 1 plane 8 bits per pixel format */
-       info = drm_format_info(DRM_FORMAT_RGB332);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
-                       (uint64_t)(UINT_MAX - 1));
-
-       /* Test 1 plane 16 bits per pixel format */
-       info = drm_format_info(DRM_FORMAT_XRGB4444);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX * 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
-                       (uint64_t)(UINT_MAX - 1) * 2);
-
-       /* Test 1 plane 24 bits per pixel format */
-       info = drm_format_info(DRM_FORMAT_RGB888);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 3);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 6);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1920);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 3072);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 5760);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 12288);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2013);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX * 3);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
-                       (uint64_t)(UINT_MAX - 1) * 3);
-
-       /* Test 1 plane 32 bits per pixel format */
-       info = drm_format_info(DRM_FORMAT_ABGR8888);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 4);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 8);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 2560);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 4096);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 7680);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 16384);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 2684);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX * 4);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
-                       (uint64_t)(UINT_MAX - 1) * 4);
-
-       /* Test 2 planes format */
-       info = drm_format_info(DRM_FORMAT_NV12);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 640);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 1024);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 1920);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 4096);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 672);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
-                       (uint64_t)UINT_MAX + 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)) !=
-                       (uint64_t)(UINT_MAX - 1));
-       FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) /  2) !=
-                       (uint64_t)(UINT_MAX - 1));
-
-       /* Test 3 planes 8 bits per pixel format */
-       info = drm_format_info(DRM_FORMAT_YUV422);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 3, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 1) != 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 1) != 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 2) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 2) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 640);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 320) != 320);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 320) != 320);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 1024);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 512) != 512);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 512) != 512);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 1920);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 960) != 960);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 960) != 960);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 4096);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 2048) != 2048);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 2048) != 2048);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 671);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 336) != 336);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, 336) != 336);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1) !=
-                       (uint64_t)UINT_MAX / 2 + 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1) !=
-                       (uint64_t)UINT_MAX / 2 + 1);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2) !=
-                       (uint64_t)(UINT_MAX - 1) / 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2) !=
-                       (uint64_t)(UINT_MAX - 1) / 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2) !=
-                       (uint64_t)(UINT_MAX - 1) / 2);
-
-       /* Test tiled format */
-       info = drm_format_info(DRM_FORMAT_X0L2);
-       FAIL_ON(!info);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, -1, 0) != 0);
-       FAIL_ON(drm_format_info_min_pitch(info, 1, 0) != 0);
-
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1) != 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 2) != 4);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 640) != 1280);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1024) != 2048);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 1920) != 3840);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 4096) != 8192);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, 671) != 1342);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX) !=
-                       (uint64_t)UINT_MAX * 2);
-       FAIL_ON(drm_format_info_min_pitch(info, 0, UINT_MAX - 1) !=
-                       (uint64_t)(UINT_MAX - 1) * 2);
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_framebuffer.c b/drivers/gpu/drm/selftests/test-drm_framebuffer.c
deleted file mode 100644 (file)
index f6d6628..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_framebuffer functions
- */
-
-#include <linux/kernel.h>
-
-#include <drm/drm_device.h>
-#include <drm/drm_mode.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_print.h>
-
-#include "../drm_crtc_internal.h"
-
-#include "test-drm_modeset_common.h"
-
-#define MIN_WIDTH 4
-#define MAX_WIDTH 4096
-#define MIN_HEIGHT 4
-#define MAX_HEIGHT 4096
-
-struct drm_framebuffer_test {
-       int buffer_created;
-       struct drm_mode_fb_cmd2 cmd;
-       const char *name;
-};
-
-static struct drm_framebuffer_test createbuffer_tests[] = {
-{ .buffer_created = 1, .name = "ABGR8888 normal sizes",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 max sizes",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 pitch greater than min required",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH + 1, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 pitch less than min required",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH - 1, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Invalid width",
-       .cmd = { .width = MAX_WIDTH + 1, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * (MAX_WIDTH + 1), 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer handle",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 0, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "No pixel format",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = 0,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Width 0",
-       .cmd = { .width = 0, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Height 0",
-       .cmd = { .width = MAX_WIDTH, .height = 0, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 Large buffer offset",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
-                .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
-                .flags = DRM_MODE_FB_MODIFIERS, .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
-                .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
-                .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
-                .handles = { 1, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "NV12 Normal sizes",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .pitches = { 600, 600, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "NV12 Max sizes",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 Invalid pitch",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
-                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 different  modifier per-plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
-                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
-                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
-                                                      DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
-                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 Modifier for inexistent plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
-                              DRM_FORMAT_MOD_SAMSUNG_64_32_TILE },
-                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 0, .name = "NV12 Handle for inexistent plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
-                .handles = { 1, 1, 1 }, .pitches = { 600, 600, 600 },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 Normal sizes",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .pitches = { 600, 300, 300 },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 DRM_MODE_FB_MODIFIERS set without modifier",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .pitches = { 600, 300, 300 },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 Max sizes",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2),
-                                                     DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Invalid pitch",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) - 1,
-                                                     DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 Different pitches",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1,
-                                                     DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH  + MAX_WIDTH * MAX_HEIGHT,
-                                                     MAX_WIDTH  + 2 * MAX_WIDTH * MAX_HEIGHT },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1, DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 1, .name = "YVU420 Valid modifier",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Different modifiers per plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR,
-                              AFBC_FORMAT_MOD_SPARSE },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
-                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE,
-                              AFBC_FORMAT_MOD_SPARSE },
-                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
-       }
-},
-{ .buffer_created = 1, .name = "X0L2 Normal sizes",
-       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 1200, 0, 0 }
-       }
-},
-{ .buffer_created = 1, .name = "X0L2 Max sizes",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH, 0, 0 }
-       }
-},
-{ .buffer_created = 0, .name = "X0L2 Invalid pitch",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH - 1, 0, 0 }
-       }
-},
-{ .buffer_created = 1, .name = "X0L2 Pitch greater than minimum required",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
-       }
-},
-{ .buffer_created = 0, .name = "X0L2 Handle for inexistent plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
-       }
-},
-{ .buffer_created = 1, .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 },
-                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
-       }
-},
-{ .buffer_created = 0, .name = "X0L2 Modifier without DRM_MODE_FB_MODIFIERS set",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
-       }
-},
-{ .buffer_created = 1, .name = "X0L2 Valid modifier",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
-                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
-       }
-},
-{ .buffer_created = 0, .name = "X0L2 Modifier for inexistent plane",
-       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT,
-                .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 },
-                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
-                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
-                .flags = DRM_MODE_FB_MODIFIERS,
-       }
-},
-};
-
-static struct drm_framebuffer *fb_create_mock(struct drm_device *dev,
-                                             struct drm_file *file_priv,
-                                             const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-       int *buffer_created = dev->dev_private;
-       *buffer_created = 1;
-       return ERR_PTR(-EINVAL);
-}
-
-static struct drm_mode_config_funcs mock_config_funcs = {
-       .fb_create = fb_create_mock,
-};
-
-static struct drm_device mock_drm_device = {
-       .mode_config = {
-               .min_width = MIN_WIDTH,
-               .max_width = MAX_WIDTH,
-               .min_height = MIN_HEIGHT,
-               .max_height = MAX_HEIGHT,
-               .funcs = &mock_config_funcs,
-       },
-};
-
-static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r)
-{
-       int buffer_created = 0;
-
-       mock_drm_device.dev_private = &buffer_created;
-       drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
-       return buffer_created;
-}
-
-int igt_check_drm_framebuffer_create(void *ignored)
-{
-       int i = 0;
-
-       for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) {
-               FAIL(createbuffer_tests[i].buffer_created !=
-                               execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd),
-                    "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name);
-       }
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c
deleted file mode 100644 (file)
index b768b53..0000000
+++ /dev/null
@@ -1,2487 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Test cases for the drm_mm range manager
- */
-
-#define pr_fmt(fmt) "drm_mm: " fmt
-
-#include <linux/module.h>
-#include <linux/prime_numbers.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/vmalloc.h>
-#include <linux/ktime.h>
-
-#include <drm/drm_mm.h>
-
-#include "../lib/drm_random.h"
-
-#define TESTS "drm_mm_selftests.h"
-#include "drm_selftest.h"
-
-static unsigned int random_seed;
-static unsigned int max_iterations = 8192;
-static unsigned int max_prime = 128;
-
-enum {
-       BEST,
-       BOTTOMUP,
-       TOPDOWN,
-       EVICT,
-};
-
-static const struct insert_mode {
-       const char *name;
-       enum drm_mm_insert_mode mode;
-} insert_modes[] = {
-       [BEST] = { "best", DRM_MM_INSERT_BEST },
-       [BOTTOMUP] = { "bottom-up", DRM_MM_INSERT_LOW },
-       [TOPDOWN] = { "top-down", DRM_MM_INSERT_HIGH },
-       [EVICT] = { "evict", DRM_MM_INSERT_EVICT },
-       {}
-}, evict_modes[] = {
-       { "bottom-up", DRM_MM_INSERT_LOW },
-       { "top-down", DRM_MM_INSERT_HIGH },
-       {}
-};
-
-static int igt_sanitycheck(void *ignored)
-{
-       pr_info("%s - ok!\n", __func__);
-       return 0;
-}
-
-static bool assert_no_holes(const struct drm_mm *mm)
-{
-       struct drm_mm_node *hole;
-       u64 hole_start, __always_unused hole_end;
-       unsigned long count;
-
-       count = 0;
-       drm_mm_for_each_hole(hole, mm, hole_start, hole_end)
-               count++;
-       if (count) {
-               pr_err("Expected to find no holes (after reserve), found %lu instead\n", count);
-               return false;
-       }
-
-       drm_mm_for_each_node(hole, mm) {
-               if (drm_mm_hole_follows(hole)) {
-                       pr_err("Hole follows node, expected none!\n");
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static bool assert_one_hole(const struct drm_mm *mm, u64 start, u64 end)
-{
-       struct drm_mm_node *hole;
-       u64 hole_start, hole_end;
-       unsigned long count;
-       bool ok = true;
-
-       if (end <= start)
-               return true;
-
-       count = 0;
-       drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
-               if (start != hole_start || end != hole_end) {
-                       if (ok)
-                               pr_err("empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n",
-                                      hole_start, hole_end,
-                                      start, end);
-                       ok = false;
-               }
-               count++;
-       }
-       if (count != 1) {
-               pr_err("Expected to find one hole, found %lu instead\n", count);
-               ok = false;
-       }
-
-       return ok;
-}
-
-static bool assert_continuous(const struct drm_mm *mm, u64 size)
-{
-       struct drm_mm_node *node, *check, *found;
-       unsigned long n;
-       u64 addr;
-
-       if (!assert_no_holes(mm))
-               return false;
-
-       n = 0;
-       addr = 0;
-       drm_mm_for_each_node(node, mm) {
-               if (node->start != addr) {
-                       pr_err("node[%ld] list out of order, expected %llx found %llx\n",
-                              n, addr, node->start);
-                       return false;
-               }
-
-               if (node->size != size) {
-                       pr_err("node[%ld].size incorrect, expected %llx, found %llx\n",
-                              n, size, node->size);
-                       return false;
-               }
-
-               if (drm_mm_hole_follows(node)) {
-                       pr_err("node[%ld] is followed by a hole!\n", n);
-                       return false;
-               }
-
-               found = NULL;
-               drm_mm_for_each_node_in_range(check, mm, addr, addr + size) {
-                       if (node != check) {
-                               pr_err("lookup return wrong node, expected start %llx, found %llx\n",
-                                      node->start, check->start);
-                               return false;
-                       }
-                       found = check;
-               }
-               if (!found) {
-                       pr_err("lookup failed for node %llx + %llx\n",
-                              addr, size);
-                       return false;
-               }
-
-               addr += size;
-               n++;
-       }
-
-       return true;
-}
-
-static u64 misalignment(struct drm_mm_node *node, u64 alignment)
-{
-       u64 rem;
-
-       if (!alignment)
-               return 0;
-
-       div64_u64_rem(node->start, alignment, &rem);
-       return rem;
-}
-
-static bool assert_node(struct drm_mm_node *node, struct drm_mm *mm,
-                       u64 size, u64 alignment, unsigned long color)
-{
-       bool ok = true;
-
-       if (!drm_mm_node_allocated(node) || node->mm != mm) {
-               pr_err("node not allocated\n");
-               ok = false;
-       }
-
-       if (node->size != size) {
-               pr_err("node has wrong size, found %llu, expected %llu\n",
-                      node->size, size);
-               ok = false;
-       }
-
-       if (misalignment(node, alignment)) {
-               pr_err("node is misaligned, start %llx rem %llu, expected alignment %llu\n",
-                      node->start, misalignment(node, alignment), alignment);
-               ok = false;
-       }
-
-       if (node->color != color) {
-               pr_err("node has wrong color, found %lu, expected %lu\n",
-                      node->color, color);
-               ok = false;
-       }
-
-       return ok;
-}
-
-#define show_mm(mm) do { \
-       struct drm_printer __p = drm_debug_printer(__func__); \
-       drm_mm_print((mm), &__p); } while (0)
-
-static int igt_init(void *ignored)
-{
-       const unsigned int size = 4096;
-       struct drm_mm mm;
-       struct drm_mm_node tmp;
-       int ret = -EINVAL;
-
-       /* Start with some simple checks on initialising the struct drm_mm */
-       memset(&mm, 0, sizeof(mm));
-       if (drm_mm_initialized(&mm)) {
-               pr_err("zeroed mm claims to be initialized\n");
-               return ret;
-       }
-
-       memset(&mm, 0xff, sizeof(mm));
-       drm_mm_init(&mm, 0, size);
-       if (!drm_mm_initialized(&mm)) {
-               pr_err("mm claims not to be initialized\n");
-               goto out;
-       }
-
-       if (!drm_mm_clean(&mm)) {
-               pr_err("mm not empty on creation\n");
-               goto out;
-       }
-
-       /* After creation, it should all be one massive hole */
-       if (!assert_one_hole(&mm, 0, size)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.start = 0;
-       tmp.size = size;
-       ret = drm_mm_reserve_node(&mm, &tmp);
-       if (ret) {
-               pr_err("failed to reserve whole drm_mm\n");
-               goto out;
-       }
-
-       /* After filling the range entirely, there should be no holes */
-       if (!assert_no_holes(&mm)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /* And then after emptying it again, the massive hole should be back */
-       drm_mm_remove_node(&tmp);
-       if (!assert_one_hole(&mm, 0, size)) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-out:
-       if (ret)
-               show_mm(&mm);
-       drm_mm_takedown(&mm);
-       return ret;
-}
-
-static int igt_debug(void *ignored)
-{
-       struct drm_mm mm;
-       struct drm_mm_node nodes[2];
-       int ret;
-
-       /* Create a small drm_mm with a couple of nodes and a few holes, and
-        * check that the debug iterator doesn't explode over a trivial drm_mm.
-        */
-
-       drm_mm_init(&mm, 0, 4096);
-
-       memset(nodes, 0, sizeof(nodes));
-       nodes[0].start = 512;
-       nodes[0].size = 1024;
-       ret = drm_mm_reserve_node(&mm, &nodes[0]);
-       if (ret) {
-               pr_err("failed to reserve node[0] {start=%lld, size=%lld)\n",
-                      nodes[0].start, nodes[0].size);
-               return ret;
-       }
-
-       nodes[1].size = 1024;
-       nodes[1].start = 4096 - 512 - nodes[1].size;
-       ret = drm_mm_reserve_node(&mm, &nodes[1]);
-       if (ret) {
-               pr_err("failed to reserve node[1] {start=%lld, size=%lld)\n",
-                      nodes[1].start, nodes[1].size);
-               return ret;
-       }
-
-       show_mm(&mm);
-       return 0;
-}
-
-static struct drm_mm_node *set_node(struct drm_mm_node *node,
-                                   u64 start, u64 size)
-{
-       node->start = start;
-       node->size = size;
-       return node;
-}
-
-static bool expect_reserve_fail(struct drm_mm *mm, struct drm_mm_node *node)
-{
-       int err;
-
-       err = drm_mm_reserve_node(mm, node);
-       if (likely(err == -ENOSPC))
-               return true;
-
-       if (!err) {
-               pr_err("impossible reserve succeeded, node %llu + %llu\n",
-                      node->start, node->size);
-               drm_mm_remove_node(node);
-       } else {
-               pr_err("impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n",
-                      err, -ENOSPC, node->start, node->size);
-       }
-       return false;
-}
-
-static bool check_reserve_boundaries(struct drm_mm *mm,
-                                    unsigned int count,
-                                    u64 size)
-{
-       const struct boundary {
-               u64 start, size;
-               const char *name;
-       } boundaries[] = {
-#define B(st, sz) { (st), (sz), "{ " #st ", " #sz "}" }
-               B(0, 0),
-               B(-size, 0),
-               B(size, 0),
-               B(size * count, 0),
-               B(-size, size),
-               B(-size, -size),
-               B(-size, 2*size),
-               B(0, -size),
-               B(size, -size),
-               B(count*size, size),
-               B(count*size, -size),
-               B(count*size, count*size),
-               B(count*size, -count*size),
-               B(count*size, -(count+1)*size),
-               B((count+1)*size, size),
-               B((count+1)*size, -size),
-               B((count+1)*size, -2*size),
-#undef B
-       };
-       struct drm_mm_node tmp = {};
-       int n;
-
-       for (n = 0; n < ARRAY_SIZE(boundaries); n++) {
-               if (!expect_reserve_fail(mm,
-                                        set_node(&tmp,
-                                                 boundaries[n].start,
-                                                 boundaries[n].size))) {
-                       pr_err("boundary[%d:%s] failed, count=%u, size=%lld\n",
-                              n, boundaries[n].name, count, size);
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static int __igt_reserve(unsigned int count, u64 size)
-{
-       DRM_RND_STATE(prng, random_seed);
-       struct drm_mm mm;
-       struct drm_mm_node tmp, *nodes, *node, *next;
-       unsigned int *order, n, m, o = 0;
-       int ret, err;
-
-       /* For exercising drm_mm_reserve_node(), we want to check that
-        * reservations outside of the drm_mm range are rejected, and to
-        * overlapping and otherwise already occupied ranges. Afterwards,
-        * the tree and nodes should be intact.
-        */
-
-       DRM_MM_BUG_ON(!count);
-       DRM_MM_BUG_ON(!size);
-
-       ret = -ENOMEM;
-       order = drm_random_order(count, &prng);
-       if (!order)
-               goto err;
-
-       nodes = vzalloc(array_size(count, sizeof(*nodes)));
-       if (!nodes)
-               goto err_order;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, count * size);
-
-       if (!check_reserve_boundaries(&mm, count, size))
-               goto out;
-
-       for (n = 0; n < count; n++) {
-               nodes[n].start = order[n] * size;
-               nodes[n].size = size;
-
-               err = drm_mm_reserve_node(&mm, &nodes[n]);
-               if (err) {
-                       pr_err("reserve failed, step %d, start %llu\n",
-                              n, nodes[n].start);
-                       ret = err;
-                       goto out;
-               }
-
-               if (!drm_mm_node_allocated(&nodes[n])) {
-                       pr_err("reserved node not allocated! step %d, start %llu\n",
-                              n, nodes[n].start);
-                       goto out;
-               }
-
-               if (!expect_reserve_fail(&mm, &nodes[n]))
-                       goto out;
-       }
-
-       /* After random insertion the nodes should be in order */
-       if (!assert_continuous(&mm, size))
-               goto out;
-
-       /* Repeated use should then fail */
-       drm_random_reorder(order, count, &prng);
-       for (n = 0; n < count; n++) {
-               if (!expect_reserve_fail(&mm,
-                                        set_node(&tmp, order[n] * size, 1)))
-                       goto out;
-
-               /* Remove and reinsert should work */
-               drm_mm_remove_node(&nodes[order[n]]);
-               err = drm_mm_reserve_node(&mm, &nodes[order[n]]);
-               if (err) {
-                       pr_err("reserve failed, step %d, start %llu\n",
-                              n, nodes[n].start);
-                       ret = err;
-                       goto out;
-               }
-       }
-
-       if (!assert_continuous(&mm, size))
-               goto out;
-
-       /* Overlapping use should then fail */
-       for (n = 0; n < count; n++) {
-               if (!expect_reserve_fail(&mm, set_node(&tmp, 0, size*count)))
-                       goto out;
-       }
-       for (n = 0; n < count; n++) {
-               if (!expect_reserve_fail(&mm,
-                                        set_node(&tmp,
-                                                 size * n,
-                                                 size * (count - n))))
-                       goto out;
-       }
-
-       /* Remove several, reinsert, check full */
-       for_each_prime_number(n, min(max_prime, count)) {
-               for (m = 0; m < n; m++) {
-                       node = &nodes[order[(o + m) % count]];
-                       drm_mm_remove_node(node);
-               }
-
-               for (m = 0; m < n; m++) {
-                       node = &nodes[order[(o + m) % count]];
-                       err = drm_mm_reserve_node(&mm, node);
-                       if (err) {
-                               pr_err("reserve failed, step %d/%d, start %llu\n",
-                                      m, n, node->start);
-                               ret = err;
-                               goto out;
-                       }
-               }
-
-               o += n;
-
-               if (!assert_continuous(&mm, size))
-                       goto out;
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       vfree(nodes);
-err_order:
-       kfree(order);
-err:
-       return ret;
-}
-
-static int igt_reserve(void *ignored)
-{
-       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
-       int n, ret;
-
-       for_each_prime_number_from(n, 1, 54) {
-               u64 size = BIT_ULL(n);
-
-               ret = __igt_reserve(count, size - 1);
-               if (ret)
-                       return ret;
-
-               ret = __igt_reserve(count, size);
-               if (ret)
-                       return ret;
-
-               ret = __igt_reserve(count, size + 1);
-               if (ret)
-                       return ret;
-
-               cond_resched();
-       }
-
-       return 0;
-}
-
-static bool expect_insert(struct drm_mm *mm, struct drm_mm_node *node,
-                         u64 size, u64 alignment, unsigned long color,
-                         const struct insert_mode *mode)
-{
-       int err;
-
-       err = drm_mm_insert_node_generic(mm, node,
-                                        size, alignment, color,
-                                        mode->mode);
-       if (err) {
-               pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n",
-                      size, alignment, color, mode->name, err);
-               return false;
-       }
-
-       if (!assert_node(node, mm, size, alignment, color)) {
-               drm_mm_remove_node(node);
-               return false;
-       }
-
-       return true;
-}
-
-static bool expect_insert_fail(struct drm_mm *mm, u64 size)
-{
-       struct drm_mm_node tmp = {};
-       int err;
-
-       err = drm_mm_insert_node(mm, &tmp, size);
-       if (likely(err == -ENOSPC))
-               return true;
-
-       if (!err) {
-               pr_err("impossible insert succeeded, node %llu + %llu\n",
-                      tmp.start, tmp.size);
-               drm_mm_remove_node(&tmp);
-       } else {
-               pr_err("impossible insert failed with wrong error %d [expected %d], size %llu\n",
-                      err, -ENOSPC, size);
-       }
-       return false;
-}
-
-static int __igt_insert(unsigned int count, u64 size, bool replace)
-{
-       DRM_RND_STATE(prng, random_seed);
-       const struct insert_mode *mode;
-       struct drm_mm mm;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int *order, n, m, o = 0;
-       int ret;
-
-       /* Fill a range with lots of nodes, check it doesn't fail too early */
-
-       DRM_MM_BUG_ON(!count);
-       DRM_MM_BUG_ON(!size);
-
-       ret = -ENOMEM;
-       nodes = vmalloc(array_size(count, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       order = drm_random_order(count, &prng);
-       if (!order)
-               goto err_nodes;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, count * size);
-
-       for (mode = insert_modes; mode->name; mode++) {
-               for (n = 0; n < count; n++) {
-                       struct drm_mm_node tmp;
-
-                       node = replace ? &tmp : &nodes[n];
-                       memset(node, 0, sizeof(*node));
-                       if (!expect_insert(&mm, node, size, 0, n, mode)) {
-                               pr_err("%s insert failed, size %llu step %d\n",
-                                      mode->name, size, n);
-                               goto out;
-                       }
-
-                       if (replace) {
-                               drm_mm_replace_node(&tmp, &nodes[n]);
-                               if (drm_mm_node_allocated(&tmp)) {
-                                       pr_err("replaced old-node still allocated! step %d\n",
-                                              n);
-                                       goto out;
-                               }
-
-                               if (!assert_node(&nodes[n], &mm, size, 0, n)) {
-                                       pr_err("replaced node did not inherit parameters, size %llu step %d\n",
-                                              size, n);
-                                       goto out;
-                               }
-
-                               if (tmp.start != nodes[n].start) {
-                                       pr_err("replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n",
-                                              tmp.start, size,
-                                              nodes[n].start, nodes[n].size);
-                                       goto out;
-                               }
-                       }
-               }
-
-               /* After random insertion the nodes should be in order */
-               if (!assert_continuous(&mm, size))
-                       goto out;
-
-               /* Repeated use should then fail */
-               if (!expect_insert_fail(&mm, size))
-                       goto out;
-
-               /* Remove one and reinsert, as the only hole it should refill itself */
-               for (n = 0; n < count; n++) {
-                       u64 addr = nodes[n].start;
-
-                       drm_mm_remove_node(&nodes[n]);
-                       if (!expect_insert(&mm, &nodes[n], size, 0, n, mode)) {
-                               pr_err("%s reinsert failed, size %llu step %d\n",
-                                      mode->name, size, n);
-                               goto out;
-                       }
-
-                       if (nodes[n].start != addr) {
-                               pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n",
-                                      mode->name, n, addr, nodes[n].start);
-                               goto out;
-                       }
-
-                       if (!assert_continuous(&mm, size))
-                               goto out;
-               }
-
-               /* Remove several, reinsert, check full */
-               for_each_prime_number(n, min(max_prime, count)) {
-                       for (m = 0; m < n; m++) {
-                               node = &nodes[order[(o + m) % count]];
-                               drm_mm_remove_node(node);
-                       }
-
-                       for (m = 0; m < n; m++) {
-                               node = &nodes[order[(o + m) % count]];
-                               if (!expect_insert(&mm, node, size, 0, n, mode)) {
-                                       pr_err("%s multiple reinsert failed, size %llu step %d\n",
-                                              mode->name, size, n);
-                                       goto out;
-                               }
-                       }
-
-                       o += n;
-
-                       if (!assert_continuous(&mm, size))
-                               goto out;
-
-                       if (!expect_insert_fail(&mm, size))
-                               goto out;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int igt_insert(void *ignored)
-{
-       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
-       unsigned int n;
-       int ret;
-
-       for_each_prime_number_from(n, 1, 54) {
-               u64 size = BIT_ULL(n);
-
-               ret = __igt_insert(count, size - 1, false);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert(count, size, false);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert(count, size + 1, false);
-               if (ret)
-                       return ret;
-
-               cond_resched();
-       }
-
-       return 0;
-}
-
-static int igt_replace(void *ignored)
-{
-       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
-       unsigned int n;
-       int ret;
-
-       /* Reuse igt_insert to exercise replacement by inserting a dummy node,
-        * then replacing it with the intended node. We want to check that
-        * the tree is intact and all the information we need is carried
-        * across to the target node.
-        */
-
-       for_each_prime_number_from(n, 1, 54) {
-               u64 size = BIT_ULL(n);
-
-               ret = __igt_insert(count, size - 1, true);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert(count, size, true);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert(count, size + 1, true);
-               if (ret)
-                       return ret;
-
-               cond_resched();
-       }
-
-       return 0;
-}
-
-static bool expect_insert_in_range(struct drm_mm *mm, struct drm_mm_node *node,
-                                  u64 size, u64 alignment, unsigned long color,
-                                  u64 range_start, u64 range_end,
-                                  const struct insert_mode *mode)
-{
-       int err;
-
-       err = drm_mm_insert_node_in_range(mm, node,
-                                         size, alignment, color,
-                                         range_start, range_end,
-                                         mode->mode);
-       if (err) {
-               pr_err("insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n",
-                      size, alignment, color, mode->name,
-                      range_start, range_end, err);
-               return false;
-       }
-
-       if (!assert_node(node, mm, size, alignment, color)) {
-               drm_mm_remove_node(node);
-               return false;
-       }
-
-       return true;
-}
-
-static bool expect_insert_in_range_fail(struct drm_mm *mm,
-                                       u64 size,
-                                       u64 range_start,
-                                       u64 range_end)
-{
-       struct drm_mm_node tmp = {};
-       int err;
-
-       err = drm_mm_insert_node_in_range(mm, &tmp,
-                                         size, 0, 0,
-                                         range_start, range_end,
-                                         0);
-       if (likely(err == -ENOSPC))
-               return true;
-
-       if (!err) {
-               pr_err("impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n",
-                      tmp.start, tmp.size, range_start, range_end);
-               drm_mm_remove_node(&tmp);
-       } else {
-               pr_err("impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n",
-                      err, -ENOSPC, size, range_start, range_end);
-       }
-
-       return false;
-}
-
-static bool assert_contiguous_in_range(struct drm_mm *mm,
-                                      u64 size,
-                                      u64 start,
-                                      u64 end)
-{
-       struct drm_mm_node *node;
-       unsigned int n;
-
-       if (!expect_insert_in_range_fail(mm, size, start, end))
-               return false;
-
-       n = div64_u64(start + size - 1, size);
-       drm_mm_for_each_node(node, mm) {
-               if (node->start < start || node->start + node->size > end) {
-                       pr_err("node %d out of range, address [%llx + %llu], range [%llx, %llx]\n",
-                              n, node->start, node->start + node->size, start, end);
-                       return false;
-               }
-
-               if (node->start != n * size) {
-                       pr_err("node %d out of order, expected start %llx, found %llx\n",
-                              n, n * size, node->start);
-                       return false;
-               }
-
-               if (node->size != size) {
-                       pr_err("node %d has wrong size, expected size %llx, found %llx\n",
-                              n, size, node->size);
-                       return false;
-               }
-
-               if (drm_mm_hole_follows(node) &&
-                   drm_mm_hole_node_end(node) < end) {
-                       pr_err("node %d is followed by a hole!\n", n);
-                       return false;
-               }
-
-               n++;
-       }
-
-       if (start > 0) {
-               node = __drm_mm_interval_first(mm, 0, start - 1);
-               if (drm_mm_node_allocated(node)) {
-                       pr_err("node before start: node=%llx+%llu, start=%llx\n",
-                              node->start, node->size, start);
-                       return false;
-               }
-       }
-
-       if (end < U64_MAX) {
-               node = __drm_mm_interval_first(mm, end, U64_MAX);
-               if (drm_mm_node_allocated(node)) {
-                       pr_err("node after end: node=%llx+%llu, end=%llx\n",
-                              node->start, node->size, end);
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end)
-{
-       const struct insert_mode *mode;
-       struct drm_mm mm;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int n, start_n, end_n;
-       int ret;
-
-       DRM_MM_BUG_ON(!count);
-       DRM_MM_BUG_ON(!size);
-       DRM_MM_BUG_ON(end <= start);
-
-       /* Very similar to __igt_insert(), but now instead of populating the
-        * full range of the drm_mm, we try to fill a small portion of it.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(count, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, count * size);
-
-       start_n = div64_u64(start + size - 1, size);
-       end_n = div64_u64(end - size, size);
-
-       for (mode = insert_modes; mode->name; mode++) {
-               for (n = start_n; n <= end_n; n++) {
-                       if (!expect_insert_in_range(&mm, &nodes[n],
-                                                   size, size, n,
-                                                   start, end, mode)) {
-                               pr_err("%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n",
-                                      mode->name, size, n,
-                                      start_n, end_n,
-                                      start, end);
-                               goto out;
-                       }
-               }
-
-               if (!assert_contiguous_in_range(&mm, size, start, end)) {
-                       pr_err("%s: range [%llx, %llx] not full after initialisation, size=%llu\n",
-                              mode->name, start, end, size);
-                       goto out;
-               }
-
-               /* Remove one and reinsert, it should refill itself */
-               for (n = start_n; n <= end_n; n++) {
-                       u64 addr = nodes[n].start;
-
-                       drm_mm_remove_node(&nodes[n]);
-                       if (!expect_insert_in_range(&mm, &nodes[n],
-                                                   size, size, n,
-                                                   start, end, mode)) {
-                               pr_err("%s reinsert failed, step %d\n", mode->name, n);
-                               goto out;
-                       }
-
-                       if (nodes[n].start != addr) {
-                               pr_err("%s reinsert node moved, step %d, expected %llx, found %llx\n",
-                                      mode->name, n, addr, nodes[n].start);
-                               goto out;
-                       }
-               }
-
-               if (!assert_contiguous_in_range(&mm, size, start, end)) {
-                       pr_err("%s: range [%llx, %llx] not full after reinsertion, size=%llu\n",
-                              mode->name, start, end, size);
-                       goto out;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int insert_outside_range(void)
-{
-       struct drm_mm mm;
-       const unsigned int start = 1024;
-       const unsigned int end = 2048;
-       const unsigned int size = end - start;
-
-       drm_mm_init(&mm, start, size);
-
-       if (!expect_insert_in_range_fail(&mm, 1, 0, start))
-               return -EINVAL;
-
-       if (!expect_insert_in_range_fail(&mm, size,
-                                        start - size/2, start + (size+1)/2))
-               return -EINVAL;
-
-       if (!expect_insert_in_range_fail(&mm, size,
-                                        end - (size+1)/2, end + size/2))
-               return -EINVAL;
-
-       if (!expect_insert_in_range_fail(&mm, 1, end, end + size))
-               return -EINVAL;
-
-       drm_mm_takedown(&mm);
-       return 0;
-}
-
-static int igt_insert_range(void *ignored)
-{
-       const unsigned int count = min_t(unsigned int, BIT(13), max_iterations);
-       unsigned int n;
-       int ret;
-
-       /* Check that requests outside the bounds of drm_mm are rejected. */
-       ret = insert_outside_range();
-       if (ret)
-               return ret;
-
-       for_each_prime_number_from(n, 1, 50) {
-               const u64 size = BIT_ULL(n);
-               const u64 max = count * size;
-
-               ret = __igt_insert_range(count, size, 0, max);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert_range(count, size, 1, max);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert_range(count, size, 0, max - 1);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert_range(count, size, 0, max/2);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert_range(count, size, max/2, max);
-               if (ret)
-                       return ret;
-
-               ret = __igt_insert_range(count, size, max/4+1, 3*max/4-1);
-               if (ret)
-                       return ret;
-
-               cond_resched();
-       }
-
-       return 0;
-}
-
-static int prepare_igt_frag(struct drm_mm *mm,
-                           struct drm_mm_node *nodes,
-                           unsigned int num_insert,
-                           const struct insert_mode *mode)
-{
-       unsigned int size = 4096;
-       unsigned int i;
-
-       for (i = 0; i < num_insert; i++) {
-               if (!expect_insert(mm, &nodes[i], size, 0, i,
-                                  mode) != 0) {
-                       pr_err("%s insert failed\n", mode->name);
-                       return -EINVAL;
-               }
-       }
-
-       /* introduce fragmentation by freeing every other node */
-       for (i = 0; i < num_insert; i++) {
-               if (i % 2 == 0)
-                       drm_mm_remove_node(&nodes[i]);
-       }
-
-       return 0;
-
-}
-
-static u64 get_insert_time(struct drm_mm *mm,
-                          unsigned int num_insert,
-                          struct drm_mm_node *nodes,
-                          const struct insert_mode *mode)
-{
-       unsigned int size = 8192;
-       ktime_t start;
-       unsigned int i;
-
-       start = ktime_get();
-       for (i = 0; i < num_insert; i++) {
-               if (!expect_insert(mm, &nodes[i], size, 0, i, mode) != 0) {
-                       pr_err("%s insert failed\n", mode->name);
-                       return 0;
-               }
-       }
-
-       return ktime_to_ns(ktime_sub(ktime_get(), start));
-}
-
-static int igt_frag(void *ignored)
-{
-       struct drm_mm mm;
-       const struct insert_mode *mode;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int insert_size = 10000;
-       unsigned int scale_factor = 4;
-       int ret = -EINVAL;
-
-       /* We need 4 * insert_size nodes to hold intermediate allocated
-        * drm_mm nodes.
-        * 1 times for prepare_igt_frag()
-        * 1 times for get_insert_time()
-        * 2 times for get_insert_time()
-        */
-       nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes)));
-       if (!nodes)
-               return -ENOMEM;
-
-       /* For BOTTOMUP and TOPDOWN, we first fragment the
-        * address space using prepare_igt_frag() and then try to verify
-        * that that insertions scale quadratically from 10k to 20k insertions
-        */
-       drm_mm_init(&mm, 1, U64_MAX - 2);
-       for (mode = insert_modes; mode->name; mode++) {
-               u64 insert_time1, insert_time2;
-
-               if (mode->mode != DRM_MM_INSERT_LOW &&
-                   mode->mode != DRM_MM_INSERT_HIGH)
-                       continue;
-
-               ret = prepare_igt_frag(&mm, nodes, insert_size, mode);
-               if (ret)
-                       goto err;
-
-               insert_time1 = get_insert_time(&mm, insert_size,
-                                              nodes + insert_size, mode);
-               if (insert_time1 == 0)
-                       goto err;
-
-               insert_time2 = get_insert_time(&mm, (insert_size * 2),
-                                              nodes + insert_size * 2, mode);
-               if (insert_time2 == 0)
-                       goto err;
-
-               pr_info("%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n",
-                       mode->name, insert_size, insert_size * 2,
-                       insert_time1, insert_time2);
-
-               if (insert_time2 > (scale_factor * insert_time1)) {
-                       pr_err("%s fragmented insert took %llu nsecs more\n",
-                              mode->name,
-                              insert_time2 - (scale_factor * insert_time1));
-                       goto err;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-       }
-
-       ret = 0;
-err:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       vfree(nodes);
-
-       return ret;
-}
-
-static int igt_align(void *ignored)
-{
-       const struct insert_mode *mode;
-       const unsigned int max_count = min(8192u, max_prime);
-       struct drm_mm mm;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int prime;
-       int ret = -EINVAL;
-
-       /* For each of the possible insertion modes, we pick a few
-        * arbitrary alignments and check that the inserted node
-        * meets our requirements.
-        */
-
-       nodes = vzalloc(array_size(max_count, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       drm_mm_init(&mm, 1, U64_MAX - 2);
-
-       for (mode = insert_modes; mode->name; mode++) {
-               unsigned int i = 0;
-
-               for_each_prime_number_from(prime, 1, max_count) {
-                       u64 size = next_prime_number(prime);
-
-                       if (!expect_insert(&mm, &nodes[i],
-                                          size, prime, i,
-                                          mode)) {
-                               pr_err("%s insert failed with alignment=%d",
-                                      mode->name, prime);
-                               goto out;
-                       }
-
-                       i++;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int igt_align_pot(int max)
-{
-       struct drm_mm mm;
-       struct drm_mm_node *node, *next;
-       int bit;
-       int ret = -EINVAL;
-
-       /* Check that we can align to the full u64 address space */
-
-       drm_mm_init(&mm, 1, U64_MAX - 2);
-
-       for (bit = max - 1; bit; bit--) {
-               u64 align, size;
-
-               node = kzalloc(sizeof(*node), GFP_KERNEL);
-               if (!node) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               align = BIT_ULL(bit);
-               size = BIT_ULL(bit-1) + 1;
-               if (!expect_insert(&mm, node,
-                                  size, align, bit,
-                                  &insert_modes[0])) {
-                       pr_err("insert failed with alignment=%llx [%d]",
-                              align, bit);
-                       goto out;
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm) {
-               drm_mm_remove_node(node);
-               kfree(node);
-       }
-       drm_mm_takedown(&mm);
-       return ret;
-}
-
-static int igt_align32(void *ignored)
-{
-       return igt_align_pot(32);
-}
-
-static int igt_align64(void *ignored)
-{
-       return igt_align_pot(64);
-}
-
-static void show_scan(const struct drm_mm_scan *scan)
-{
-       pr_info("scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n",
-               scan->hit_start, scan->hit_end,
-               scan->size, scan->alignment, scan->color);
-}
-
-static void show_holes(const struct drm_mm *mm, int count)
-{
-       u64 hole_start, hole_end;
-       struct drm_mm_node *hole;
-
-       drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
-               struct drm_mm_node *next = list_next_entry(hole, node_list);
-               const char *node1 = NULL, *node2 = NULL;
-
-               if (drm_mm_node_allocated(hole))
-                       node1 = kasprintf(GFP_KERNEL,
-                                         "[%llx + %lld, color=%ld], ",
-                                         hole->start, hole->size, hole->color);
-
-               if (drm_mm_node_allocated(next))
-                       node2 = kasprintf(GFP_KERNEL,
-                                         ", [%llx + %lld, color=%ld]",
-                                         next->start, next->size, next->color);
-
-               pr_info("%sHole [%llx - %llx, size %lld]%s\n",
-                       node1,
-                       hole_start, hole_end, hole_end - hole_start,
-                       node2);
-
-               kfree(node2);
-               kfree(node1);
-
-               if (!--count)
-                       break;
-       }
-}
-
-struct evict_node {
-       struct drm_mm_node node;
-       struct list_head link;
-};
-
-static bool evict_nodes(struct drm_mm_scan *scan,
-                       struct evict_node *nodes,
-                       unsigned int *order,
-                       unsigned int count,
-                       bool use_color,
-                       struct list_head *evict_list)
-{
-       struct evict_node *e, *en;
-       unsigned int i;
-
-       for (i = 0; i < count; i++) {
-               e = &nodes[order ? order[i] : i];
-               list_add(&e->link, evict_list);
-               if (drm_mm_scan_add_block(scan, &e->node))
-                       break;
-       }
-       list_for_each_entry_safe(e, en, evict_list, link) {
-               if (!drm_mm_scan_remove_block(scan, &e->node))
-                       list_del(&e->link);
-       }
-       if (list_empty(evict_list)) {
-               pr_err("Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n",
-                      scan->size, count, scan->alignment, scan->color);
-               return false;
-       }
-
-       list_for_each_entry(e, evict_list, link)
-               drm_mm_remove_node(&e->node);
-
-       if (use_color) {
-               struct drm_mm_node *node;
-
-               while ((node = drm_mm_scan_color_evict(scan))) {
-                       e = container_of(node, typeof(*e), node);
-                       drm_mm_remove_node(&e->node);
-                       list_add(&e->link, evict_list);
-               }
-       } else {
-               if (drm_mm_scan_color_evict(scan)) {
-                       pr_err("drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n");
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-static bool evict_nothing(struct drm_mm *mm,
-                         unsigned int total_size,
-                         struct evict_node *nodes)
-{
-       struct drm_mm_scan scan;
-       LIST_HEAD(evict_list);
-       struct evict_node *e;
-       struct drm_mm_node *node;
-       unsigned int n;
-
-       drm_mm_scan_init(&scan, mm, 1, 0, 0, 0);
-       for (n = 0; n < total_size; n++) {
-               e = &nodes[n];
-               list_add(&e->link, &evict_list);
-               drm_mm_scan_add_block(&scan, &e->node);
-       }
-       list_for_each_entry(e, &evict_list, link)
-               drm_mm_scan_remove_block(&scan, &e->node);
-
-       for (n = 0; n < total_size; n++) {
-               e = &nodes[n];
-
-               if (!drm_mm_node_allocated(&e->node)) {
-                       pr_err("node[%d] no longer allocated!\n", n);
-                       return false;
-               }
-
-               e->link.next = NULL;
-       }
-
-       drm_mm_for_each_node(node, mm) {
-               e = container_of(node, typeof(*e), node);
-               e->link.next = &e->link;
-       }
-
-       for (n = 0; n < total_size; n++) {
-               e = &nodes[n];
-
-               if (!e->link.next) {
-                       pr_err("node[%d] no longer connected!\n", n);
-                       return false;
-               }
-       }
-
-       return assert_continuous(mm, nodes[0].node.size);
-}
-
-static bool evict_everything(struct drm_mm *mm,
-                            unsigned int total_size,
-                            struct evict_node *nodes)
-{
-       struct drm_mm_scan scan;
-       LIST_HEAD(evict_list);
-       struct evict_node *e;
-       unsigned int n;
-       int err;
-
-       drm_mm_scan_init(&scan, mm, total_size, 0, 0, 0);
-       for (n = 0; n < total_size; n++) {
-               e = &nodes[n];
-               list_add(&e->link, &evict_list);
-               if (drm_mm_scan_add_block(&scan, &e->node))
-                       break;
-       }
-
-       err = 0;
-       list_for_each_entry(e, &evict_list, link) {
-               if (!drm_mm_scan_remove_block(&scan, &e->node)) {
-                       if (!err) {
-                               pr_err("Node %lld not marked for eviction!\n",
-                                      e->node.start);
-                               err = -EINVAL;
-                       }
-               }
-       }
-       if (err)
-               return false;
-
-       list_for_each_entry(e, &evict_list, link)
-               drm_mm_remove_node(&e->node);
-
-       if (!assert_one_hole(mm, 0, total_size))
-               return false;
-
-       list_for_each_entry(e, &evict_list, link) {
-               err = drm_mm_reserve_node(mm, &e->node);
-               if (err) {
-                       pr_err("Failed to reinsert node after eviction: start=%llx\n",
-                              e->node.start);
-                       return false;
-               }
-       }
-
-       return assert_continuous(mm, nodes[0].node.size);
-}
-
-static int evict_something(struct drm_mm *mm,
-                          u64 range_start, u64 range_end,
-                          struct evict_node *nodes,
-                          unsigned int *order,
-                          unsigned int count,
-                          unsigned int size,
-                          unsigned int alignment,
-                          const struct insert_mode *mode)
-{
-       struct drm_mm_scan scan;
-       LIST_HEAD(evict_list);
-       struct evict_node *e;
-       struct drm_mm_node tmp;
-       int err;
-
-       drm_mm_scan_init_with_range(&scan, mm,
-                                   size, alignment, 0,
-                                   range_start, range_end,
-                                   mode->mode);
-       if (!evict_nodes(&scan,
-                        nodes, order, count, false,
-                        &evict_list))
-               return -EINVAL;
-
-       memset(&tmp, 0, sizeof(tmp));
-       err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, 0,
-                                        DRM_MM_INSERT_EVICT);
-       if (err) {
-               pr_err("Failed to insert into eviction hole: size=%d, align=%d\n",
-                      size, alignment);
-               show_scan(&scan);
-               show_holes(mm, 3);
-               return err;
-       }
-
-       if (tmp.start < range_start || tmp.start + tmp.size > range_end) {
-               pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n",
-                      tmp.start, tmp.size, range_start, range_end);
-               err = -EINVAL;
-       }
-
-       if (!assert_node(&tmp, mm, size, alignment, 0) ||
-           drm_mm_hole_follows(&tmp)) {
-               pr_err("Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n",
-                      tmp.size, size,
-                      alignment, misalignment(&tmp, alignment),
-                      tmp.start, drm_mm_hole_follows(&tmp));
-               err = -EINVAL;
-       }
-
-       drm_mm_remove_node(&tmp);
-       if (err)
-               return err;
-
-       list_for_each_entry(e, &evict_list, link) {
-               err = drm_mm_reserve_node(mm, &e->node);
-               if (err) {
-                       pr_err("Failed to reinsert node after eviction: start=%llx\n",
-                              e->node.start);
-                       return err;
-               }
-       }
-
-       if (!assert_continuous(mm, nodes[0].node.size)) {
-               pr_err("range is no longer continuous\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int igt_evict(void *ignored)
-{
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int size = 8192;
-       const struct insert_mode *mode;
-       struct drm_mm mm;
-       struct evict_node *nodes;
-       struct drm_mm_node *node, *next;
-       unsigned int *order, n;
-       int ret, err;
-
-       /* Here we populate a full drm_mm and then try and insert a new node
-        * by evicting other nodes in a random order. The drm_mm_scan should
-        * pick the first matching hole it finds from the random list. We
-        * repeat that for different allocation strategies, alignments and
-        * sizes to try and stress the hole finder.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(size, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       order = drm_random_order(size, &prng);
-       if (!order)
-               goto err_nodes;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, size);
-       for (n = 0; n < size; n++) {
-               err = drm_mm_insert_node(&mm, &nodes[n].node, 1);
-               if (err) {
-                       pr_err("insert failed, step %d\n", n);
-                       ret = err;
-                       goto out;
-               }
-       }
-
-       /* First check that using the scanner doesn't break the mm */
-       if (!evict_nothing(&mm, size, nodes)) {
-               pr_err("evict_nothing() failed\n");
-               goto out;
-       }
-       if (!evict_everything(&mm, size, nodes)) {
-               pr_err("evict_everything() failed\n");
-               goto out;
-       }
-
-       for (mode = evict_modes; mode->name; mode++) {
-               for (n = 1; n <= size; n <<= 1) {
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, 0, U64_MAX,
-                                             nodes, order, size,
-                                             n, 1,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u) failed\n",
-                                      mode->name, n);
-                               ret = err;
-                               goto out;
-                       }
-               }
-
-               for (n = 1; n < size; n <<= 1) {
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, 0, U64_MAX,
-                                             nodes, order, size,
-                                             size/2, n,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u, alignment=%u) failed\n",
-                                      mode->name, size/2, n);
-                               ret = err;
-                               goto out;
-                       }
-               }
-
-               for_each_prime_number_from(n, 1, min(size, max_prime)) {
-                       unsigned int nsize = (size - n + 1) / 2;
-
-                       DRM_MM_BUG_ON(!nsize);
-
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, 0, U64_MAX,
-                                             nodes, order, size,
-                                             nsize, n,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u, alignment=%u) failed\n",
-                                      mode->name, nsize, n);
-                               ret = err;
-                               goto out;
-                       }
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int igt_evict_range(void *ignored)
-{
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int size = 8192;
-       const unsigned int range_size = size / 2;
-       const unsigned int range_start = size / 4;
-       const unsigned int range_end = range_start + range_size;
-       const struct insert_mode *mode;
-       struct drm_mm mm;
-       struct evict_node *nodes;
-       struct drm_mm_node *node, *next;
-       unsigned int *order, n;
-       int ret, err;
-
-       /* Like igt_evict() but now we are limiting the search to a
-        * small portion of the full drm_mm.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(size, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       order = drm_random_order(size, &prng);
-       if (!order)
-               goto err_nodes;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, size);
-       for (n = 0; n < size; n++) {
-               err = drm_mm_insert_node(&mm, &nodes[n].node, 1);
-               if (err) {
-                       pr_err("insert failed, step %d\n", n);
-                       ret = err;
-                       goto out;
-               }
-       }
-
-       for (mode = evict_modes; mode->name; mode++) {
-               for (n = 1; n <= range_size; n <<= 1) {
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, range_start, range_end,
-                                             nodes, order, size,
-                                             n, 1,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u) failed with range [%u, %u]\n",
-                                      mode->name, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               for (n = 1; n <= range_size; n <<= 1) {
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, range_start, range_end,
-                                             nodes, order, size,
-                                             range_size/2, n,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n",
-                                      mode->name, range_size/2, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               for_each_prime_number_from(n, 1, min(range_size, max_prime)) {
-                       unsigned int nsize = (range_size - n + 1) / 2;
-
-                       DRM_MM_BUG_ON(!nsize);
-
-                       drm_random_reorder(order, size, &prng);
-                       err = evict_something(&mm, range_start, range_end,
-                                             nodes, order, size,
-                                             nsize, n,
-                                             mode);
-                       if (err) {
-                               pr_err("%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n",
-                                      mode->name, nsize, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static unsigned int node_index(const struct drm_mm_node *node)
-{
-       return div64_u64(node->start, node->size);
-}
-
-static int igt_topdown(void *ignored)
-{
-       const struct insert_mode *topdown = &insert_modes[TOPDOWN];
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int count = 8192;
-       unsigned int size;
-       unsigned long *bitmap;
-       struct drm_mm mm;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int *order, n, m, o = 0;
-       int ret;
-
-       /* When allocating top-down, we expect to be returned a node
-        * from a suitable hole at the top of the drm_mm. We check that
-        * the returned node does match the highest available slot.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(count, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       bitmap = bitmap_zalloc(count, GFP_KERNEL);
-       if (!bitmap)
-               goto err_nodes;
-
-       order = drm_random_order(count, &prng);
-       if (!order)
-               goto err_bitmap;
-
-       ret = -EINVAL;
-       for (size = 1; size <= 64; size <<= 1) {
-               drm_mm_init(&mm, 0, size*count);
-               for (n = 0; n < count; n++) {
-                       if (!expect_insert(&mm, &nodes[n],
-                                          size, 0, n,
-                                          topdown)) {
-                               pr_err("insert failed, size %u step %d\n", size, n);
-                               goto out;
-                       }
-
-                       if (drm_mm_hole_follows(&nodes[n])) {
-                               pr_err("hole after topdown insert %d, start=%llx\n, size=%u",
-                                      n, nodes[n].start, size);
-                               goto out;
-                       }
-
-                       if (!assert_one_hole(&mm, 0, size*(count - n - 1)))
-                               goto out;
-               }
-
-               if (!assert_continuous(&mm, size))
-                       goto out;
-
-               drm_random_reorder(order, count, &prng);
-               for_each_prime_number_from(n, 1, min(count, max_prime)) {
-                       for (m = 0; m < n; m++) {
-                               node = &nodes[order[(o + m) % count]];
-                               drm_mm_remove_node(node);
-                               __set_bit(node_index(node), bitmap);
-                       }
-
-                       for (m = 0; m < n; m++) {
-                               unsigned int last;
-
-                               node = &nodes[order[(o + m) % count]];
-                               if (!expect_insert(&mm, node,
-                                                  size, 0, 0,
-                                                  topdown)) {
-                                       pr_err("insert failed, step %d/%d\n", m, n);
-                                       goto out;
-                               }
-
-                               if (drm_mm_hole_follows(node)) {
-                                       pr_err("hole after topdown insert %d/%d, start=%llx\n",
-                                              m, n, node->start);
-                                       goto out;
-                               }
-
-                               last = find_last_bit(bitmap, count);
-                               if (node_index(node) != last) {
-                                       pr_err("node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n",
-                                              m, n, size, last, node_index(node));
-                                       goto out;
-                               }
-
-                               __clear_bit(last, bitmap);
-                       }
-
-                       DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count);
-
-                       o += n;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_bitmap:
-       bitmap_free(bitmap);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int igt_bottomup(void *ignored)
-{
-       const struct insert_mode *bottomup = &insert_modes[BOTTOMUP];
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int count = 8192;
-       unsigned int size;
-       unsigned long *bitmap;
-       struct drm_mm mm;
-       struct drm_mm_node *nodes, *node, *next;
-       unsigned int *order, n, m, o = 0;
-       int ret;
-
-       /* Like igt_topdown, but instead of searching for the last hole,
-        * we search for the first.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(count, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       bitmap = bitmap_zalloc(count, GFP_KERNEL);
-       if (!bitmap)
-               goto err_nodes;
-
-       order = drm_random_order(count, &prng);
-       if (!order)
-               goto err_bitmap;
-
-       ret = -EINVAL;
-       for (size = 1; size <= 64; size <<= 1) {
-               drm_mm_init(&mm, 0, size*count);
-               for (n = 0; n < count; n++) {
-                       if (!expect_insert(&mm, &nodes[n],
-                                          size, 0, n,
-                                          bottomup)) {
-                               pr_err("bottomup insert failed, size %u step %d\n", size, n);
-                               goto out;
-                       }
-
-                       if (!assert_one_hole(&mm, size*(n + 1), size*count))
-                               goto out;
-               }
-
-               if (!assert_continuous(&mm, size))
-                       goto out;
-
-               drm_random_reorder(order, count, &prng);
-               for_each_prime_number_from(n, 1, min(count, max_prime)) {
-                       for (m = 0; m < n; m++) {
-                               node = &nodes[order[(o + m) % count]];
-                               drm_mm_remove_node(node);
-                               __set_bit(node_index(node), bitmap);
-                       }
-
-                       for (m = 0; m < n; m++) {
-                               unsigned int first;
-
-                               node = &nodes[order[(o + m) % count]];
-                               if (!expect_insert(&mm, node,
-                                                  size, 0, 0,
-                                                  bottomup)) {
-                                       pr_err("insert failed, step %d/%d\n", m, n);
-                                       goto out;
-                               }
-
-                               first = find_first_bit(bitmap, count);
-                               if (node_index(node) != first) {
-                                       pr_err("node %d/%d not inserted into bottom hole, expected %d, found %d\n",
-                                              m, n, first, node_index(node));
-                                       goto out;
-                               }
-                               __clear_bit(first, bitmap);
-                       }
-
-                       DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count);
-
-                       o += n;
-               }
-
-               drm_mm_for_each_node_safe(node, next, &mm)
-                       drm_mm_remove_node(node);
-               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_bitmap:
-       bitmap_free(bitmap);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int __igt_once(unsigned int mode)
-{
-       struct drm_mm mm;
-       struct drm_mm_node rsvd_lo, rsvd_hi, node;
-       int err;
-
-       drm_mm_init(&mm, 0, 7);
-
-       memset(&rsvd_lo, 0, sizeof(rsvd_lo));
-       rsvd_lo.start = 1;
-       rsvd_lo.size = 1;
-       err = drm_mm_reserve_node(&mm, &rsvd_lo);
-       if (err) {
-               pr_err("Could not reserve low node\n");
-               goto err;
-       }
-
-       memset(&rsvd_hi, 0, sizeof(rsvd_hi));
-       rsvd_hi.start = 5;
-       rsvd_hi.size = 1;
-       err = drm_mm_reserve_node(&mm, &rsvd_hi);
-       if (err) {
-               pr_err("Could not reserve low node\n");
-               goto err_lo;
-       }
-
-       if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) {
-               pr_err("Expected a hole after lo and high nodes!\n");
-               err = -EINVAL;
-               goto err_hi;
-       }
-
-       memset(&node, 0, sizeof(node));
-       err = drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode);
-       if (err) {
-               pr_err("Could not insert the node into the available hole!\n");
-               err = -EINVAL;
-               goto err_hi;
-       }
-
-       drm_mm_remove_node(&node);
-err_hi:
-       drm_mm_remove_node(&rsvd_hi);
-err_lo:
-       drm_mm_remove_node(&rsvd_lo);
-err:
-       drm_mm_takedown(&mm);
-       return err;
-}
-
-static int igt_lowest(void *ignored)
-{
-       return __igt_once(DRM_MM_INSERT_LOW);
-}
-
-static int igt_highest(void *ignored)
-{
-       return __igt_once(DRM_MM_INSERT_HIGH);
-}
-
-static void separate_adjacent_colors(const struct drm_mm_node *node,
-                                    unsigned long color,
-                                    u64 *start,
-                                    u64 *end)
-{
-       if (drm_mm_node_allocated(node) && node->color != color)
-               ++*start;
-
-       node = list_next_entry(node, node_list);
-       if (drm_mm_node_allocated(node) && node->color != color)
-               --*end;
-}
-
-static bool colors_abutt(const struct drm_mm_node *node)
-{
-       if (!drm_mm_hole_follows(node) &&
-           drm_mm_node_allocated(list_next_entry(node, node_list))) {
-               pr_err("colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n",
-                      node->color, node->start, node->size,
-                      list_next_entry(node, node_list)->color,
-                      list_next_entry(node, node_list)->start,
-                      list_next_entry(node, node_list)->size);
-               return true;
-       }
-
-       return false;
-}
-
-static int igt_color(void *ignored)
-{
-       const unsigned int count = min(4096u, max_iterations);
-       const struct insert_mode *mode;
-       struct drm_mm mm;
-       struct drm_mm_node *node, *nn;
-       unsigned int n;
-       int ret = -EINVAL, err;
-
-       /* Color adjustment complicates everything. First we just check
-        * that when we insert a node we apply any color_adjustment callback.
-        * The callback we use should ensure that there is a gap between
-        * any two nodes, and so after each insertion we check that those
-        * holes are inserted and that they are preserved.
-        */
-
-       drm_mm_init(&mm, 0, U64_MAX);
-
-       for (n = 1; n <= count; n++) {
-               node = kzalloc(sizeof(*node), GFP_KERNEL);
-               if (!node) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               if (!expect_insert(&mm, node,
-                                  n, 0, n,
-                                  &insert_modes[0])) {
-                       pr_err("insert failed, step %d\n", n);
-                       kfree(node);
-                       goto out;
-               }
-       }
-
-       drm_mm_for_each_node_safe(node, nn, &mm) {
-               if (node->color != node->size) {
-                       pr_err("invalid color stored: expected %lld, found %ld\n",
-                              node->size, node->color);
-
-                       goto out;
-               }
-
-               drm_mm_remove_node(node);
-               kfree(node);
-       }
-
-       /* Now, let's start experimenting with applying a color callback */
-       mm.color_adjust = separate_adjacent_colors;
-       for (mode = insert_modes; mode->name; mode++) {
-               u64 last;
-
-               node = kzalloc(sizeof(*node), GFP_KERNEL);
-               if (!node) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               node->size = 1 + 2*count;
-               node->color = node->size;
-
-               err = drm_mm_reserve_node(&mm, node);
-               if (err) {
-                       pr_err("initial reserve failed!\n");
-                       ret = err;
-                       goto out;
-               }
-
-               last = node->start + node->size;
-
-               for (n = 1; n <= count; n++) {
-                       int rem;
-
-                       node = kzalloc(sizeof(*node), GFP_KERNEL);
-                       if (!node) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-
-                       node->start = last;
-                       node->size = n + count;
-                       node->color = node->size;
-
-                       err = drm_mm_reserve_node(&mm, node);
-                       if (err != -ENOSPC) {
-                               pr_err("reserve %d did not report color overlap! err=%d\n",
-                                      n, err);
-                               goto out;
-                       }
-
-                       node->start += n + 1;
-                       rem = misalignment(node, n + count);
-                       node->start += n + count - rem;
-
-                       err = drm_mm_reserve_node(&mm, node);
-                       if (err) {
-                               pr_err("reserve %d failed, err=%d\n", n, err);
-                               ret = err;
-                               goto out;
-                       }
-
-                       last = node->start + node->size;
-               }
-
-               for (n = 1; n <= count; n++) {
-                       node = kzalloc(sizeof(*node), GFP_KERNEL);
-                       if (!node) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-
-                       if (!expect_insert(&mm, node,
-                                          n, n, n,
-                                          mode)) {
-                               pr_err("%s insert failed, step %d\n",
-                                      mode->name, n);
-                               kfree(node);
-                               goto out;
-                       }
-               }
-
-               drm_mm_for_each_node_safe(node, nn, &mm) {
-                       u64 rem;
-
-                       if (node->color != node->size) {
-                               pr_err("%s invalid color stored: expected %lld, found %ld\n",
-                                      mode->name, node->size, node->color);
-
-                               goto out;
-                       }
-
-                       if (colors_abutt(node))
-                               goto out;
-
-                       div64_u64_rem(node->start, node->size, &rem);
-                       if (rem) {
-                               pr_err("%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n",
-                                      mode->name, node->start, node->size, rem);
-                               goto out;
-                       }
-
-                       drm_mm_remove_node(node);
-                       kfree(node);
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       drm_mm_for_each_node_safe(node, nn, &mm) {
-               drm_mm_remove_node(node);
-               kfree(node);
-       }
-       drm_mm_takedown(&mm);
-       return ret;
-}
-
-static int evict_color(struct drm_mm *mm,
-                      u64 range_start, u64 range_end,
-                      struct evict_node *nodes,
-                      unsigned int *order,
-                      unsigned int count,
-                      unsigned int size,
-                      unsigned int alignment,
-                      unsigned long color,
-                      const struct insert_mode *mode)
-{
-       struct drm_mm_scan scan;
-       LIST_HEAD(evict_list);
-       struct evict_node *e;
-       struct drm_mm_node tmp;
-       int err;
-
-       drm_mm_scan_init_with_range(&scan, mm,
-                                   size, alignment, color,
-                                   range_start, range_end,
-                                   mode->mode);
-       if (!evict_nodes(&scan,
-                        nodes, order, count, true,
-                        &evict_list))
-               return -EINVAL;
-
-       memset(&tmp, 0, sizeof(tmp));
-       err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, color,
-                                        DRM_MM_INSERT_EVICT);
-       if (err) {
-               pr_err("Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n",
-                      size, alignment, color, err);
-               show_scan(&scan);
-               show_holes(mm, 3);
-               return err;
-       }
-
-       if (tmp.start < range_start || tmp.start + tmp.size > range_end) {
-               pr_err("Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n",
-                      tmp.start, tmp.size, range_start, range_end);
-               err = -EINVAL;
-       }
-
-       if (colors_abutt(&tmp))
-               err = -EINVAL;
-
-       if (!assert_node(&tmp, mm, size, alignment, color)) {
-               pr_err("Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n",
-                      tmp.size, size,
-                      alignment, misalignment(&tmp, alignment), tmp.start);
-               err = -EINVAL;
-       }
-
-       drm_mm_remove_node(&tmp);
-       if (err)
-               return err;
-
-       list_for_each_entry(e, &evict_list, link) {
-               err = drm_mm_reserve_node(mm, &e->node);
-               if (err) {
-                       pr_err("Failed to reinsert node after eviction: start=%llx\n",
-                              e->node.start);
-                       return err;
-               }
-       }
-
-       cond_resched();
-       return 0;
-}
-
-static int igt_color_evict(void *ignored)
-{
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int total_size = min(8192u, max_iterations);
-       const struct insert_mode *mode;
-       unsigned long color = 0;
-       struct drm_mm mm;
-       struct evict_node *nodes;
-       struct drm_mm_node *node, *next;
-       unsigned int *order, n;
-       int ret, err;
-
-       /* Check that the drm_mm_scan also honours color adjustment when
-        * choosing its victims to create a hole. Our color_adjust does not
-        * allow two nodes to be placed together without an intervening hole
-        * enlarging the set of victims that must be evicted.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       order = drm_random_order(total_size, &prng);
-       if (!order)
-               goto err_nodes;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, 2*total_size - 1);
-       mm.color_adjust = separate_adjacent_colors;
-       for (n = 0; n < total_size; n++) {
-               if (!expect_insert(&mm, &nodes[n].node,
-                                  1, 0, color++,
-                                  &insert_modes[0])) {
-                       pr_err("insert failed, step %d\n", n);
-                       goto out;
-               }
-       }
-
-       for (mode = evict_modes; mode->name; mode++) {
-               for (n = 1; n <= total_size; n <<= 1) {
-                       drm_random_reorder(order, total_size, &prng);
-                       err = evict_color(&mm, 0, U64_MAX,
-                                         nodes, order, total_size,
-                                         n, 1, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u) failed\n",
-                                      mode->name, n);
-                               goto out;
-                       }
-               }
-
-               for (n = 1; n < total_size; n <<= 1) {
-                       drm_random_reorder(order, total_size, &prng);
-                       err = evict_color(&mm, 0, U64_MAX,
-                                         nodes, order, total_size,
-                                         total_size/2, n, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u, alignment=%u) failed\n",
-                                      mode->name, total_size/2, n);
-                               goto out;
-                       }
-               }
-
-               for_each_prime_number_from(n, 1, min(total_size, max_prime)) {
-                       unsigned int nsize = (total_size - n + 1) / 2;
-
-                       DRM_MM_BUG_ON(!nsize);
-
-                       drm_random_reorder(order, total_size, &prng);
-                       err = evict_color(&mm, 0, U64_MAX,
-                                         nodes, order, total_size,
-                                         nsize, n, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u, alignment=%u) failed\n",
-                                      mode->name, nsize, n);
-                               goto out;
-                       }
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       if (ret)
-               show_mm(&mm);
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-static int igt_color_evict_range(void *ignored)
-{
-       DRM_RND_STATE(prng, random_seed);
-       const unsigned int total_size = 8192;
-       const unsigned int range_size = total_size / 2;
-       const unsigned int range_start = total_size / 4;
-       const unsigned int range_end = range_start + range_size;
-       const struct insert_mode *mode;
-       unsigned long color = 0;
-       struct drm_mm mm;
-       struct evict_node *nodes;
-       struct drm_mm_node *node, *next;
-       unsigned int *order, n;
-       int ret, err;
-
-       /* Like igt_color_evict(), but limited to small portion of the full
-        * drm_mm range.
-        */
-
-       ret = -ENOMEM;
-       nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
-       if (!nodes)
-               goto err;
-
-       order = drm_random_order(total_size, &prng);
-       if (!order)
-               goto err_nodes;
-
-       ret = -EINVAL;
-       drm_mm_init(&mm, 0, 2*total_size - 1);
-       mm.color_adjust = separate_adjacent_colors;
-       for (n = 0; n < total_size; n++) {
-               if (!expect_insert(&mm, &nodes[n].node,
-                                  1, 0, color++,
-                                  &insert_modes[0])) {
-                       pr_err("insert failed, step %d\n", n);
-                       goto out;
-               }
-       }
-
-       for (mode = evict_modes; mode->name; mode++) {
-               for (n = 1; n <= range_size; n <<= 1) {
-                       drm_random_reorder(order, range_size, &prng);
-                       err = evict_color(&mm, range_start, range_end,
-                                         nodes, order, total_size,
-                                         n, 1, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u) failed for range [%x, %x]\n",
-                                      mode->name, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               for (n = 1; n < range_size; n <<= 1) {
-                       drm_random_reorder(order, total_size, &prng);
-                       err = evict_color(&mm, range_start, range_end,
-                                         nodes, order, total_size,
-                                         range_size/2, n, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n",
-                                      mode->name, total_size/2, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               for_each_prime_number_from(n, 1, min(range_size, max_prime)) {
-                       unsigned int nsize = (range_size - n + 1) / 2;
-
-                       DRM_MM_BUG_ON(!nsize);
-
-                       drm_random_reorder(order, total_size, &prng);
-                       err = evict_color(&mm, range_start, range_end,
-                                         nodes, order, total_size,
-                                         nsize, n, color++,
-                                         mode);
-                       if (err) {
-                               pr_err("%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n",
-                                      mode->name, nsize, n, range_start, range_end);
-                               goto out;
-                       }
-               }
-
-               cond_resched();
-       }
-
-       ret = 0;
-out:
-       if (ret)
-               show_mm(&mm);
-       drm_mm_for_each_node_safe(node, next, &mm)
-               drm_mm_remove_node(node);
-       drm_mm_takedown(&mm);
-       kfree(order);
-err_nodes:
-       vfree(nodes);
-err:
-       return ret;
-}
-
-#include "drm_selftest.c"
-
-static int __init test_drm_mm_init(void)
-{
-       int err;
-
-       while (!random_seed)
-               random_seed = get_random_int();
-
-       pr_info("Testing DRM range manager (struct drm_mm), with random_seed=0x%x max_iterations=%u max_prime=%u\n",
-               random_seed, max_iterations, max_prime);
-       err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
-
-       return err > 0 ? 0 : err;
-}
-
-static void __exit test_drm_mm_exit(void)
-{
-}
-
-module_init(test_drm_mm_init);
-module_exit(test_drm_mm_exit);
-
-module_param(random_seed, uint, 0400);
-module_param(max_iterations, uint, 0400);
-module_param(max_prime, uint, 0400);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.c b/drivers/gpu/drm/selftests/test-drm_modeset_common.c
deleted file mode 100644 (file)
index 2a7f937..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Common file for modeset selftests.
- */
-
-#include <linux/module.h>
-
-#include "test-drm_modeset_common.h"
-
-#define TESTS "drm_modeset_selftests.h"
-#include "drm_selftest.h"
-
-#include "drm_selftest.c"
-
-static int __init test_drm_modeset_init(void)
-{
-       int err;
-
-       err = run_selftests(selftests, ARRAY_SIZE(selftests), NULL);
-
-       return err > 0 ? 0 : err;
-}
-
-static void __exit test_drm_modeset_exit(void)
-{
-}
-
-module_init(test_drm_modeset_init);
-module_exit(test_drm_modeset_exit);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
deleted file mode 100644 (file)
index cfb51d8..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#ifndef __TEST_DRM_MODESET_COMMON_H__
-#define __TEST_DRM_MODESET_COMMON_H__
-
-#include <linux/errno.h>
-#include <linux/printk.h>
-
-#define FAIL(test, msg, ...) \
-       do { \
-               if (test) { \
-                       pr_err("%s/%u: " msg, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
-                       return -EINVAL; \
-               } \
-       } while (0)
-
-#define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
-
-int igt_drm_rect_clip_scaled_div_by_zero(void *ignored);
-int igt_drm_rect_clip_scaled_not_clipped(void *ignored);
-int igt_drm_rect_clip_scaled_clipped(void *ignored);
-int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored);
-int igt_check_plane_state(void *ignored);
-int igt_check_drm_format_block_width(void *ignored);
-int igt_check_drm_format_block_height(void *ignored);
-int igt_check_drm_format_min_pitch(void *ignored);
-int igt_check_drm_framebuffer_create(void *ignored);
-int igt_damage_iter_no_damage(void *ignored);
-int igt_damage_iter_no_damage_fractional_src(void *ignored);
-int igt_damage_iter_no_damage_src_moved(void *ignored);
-int igt_damage_iter_no_damage_fractional_src_moved(void *ignored);
-int igt_damage_iter_no_damage_not_visible(void *ignored);
-int igt_damage_iter_no_damage_no_crtc(void *ignored);
-int igt_damage_iter_no_damage_no_fb(void *ignored);
-int igt_damage_iter_simple_damage(void *ignored);
-int igt_damage_iter_single_damage(void *ignored);
-int igt_damage_iter_single_damage_intersect_src(void *ignored);
-int igt_damage_iter_single_damage_outside_src(void *ignored);
-int igt_damage_iter_single_damage_fractional_src(void *ignored);
-int igt_damage_iter_single_damage_intersect_fractional_src(void *ignored);
-int igt_damage_iter_single_damage_outside_fractional_src(void *ignored);
-int igt_damage_iter_single_damage_src_moved(void *ignored);
-int igt_damage_iter_single_damage_fractional_src_moved(void *ignored);
-int igt_damage_iter_damage(void *ignored);
-int igt_damage_iter_damage_one_intersect(void *ignored);
-int igt_damage_iter_damage_one_outside(void *ignored);
-int igt_damage_iter_damage_src_moved(void *ignored);
-int igt_damage_iter_damage_not_visible(void *ignored);
-int igt_dp_mst_calc_pbn_mode(void *ignored);
-int igt_dp_mst_sideband_msg_req_decode(void *ignored);
-
-#endif
diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c b/drivers/gpu/drm/selftests/test-drm_plane_helper.c
deleted file mode 100644 (file)
index 64e8938..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_plane_helper functions
- */
-
-#define pr_fmt(fmt) "drm_plane_helper: " fmt
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_modes.h>
-
-#include "test-drm_modeset_common.h"
-
-static void set_src(struct drm_plane_state *plane_state,
-                   unsigned src_x, unsigned src_y,
-                   unsigned src_w, unsigned src_h)
-{
-       plane_state->src_x = src_x;
-       plane_state->src_y = src_y;
-       plane_state->src_w = src_w;
-       plane_state->src_h = src_h;
-}
-
-static bool check_src_eq(struct drm_plane_state *plane_state,
-                        unsigned src_x, unsigned src_y,
-                        unsigned src_w, unsigned src_h)
-{
-       if (plane_state->src.x1 < 0) {
-               pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
-               drm_rect_debug_print("src: ", &plane_state->src, true);
-               return false;
-       }
-       if (plane_state->src.y1 < 0) {
-               pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
-               drm_rect_debug_print("src: ", &plane_state->src, true);
-               return false;
-       }
-
-       if (plane_state->src.x1 != src_x ||
-           plane_state->src.y1 != src_y ||
-           drm_rect_width(&plane_state->src) != src_w ||
-           drm_rect_height(&plane_state->src) != src_h) {
-               drm_rect_debug_print("src: ", &plane_state->src, true);
-               return false;
-       }
-
-       return true;
-}
-
-static void set_crtc(struct drm_plane_state *plane_state,
-                    int crtc_x, int crtc_y,
-                    unsigned crtc_w, unsigned crtc_h)
-{
-       plane_state->crtc_x = crtc_x;
-       plane_state->crtc_y = crtc_y;
-       plane_state->crtc_w = crtc_w;
-       plane_state->crtc_h = crtc_h;
-}
-
-static bool check_crtc_eq(struct drm_plane_state *plane_state,
-                         int crtc_x, int crtc_y,
-                         unsigned crtc_w, unsigned crtc_h)
-{
-       if (plane_state->dst.x1 != crtc_x ||
-           plane_state->dst.y1 != crtc_y ||
-           drm_rect_width(&plane_state->dst) != crtc_w ||
-           drm_rect_height(&plane_state->dst) != crtc_h) {
-               drm_rect_debug_print("dst: ", &plane_state->dst, false);
-
-               return false;
-       }
-
-       return true;
-}
-
-int igt_check_plane_state(void *ignored)
-{
-       int ret;
-
-       static const struct drm_crtc_state crtc_state = {
-               .crtc = ZERO_SIZE_PTR,
-               .enable = true,
-               .active = true,
-               .mode = {
-                       DRM_MODE("1024x768", 0, 65000, 1024, 1048,
-                               1184, 1344, 0, 768, 771, 777, 806, 0,
-                               DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
-               },
-       };
-       static struct drm_plane plane = {
-               .dev = NULL
-       };
-       static struct drm_framebuffer fb = {
-               .width = 2048,
-               .height = 2048
-       };
-       static struct drm_plane_state plane_state = {
-               .plane = &plane,
-               .crtc = ZERO_SIZE_PTR,
-               .fb = &fb,
-               .rotation = DRM_MODE_ROTATE_0
-       };
-
-       /* Simple clipping, no scaling. */
-       set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
-       set_crtc(&plane_state, 0, 0, fb.width, fb.height);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(ret < 0, "Simple clipping check should pass\n");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
-       /* Rotated clipping + reflection, no scaling. */
-       plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(ret < 0, "Rotated clipping check should pass\n");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-       plane_state.rotation = DRM_MODE_ROTATE_0;
-
-       /* Check whether positioning works correctly. */
-       set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
-       set_crtc(&plane_state, 0, 0, 1023, 767);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(!ret, "Should not be able to position on the crtc with can_position=false\n");
-
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 true, false);
-       FAIL(ret < 0, "Simple positioning should work\n");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1023, 767));
-
-       /* Simple scaling tests. */
-       set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
-       set_crtc(&plane_state, 0, 0, 1024, 768);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 0x8001,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(!ret, "Upscaling out of range should fail.\n");
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 0x8000,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(ret < 0, "Upscaling exactly 2x should work\n");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
-       set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 0x1ffff, false, false);
-       FAIL(!ret, "Downscaling out of range should fail.\n");
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 0x20000, false, false);
-       FAIL(ret < 0, "Should succeed with exact scaling limit\n");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
-       /* Testing rounding errors. */
-       set_src(&plane_state, 0, 0, 0x40001, 0x40001);
-       set_crtc(&plane_state, 1022, 766, 4, 4);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 0x10001,
-                                                 true, false);
-       FAIL(ret < 0, "Should succeed by clipping to exact multiple");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
-
-       set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
-       set_crtc(&plane_state, -2, -2, 1028, 772);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 0x10001,
-                                                 false, false);
-       FAIL(ret < 0, "Should succeed by clipping to exact multiple");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0x40002, 0x40002, 1024 << 16, 768 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
-       set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
-       set_crtc(&plane_state, 1022, 766, 4, 4);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 0xffff,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 true, false);
-       FAIL(ret < 0, "Should succeed by clipping to exact multiple");
-       FAIL_ON(!plane_state.visible);
-       /* Should not be rounded to 0x20001, which would be upscaling. */
-       FAIL_ON(!check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 1022, 766, 2, 2));
-
-       set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
-       set_crtc(&plane_state, -2, -2, 1028, 772);
-       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
-                                                 0xffff,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 false, false);
-       FAIL(ret < 0, "Should succeed by clipping to exact multiple");
-       FAIL_ON(!plane_state.visible);
-       FAIL_ON(!check_src_eq(&plane_state, 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16));
-       FAIL_ON(!check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
-       return 0;
-}
diff --git a/drivers/gpu/drm/selftests/test-drm_rect.c b/drivers/gpu/drm/selftests/test-drm_rect.c
deleted file mode 100644 (file)
index 3a5ff38..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_rect functions
- */
-
-#define pr_fmt(fmt) "drm_rect: " fmt
-
-#include <linux/limits.h>
-
-#include <drm/drm_rect.h>
-
-#include "test-drm_modeset_common.h"
-
-int igt_drm_rect_clip_scaled_div_by_zero(void *ignored)
-{
-       struct drm_rect src, dst, clip;
-       bool visible;
-
-       /*
-        * Make sure we don't divide by zero when dst
-        * width/height is zero and dst and clip do not intersect.
-        */
-       drm_rect_init(&src, 0, 0, 0, 0);
-       drm_rect_init(&dst, 0, 0, 0, 0);
-       drm_rect_init(&clip, 1, 1, 1, 1);
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-       FAIL(visible, "Destination not be visible\n");
-       FAIL(drm_rect_visible(&src), "Source should not be visible\n");
-
-       drm_rect_init(&src, 0, 0, 0, 0);
-       drm_rect_init(&dst, 3, 3, 0, 0);
-       drm_rect_init(&clip, 1, 1, 1, 1);
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-       FAIL(visible, "Destination not be visible\n");
-       FAIL(drm_rect_visible(&src), "Source should not be visible\n");
-
-       return 0;
-}
-
-int igt_drm_rect_clip_scaled_not_clipped(void *ignored)
-{
-       struct drm_rect src, dst, clip;
-       bool visible;
-
-       /* 1:1 scaling */
-       drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
-       drm_rect_init(&dst, 0, 0, 1, 1);
-       drm_rect_init(&clip, 0, 0, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
-            src.y1 != 0 || src.y2 != 1 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 1 ||
-            dst.y1 != 0 || dst.y2 != 1,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 2:1 scaling */
-       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
-       drm_rect_init(&dst, 0, 0, 1, 1);
-       drm_rect_init(&clip, 0, 0, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
-            src.y1 != 0 || src.y2 != 2 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 1 ||
-            dst.y1 != 0 || dst.y2 != 1,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 1:2 scaling */
-       drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 0, 0, 2, 2);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
-            src.y1 != 0 || src.y2 != 1 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 2 ||
-            dst.y1 != 0 || dst.y2 != 2,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       return 0;
-}
-
-int igt_drm_rect_clip_scaled_clipped(void *ignored)
-{
-       struct drm_rect src, dst, clip;
-       bool visible;
-
-       /* 1:1 scaling top/left clip */
-       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 0, 0, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
-            src.y1 != 0 || src.y2 != 1 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 1 ||
-            dst.y1 != 0 || dst.y2 != 1,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 1:1 scaling bottom/right clip */
-       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 1, 1, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
-            src.y1 != 1 << 16 || src.y2 != 2 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 1 || dst.x2 != 2 ||
-            dst.y1 != 1 || dst.y2 != 2,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 2:1 scaling top/left clip */
-       drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 0, 0, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 2 << 16 ||
-            src.y1 != 0 || src.y2 != 2 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 1 ||
-            dst.y1 != 0 || dst.y2 != 1,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 2:1 scaling bottom/right clip */
-       drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 1, 1, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
-            src.y1 != 2 << 16 || src.y2 != 4 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 1 || dst.x2 != 2 ||
-            dst.y1 != 1 || dst.y2 != 2,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 1:2 scaling top/left clip */
-       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
-       drm_rect_init(&dst, 0, 0, 4, 4);
-       drm_rect_init(&clip, 0, 0, 2, 2);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
-            src.y1 != 0 || src.y2 != 1 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 0 || dst.x2 != 2 ||
-            dst.y1 != 0 || dst.y2 != 2,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       /* 1:2 scaling bottom/right clip */
-       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
-       drm_rect_init(&dst, 0, 0, 4, 4);
-       drm_rect_init(&clip, 2, 2, 2, 2);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
-            src.y1 != 1 << 16 || src.y2 != 2 << 16,
-            "Source badly clipped\n");
-       FAIL(dst.x1 != 2 || dst.x2 != 4 ||
-            dst.y1 != 2 || dst.y2 != 4,
-            "Destination badly clipped\n");
-       FAIL(!visible, "Destination should be visible\n");
-       FAIL(!drm_rect_visible(&src), "Source should be visible\n");
-
-       return 0;
-}
-
-int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored)
-{
-       struct drm_rect src, dst, clip;
-       bool visible;
-
-       /*
-        * 'clip.x2 - dst.x1 >= dst width' could result a negative
-        * src rectangle width which is no longer expected by the
-        * code as it's using unsigned types. This could lead to
-        * the clipped source rectangle appering visible when it
-        * should have been fully clipped. Make sure both rectangles
-        * end up invisible.
-        */
-       drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
-       drm_rect_init(&dst, 0, 0, 2, 2);
-       drm_rect_init(&clip, 3, 3, 1, 1);
-
-       visible = drm_rect_clip_scaled(&src, &dst, &clip);
-
-       FAIL(visible, "Destination should not be visible\n");
-       FAIL(drm_rect_visible(&src), "Source should not be visible\n");
-
-       return 0;
-}
index 288b838a904a211ef16c206ca582dac0444d6507..4ec5dc74a6b0b880c61772191eba2561f75ba98e 100644 (file)
@@ -5,7 +5,7 @@ config DRM_SHMOBILE
        depends on ARCH_SHMOBILE || COMPILE_TEST
        select BACKLIGHT_CLASS_DEVICE
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        help
          Choose this option if you have an SH Mobile chipset.
          If M is selected the module will be called shmob-drm.
index 071a929e9fe341c883610d0233c4a4e5601d3497..4624c0aff51ffa583d438d1b44b149fbc6ed4a30 100644 (file)
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
@@ -289,18 +288,18 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
 {
        struct drm_crtc *crtc = &scrtc->crtc;
        struct drm_framebuffer *fb = crtc->primary->fb;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        unsigned int bpp;
 
        bpp = scrtc->format->yuv ? 8 : scrtc->format->bpp;
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
-       scrtc->dma[0] = gem->paddr + fb->offsets[0]
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
+       scrtc->dma[0] = gem->dma_addr + fb->offsets[0]
                      + y * fb->pitches[0] + x * bpp / 8;
 
        if (scrtc->format->yuv) {
                bpp = scrtc->format->bpp - 8;
-               gem = drm_fb_cma_get_gem_obj(fb, 1);
-               scrtc->dma[1] = gem->paddr + fb->offsets[1]
+               gem = drm_fb_dma_get_gem_obj(fb, 1);
+               scrtc->dma[1] = gem->dma_addr + fb->offsets[1]
                              + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
                              + x * (bpp == 16 ? 2 : 1);
        }
index 731cbad7520f24e3a0b8d98a3c8bdb9632395d47..3d511fa389136411da470ad12096f124df328f9f 100644 (file)
@@ -17,7 +17,7 @@
 
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
@@ -126,11 +126,11 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(shmob_drm_fops);
 
 static const struct drm_driver shmob_drm_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
        .fops                   = &shmob_drm_fops,
        .name                   = "shmob-drm",
        .desc                   = "Renesas SH Mobile DRM",
index 68d21be784aa8f24dfb5fdbe8c24c732da2a5bb4..60a2c8d8a0d947d2f6626196f9581fc3fff0a72b 100644 (file)
@@ -9,9 +9,8 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_probe_helper.h>
 
index 6ec2b732bb9498829ec2f83b74ee8cd5850625d7..0347b1fd2338a84dfc4d35df4f066ab035cea472 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 
-struct drm_gem_cma_object;
+struct drm_gem_dma_object;
 struct shmob_drm_device;
 
 struct shmob_drm_format_info {
index 4763ea8e1af02a3d14b6fa84fce14bf20f1b18a9..54228424793a7edc5fc019420d82ff9175505907 100644 (file)
@@ -9,10 +9,10 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "shmob_drm_drv.h"
 #include "shmob_drm_kms.h"
@@ -41,18 +41,18 @@ static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane,
                                         struct drm_framebuffer *fb,
                                         int x, int y)
 {
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        unsigned int bpp;
 
        bpp = splane->format->yuv ? 8 : splane->format->bpp;
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
-       splane->dma[0] = gem->paddr + fb->offsets[0]
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
+       splane->dma[0] = gem->dma_addr + fb->offsets[0]
                       + y * fb->pitches[0] + x * bpp / 8;
 
        if (splane->format->yuv) {
                bpp = splane->format->bpp - 8;
-               gem = drm_fb_cma_get_gem_obj(fb, 1);
-               splane->dma[1] = gem->paddr + fb->offsets[1]
+               gem = drm_fb_dma_get_gem_obj(fb, 1);
+               splane->dma[1] = gem->dma_addr + fb->offsets[1]
                               + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
                               + x * (bpp == 16 ? 2 : 1);
        }
index e35e719cf315b30ce5646fa929bc69bceec51e92..6173020a9bf56a44b37451c7b78031669ad9e31e 100644 (file)
@@ -50,7 +50,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
        if (dev_priv == NULL)
                return -ENOMEM;
 
-       idr_init(&dev_priv->object_idr);
+       idr_init_base(&dev_priv->object_idr, 1);
        dev->dev_private = (void *)dev_priv;
        dev_priv->chipset = chipset;
 
index 07802907e39add8c8113536b4c1d766cf3fd2968..19ab4942cb33cff89139286f007fd3217d736c16 100644 (file)
@@ -18,11 +18,6 @@ struct ssd130x_spi_transport {
        struct gpio_desc *dc;
 };
 
-static const struct regmap_config ssd130x_spi_regmap_config = {
-       .reg_bits = 8,
-       .val_bits = 8,
-};
-
 /*
  * The regmap bus .write handler, it is just a wrapper around spi_write()
  * but toggling the Data/Command control pin (D/C#). Since for 4-wire SPI
@@ -56,17 +51,12 @@ static int ssd130x_spi_read(void *context, const void *reg, size_t reg_size,
        return -EOPNOTSUPP;
 }
 
-/*
- * A custom bus is needed due the special write that toggles a D/C# pin,
- * another option could be to just have a .reg_write() callback but that
- * will prevent to do data writes in bulk.
- *
- * Once the regmap API is extended to support defining a bulk write handler
- * in the struct regmap_config, this can be simplified and the bus dropped.
- */
-static struct regmap_bus regmap_ssd130x_spi_bus = {
+static const struct regmap_config ssd130x_spi_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
        .write = ssd130x_spi_write,
        .read = ssd130x_spi_read,
+       .can_multi_write = true,
 };
 
 static int ssd130x_spi_probe(struct spi_device *spi)
@@ -90,8 +80,7 @@ static int ssd130x_spi_probe(struct spi_device *spi)
        t->spi = spi;
        t->dc = dc;
 
-       regmap = devm_regmap_init(dev, &regmap_ssd130x_spi_bus, t,
-                                 &ssd130x_spi_regmap_config);
+       regmap = devm_regmap_init(dev, NULL, t, &ssd130x_spi_regmap_config);
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
index 5a3e3b78cd9ed41b9a89dada20633c235d23cd09..94d92b726c3485450825757a96d692082957b613 100644 (file)
@@ -21,7 +21,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_framebuffer.h>
@@ -537,11 +536,11 @@ static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
        kfree(buf);
 }
 
-static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *map,
+static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap,
                                struct drm_rect *rect)
 {
        struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
-       void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
+       struct iosys_map dst;
        unsigned int dst_pitch;
        int ret = 0;
        u8 *buf = NULL;
@@ -555,7 +554,8 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m
        if (!buf)
                return -ENOMEM;
 
-       drm_fb_xrgb8888_to_mono(buf, dst_pitch, vmap, fb, rect);
+       iosys_map_set_vaddr(&dst, buf);
+       drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
 
        ssd130x_update_rect(ssd130x, buf, rect);
 
index 9a9c7ebfc71662634afa3056dc473548e2840670..e22b780fe82248296a7153d02269faf8cd63294f 100644 (file)
@@ -2,7 +2,7 @@ config DRM_SPRD
        tristate "DRM Support for Unisoc SoCs Platform"
        depends on ARCH_SPRD || COMPILE_TEST
        depends on DRM && OF
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_MIPI_DSI
        select VIDEOMODE_HELPERS
index 3664089b6983afaa8efad5d8062e3ba147502f3d..88f4259680f14252b94497d3f3ae29011d86cbdd 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "sprd_drm.h"
 #include "sprd_dpu.h"
@@ -324,7 +323,7 @@ static u32 drm_blend_to_dpu(struct drm_plane_state *state)
 static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state)
 {
        struct dpu_context *ctx = &dpu->ctx;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct drm_framebuffer *fb = state->fb;
        u32 addr, size, offset, pitch, blend, format, rotation;
        u32 src_x = state->src_x >> 16;
@@ -341,8 +340,8 @@ static void sprd_dpu_layer(struct sprd_dpu *dpu, struct drm_plane_state *state)
        size = (src_w & 0xffff) | (src_h << 16);
 
        for (i = 0; i < fb->format->num_planes; i++) {
-               cma_obj = drm_fb_cma_get_gem_obj(fb, i);
-               addr = cma_obj->paddr + fb->offsets[i];
+               dma_obj = drm_fb_dma_get_gem_obj(fb, i);
+               addr = dma_obj->dma_addr + fb->offsets[i];
 
                if (i == 0)
                        layer_reg_wr(ctx, REG_LAY_BASE_ADDR0, addr, index);
@@ -524,8 +523,8 @@ static int sprd_plane_atomic_check(struct drm_plane *plane,
                return PTR_ERR(crtc_state);
 
        return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
 }
 
index b8fc1c6a0cb84c3616afdd68d456ed208e26182f..9d42f17a5734352ac93a7666c17bbbe5ead22aa1 100644 (file)
@@ -13,7 +13,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
@@ -48,14 +48,14 @@ static void sprd_drm_mode_config_init(struct drm_device *drm)
        drm->mode_config.helper_private = &sprd_drm_mode_config_helper;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(sprd_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(sprd_drm_fops);
 
 static struct drm_driver sprd_drm_drv = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &sprd_drm_fops,
 
        /* GEM Operations */
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 
        .name                   = DRIVER_NAME,
        .desc                   = DRIVER_DESC,
index 246a94afbe745417e0cdbfc861cd588d7cfa4504..f2a880c48485e9bad5f1fc91036bd8604ba626e6 100644 (file)
@@ -4,7 +4,7 @@ config DRM_STI
        depends on OF && DRM && (ARCH_STI || ARCH_MULTIPLATFORM)
        select RESET_CONTROLLER
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_PANEL
        select FW_LOADER
        select SND_SOC_HDMI_CODEC if SND_SOC
index 409795786f0390c71fd444e04a8e2f108d9a5cac..3c7154f2d5f3729e7ca3c1b7d29ac3ea9d42ec27 100644 (file)
@@ -11,7 +11,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_device.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
index 1e9bd4241f10252c9b6e88934fa0c0e2ad812dfa..db0a1eb535328f931a0a4ed6f388b5532dcf054d 100644 (file)
@@ -11,9 +11,9 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "sti_compositor.h"
 #include "sti_cursor.h"
@@ -243,8 +243,8 @@ static int sti_cursor_atomic_check(struct drm_plane *drm_plane,
                }
        }
 
-       if (!drm_fb_cma_get_gem_obj(fb, 0)) {
-               DRM_ERROR("Can't get CMA GEM object for fb\n");
+       if (!drm_fb_dma_get_gem_obj(fb, 0)) {
+               DRM_ERROR("Can't get DMA GEM object for fb\n");
                return -EINVAL;
        }
 
@@ -267,7 +267,7 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
        struct drm_framebuffer *fb = newstate->fb;
        struct drm_display_mode *mode;
        int dst_x, dst_y;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        u32 y, x;
        u32 val;
 
@@ -278,10 +278,10 @@ static void sti_cursor_atomic_update(struct drm_plane *drm_plane,
        dst_x = newstate->crtc_x;
        dst_y = newstate->crtc_y;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
 
        /* Convert ARGB8888 to CLUT8 */
-       sti_cursor_argb8888_to_clut8(cursor, (u32 *)cma_obj->vaddr);
+       sti_cursor_argb8888_to_clut8(cursor, (u32 *)dma_obj->vaddr);
 
        /* AWS and AWE depend on the mode */
        y = sti_vtg_get_line_number(*mode, 0);
index d858209cf8de243caa28a5d002e9ae169cb65fe2..7abf010a329351fc89d21e4afc6e05a47fb84e25 100644 (file)
@@ -14,9 +14,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_debugfs.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
@@ -128,12 +127,12 @@ static void sti_mode_config_init(struct drm_device *dev)
        dev->mode_config.normalize_zpos = true;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops);
+DEFINE_DRM_GEM_DMA_FOPS(sti_driver_fops);
 
 static const struct drm_driver sti_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
        .fops = &sti_driver_fops,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 
        .debugfs_init = sti_drm_dbg_init,
 
index af783f599306c3d7ff92eef48cab152a529b7d21..43c72c2604a0cdb8abd0d8e79cb41d8b45a08290 100644 (file)
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "sti_compositor.h"
 #include "sti_gdp.h"
@@ -658,8 +658,8 @@ static int sti_gdp_atomic_check(struct drm_plane *drm_plane,
                return -EINVAL;
        }
 
-       if (!drm_fb_cma_get_gem_obj(fb, 0)) {
-               DRM_ERROR("Can't get CMA GEM object for fb\n");
+       if (!drm_fb_dma_get_gem_obj(fb, 0)) {
+               DRM_ERROR("Can't get DMA GEM object for fb\n");
                return -EINVAL;
        }
 
@@ -714,7 +714,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
        struct drm_display_mode *mode;
        int dst_x, dst_y, dst_w, dst_h;
        int src_x, src_y, src_w, src_h;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct sti_gdp_node_list *list;
        struct sti_gdp_node_list *curr_list;
        struct sti_gdp_node *top_field, *btm_field;
@@ -778,15 +778,15 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
        top_field->gam_gdp_ctl |= sti_gdp_get_alpharange(format);
        top_field->gam_gdp_ppt &= ~GAM_GDP_PPT_IGNORE;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
 
        DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
                         (char *)&fb->format->format,
-                        (unsigned long)cma_obj->paddr);
+                        (unsigned long) dma_obj->dma_addr);
 
        /* pixel memory location */
        bpp = fb->format->cpp[0];
-       top_field->gam_gdp_pml = (u32)cma_obj->paddr + fb->offsets[0];
+       top_field->gam_gdp_pml = (u32) dma_obj->dma_addr + fb->offsets[0];
        top_field->gam_gdp_pml += src_x * bpp;
        top_field->gam_gdp_pml += src_y * fb->pitches[0];
 
@@ -831,7 +831,7 @@ static void sti_gdp_atomic_update(struct drm_plane *drm_plane,
        dev_dbg(gdp->dev, "Current NVN:0x%X\n",
                readl(gdp->regs + GAM_GDP_NVN_OFFSET));
        dev_dbg(gdp->dev, "Posted buff: %lx current buff: %x\n",
-               (unsigned long)cma_obj->paddr,
+               (unsigned long) dma_obj->dma_addr,
                readl(gdp->regs + GAM_GDP_PML_OFFSET));
 
        if (!curr_list) {
index 2719820804379f9da656a5033a0bbe54a5c0a7ec..02b77279f6e4c44d718f0356d26ca8040c2e2511 100644 (file)
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "sti_compositor.h"
 #include "sti_drv.h"
@@ -1055,8 +1055,8 @@ static int sti_hqvdp_atomic_check(struct drm_plane *drm_plane,
                return -EINVAL;
        }
 
-       if (!drm_fb_cma_get_gem_obj(fb, 0)) {
-               DRM_ERROR("Can't get CMA GEM object for fb\n");
+       if (!drm_fb_dma_get_gem_obj(fb, 0)) {
+               DRM_ERROR("Can't get DMA GEM object for fb\n");
                return -EINVAL;
        }
 
@@ -1124,7 +1124,7 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
        struct drm_display_mode *mode;
        int dst_x, dst_y, dst_w, dst_h;
        int src_x, src_y, src_w, src_h;
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct sti_hqvdp_cmd *cmd;
        int scale_h, scale_v;
        int cmd_offset;
@@ -1178,15 +1178,15 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
        cmd->iqi.sat_gain = IQI_SAT_GAIN_DFLT;
        cmd->iqi.pxf_conf = IQI_PXF_CONF_DFLT;
 
-       cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
 
        DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id,
                         (char *)&fb->format->format,
-                        (unsigned long)cma_obj->paddr);
+                        (unsigned long) dma_obj->dma_addr);
 
        /* Buffer planes address */
-       cmd->top.current_luma = (u32)cma_obj->paddr + fb->offsets[0];
-       cmd->top.current_chroma = (u32)cma_obj->paddr + fb->offsets[1];
+       cmd->top.current_luma = (u32) dma_obj->dma_addr + fb->offsets[0];
+       cmd->top.current_chroma = (u32) dma_obj->dma_addr + fb->offsets[1];
 
        /* Pitches */
        cmd->top.luma_processed_pitch = fb->pitches[0];
index c74b524663abcbc43f2cc169ddb369c56c9fa45a..29e669ccec5b079769cb608a2cbe0867f222893c 100644 (file)
@@ -9,10 +9,9 @@
 #include <linux/types.h>
 
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 
 #include "sti_compositor.h"
 #include "sti_drv.h"
index 8e33e629d9b0412bea97b973a51fe4b9e31ca974..2c0156bede9c4db0340fb9b05ba8f5a3f552211f 100644 (file)
@@ -8,7 +8,6 @@
 #define _STI_PLANE_H_
 
 #include <drm/drm_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #define to_sti_plane(x) container_of(x, struct sti_plane, drm_plane)
 
index e0379488cd0d2e1724687f8cb803e359ed91f11d..ded72f8794820ecfc78241528fb9bb2e136fa798 100644 (file)
@@ -3,7 +3,7 @@ config DRM_STM
        tristate "DRM Support for STMicroelectronics SoC Series"
        depends on DRM && (ARCH_STM32 || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_PANEL_BRIDGE
        select VIDEOMODE_HELPERS
        select FB_PROVIDE_GET_FB_UNMAPPED_AREA if FB
index c63945dc2260c6f7af41698aba3b9958117f17e5..d7914f5122dff046b85fe1d224b9febc186df3f1 100644 (file)
@@ -18,9 +18,8 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -37,7 +36,7 @@ static const struct drm_mode_config_funcs drv_mode_config_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
-static int stm_gem_cma_dumb_create(struct drm_file *file,
+static int stm_gem_dma_dumb_create(struct drm_file *file,
                                   struct drm_device *dev,
                                   struct drm_mode_create_dumb *args)
 {
@@ -50,10 +49,10 @@ static int stm_gem_cma_dumb_create(struct drm_file *file,
        args->pitch = roundup(min_pitch, 128);
        args->height = roundup(args->height, 4);
 
-       return drm_gem_cma_dumb_create_internal(file, dev, args);
+       return drm_gem_dma_dumb_create_internal(file, dev, args);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops);
+DEFINE_DRM_GEM_DMA_FOPS(drv_driver_fops);
 
 static const struct drm_driver drv_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
@@ -64,7 +63,7 @@ static const struct drm_driver drv_driver = {
        .minor = 0,
        .patchlevel = 0,
        .fops = &drv_driver_fops,
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_cma_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(stm_gem_dma_dumb_create),
 };
 
 static int drv_load(struct drm_device *ddev)
index da7a0a183b27cb980069740318ec8dadde5692e0..03c6becda795c2b1f9ea907496eb068ef47846ee 100644 (file)
 #include <drm/drm_bridge.h>
 #include <drm/drm_device.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_of.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <drm/drm_vblank.h>
@@ -1347,7 +1346,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
        }
 
        /* Sets the FB address */
-       paddr = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 0);
+       paddr = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 0);
 
        if (newstate->rotation & DRM_MODE_REFLECT_X)
                paddr += (fb->format->cpp[0] * (x1 - x0 + 1)) - 1;
@@ -1381,7 +1380,7 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
                        case DRM_FORMAT_NV12:
                        case DRM_FORMAT_NV21:
                        /* Configure the auxiliary frame buffer address 0 */
-                       paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
+                       paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1);
 
                        if (newstate->rotation & DRM_MODE_REFLECT_X)
                                paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1;
@@ -1393,8 +1392,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
                        break;
                        case DRM_FORMAT_YUV420:
                        /* Configure the auxiliary frame buffer address 0 & 1 */
-                       paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
-                       paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2);
+                       paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1);
+                       paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2);
 
                        if (newstate->rotation & DRM_MODE_REFLECT_X) {
                                paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1;
@@ -1411,8 +1410,8 @@ static void ltdc_plane_atomic_update(struct drm_plane *plane,
                        break;
                        case DRM_FORMAT_YVU420:
                        /* Configure the auxiliary frame buffer address 0 & 1 */
-                       paddr1 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 2);
-                       paddr2 = (u32)drm_fb_cma_get_gem_addr(fb, newstate, 1);
+                       paddr1 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 2);
+                       paddr2 = (u32)drm_fb_dma_get_gem_addr(fb, newstate, 1);
 
                        if (newstate->rotation & DRM_MODE_REFLECT_X) {
                                paddr1 += ((fb->format->cpp[1] * (x1 - x0 + 1)) >> 1) - 1;
index 3a43c436c74a78d08d526146f65c9b39aff6f68c..4741d9f6544c201b699d57385a1ddbc826bf84ce 100644 (file)
@@ -3,7 +3,7 @@ config DRM_SUN4I
        tristate "DRM Support for Allwinner A10 Display Engine"
        depends on DRM && COMMON_CLK
        depends on ARCH_SUNXI || COMPILE_TEST
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_PANEL
        select REGMAP_MMIO
@@ -16,23 +16,25 @@ config DRM_SUN4I
 if DRM_SUN4I
 
 config DRM_SUN4I_HDMI
-       tristate "Allwinner A10 HDMI Controller Support"
+       tristate "Allwinner A10/A10s/A20/A31 HDMI Controller Support"
+       depends on ARM || COMPILE_TEST
        default DRM_SUN4I
        help
-         Choose this option if you have an Allwinner SoC with an HDMI
-         controller.
+         Choose this option if you have an Allwinner A10/A10s/A20/A31
+         SoC with an HDMI controller.
 
 config DRM_SUN4I_HDMI_CEC
-       bool "Allwinner A10 HDMI CEC Support"
+       bool "Allwinner A10/A10s/A20/A31 HDMI CEC Support"
        depends on DRM_SUN4I_HDMI
        select CEC_CORE
        select CEC_PIN
        help
-         Choose this option if you have an Allwinner SoC with an HDMI
-         controller and want to use CEC.
+         Choose this option if you have an Allwinner A10/A10s/A20/A31
+         SoC with an HDMI controller and want to use CEC.
 
 config DRM_SUN4I_BACKEND
        tristate "Support for Allwinner A10 Display Engine Backend"
+       depends on ARM || COMPILE_TEST
        default DRM_SUN4I
        help
          Choose this option if you have an Allwinner SoC with the
@@ -41,8 +43,8 @@ config DRM_SUN4I_BACKEND
          selected the module will be called sun4i-backend.
 
 config DRM_SUN6I_DSI
-       tristate "Allwinner A31 MIPI-DSI Controller Support"
-       default MACH_SUN8I
+       tristate "Allwinner A31/A64 MIPI-DSI Controller Support"
+       default DRM_SUN4I
        select CRC_CCITT
        select DRM_MIPI_DSI
        select RESET_CONTROLLER
@@ -55,15 +57,17 @@ config DRM_SUN6I_DSI
 config DRM_SUN8I_DW_HDMI
        tristate "Support for Allwinner version of DesignWare HDMI"
        depends on DRM_SUN4I
+       default DRM_SUN4I
        select DRM_DW_HDMI
        help
          Choose this option if you have an Allwinner SoC with the
-         DesignWare HDMI controller with custom HDMI PHY. If M is
+         DesignWare HDMI controller. SoCs that support HDMI and
+         have a Display Engine 2.0 contain this controller. If M is
          selected the module will be called sun8i_dw_hdmi.
 
 config DRM_SUN8I_MIXER
        tristate "Support for Allwinner Display Engine 2.0 Mixer"
-       default MACH_SUN8I
+       default DRM_SUN4I
        help
          Choose this option if you have an Allwinner SoC with the
          Allwinner Display Engine 2.0, which has a mixer to do some
@@ -75,6 +79,6 @@ config DRM_SUN8I_TCON_TOP
        default DRM_SUN4I if DRM_SUN8I_MIXER!=n
        help
          TCON TOP is responsible for configuring display pipeline for
-         HTMI, TVE and LCD.
+         HDMI, TVE and LCD.
 
 endif
index 287e8c4bbaea106493d9d775e3b0db177c143a6e..38070fc261f3af53aeb7dbb143943148b62fed38 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_backend.h"
@@ -330,7 +329,7 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
        u32 lo_paddr, hi_paddr;
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
 
        /* Set the line width */
        DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
@@ -339,21 +338,21 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
                     fb->pitches[0] * 8);
 
        /* Get the start of the displayed memory */
-       paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
-       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+       dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
+       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &dma_addr);
 
        if (fb->format->is_yuv)
-               return sun4i_backend_update_yuv_buffer(backend, fb, paddr);
+               return sun4i_backend_update_yuv_buffer(backend, fb, dma_addr);
 
        /* Write the 32 lower bits of the address (in bits) */
-       lo_paddr = paddr << 3;
+       lo_paddr = dma_addr << 3;
        DRM_DEBUG_DRIVER("Setting address lower bits to 0x%x\n", lo_paddr);
        regmap_write(backend->engine.regs,
                     SUN4I_BACKEND_LAYFB_L32ADD_REG(layer),
                     lo_paddr);
 
        /* And the upper bits */
-       hi_paddr = paddr >> 29;
+       hi_paddr = dma_addr >> 29;
        DRM_DEBUG_DRIVER("Setting address high bits to 0x%x\n", hi_paddr);
        regmap_update_bits(backend->engine.regs, SUN4I_BACKEND_LAYFB_H4ADD_REG,
                           SUN4I_BACKEND_LAYFB_H4ADD_MSK(layer),
index 6eb1aabdb1618b36dcda5ed7dfd449ac180c5eaf..d06ffd99d86e157523f082673ca67affd83f392c 100644 (file)
@@ -17,9 +17,8 @@
 #include <drm/drm_aperture.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_of.h>
 #include <drm/drm_probe_helper.h>
@@ -38,10 +37,10 @@ static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv,
        /* The hardware only allows even pitches for YUV buffers. */
        args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2);
 
-       return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
+       return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops);
+DEFINE_DRM_GEM_DMA_FOPS(sun4i_drv_fops);
 
 static const struct drm_driver sun4i_drv_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
@@ -55,7 +54,7 @@ static const struct drm_driver sun4i_drv_driver = {
        .minor                  = 0,
 
        /* GEM Operations */
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create),
 };
 
 static int sun4i_drv_bind(struct device *dev)
index 462fae73eae98e13a9c09502513135afbdcbb1c8..799ab7460ae5427901bc7e018f2d61c95aac8be4 100644 (file)
 #include <linux/reset.h>
 
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_plane.h>
 
 #include "sun4i_drv.h"
@@ -160,7 +160,7 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
        struct drm_framebuffer *fb = state->fb;
        unsigned int strides[3] = {};
 
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        bool swap;
 
        if (fb->modifier == DRM_FORMAT_MOD_ALLWINNER_TILED) {
@@ -221,22 +221,24 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
        swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format);
 
        /* Set the physical address of the buffer in memory */
-       paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
-       DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &paddr);
-       regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, paddr);
+       dma_addr = drm_fb_dma_get_gem_addr(fb, state, 0);
+       DRM_DEBUG_DRIVER("Setting buffer #0 address to %pad\n", &dma_addr);
+       regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR0_REG, dma_addr);
 
        if (fb->format->num_planes > 1) {
-               paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 2 : 1);
-               DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n", &paddr);
+               dma_addr = drm_fb_dma_get_gem_addr(fb, state, swap ? 2 : 1);
+               DRM_DEBUG_DRIVER("Setting buffer #1 address to %pad\n",
+                                &dma_addr);
                regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR1_REG,
-                            paddr);
+                            dma_addr);
        }
 
        if (fb->format->num_planes > 2) {
-               paddr = drm_fb_cma_get_gem_addr(fb, state, swap ? 1 : 2);
-               DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n", &paddr);
+               dma_addr = drm_fb_dma_get_gem_addr(fb, state, swap ? 1 : 2);
+               DRM_DEBUG_DRIVER("Setting buffer #2 address to %pad\n",
+                                &dma_addr);
                regmap_write(frontend->regs, SUN4I_FRONTEND_BUF_ADDR2_REG,
-                            paddr);
+                            dma_addr);
        }
 }
 EXPORT_SYMBOL(sun4i_frontend_update_buffer);
index 648dd0b5b1165f4036ab1ef8a465003d8dd9e299..98f3176366c0e6381c83bb54f1cd07dba73c12f1 100644 (file)
@@ -10,7 +10,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "sun4i_backend.h"
 #include "sun4i_frontend.h"
index 648b38a7306663e4a532b460b597e8a270d5bdbf..bafee05f6b247697415ab126999fd5bf8a7576b0 100644 (file)
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun4i_drv.h"
index 36da962de39468d619dbb80c2cd3617cbd0140ba..ca75ca0835a636ba287a78124cafb09a2c8d5a45 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun8i_mixer.h"
@@ -193,25 +192,25 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 {
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *gem;
-       dma_addr_t paddr;
+       struct drm_gem_dma_object *gem;
+       dma_addr_t dma_addr;
        u32 ch_base;
        int bpp;
 
        ch_base = sun8i_channel_base(mixer, channel);
 
        /* Get the physical address of the buffer in memory */
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
 
-       DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+       DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
 
        /* Compute the start of the displayed memory */
        bpp = fb->format->cpp[0];
-       paddr = gem->paddr + fb->offsets[0];
+       dma_addr = gem->dma_addr + fb->offsets[0];
 
        /* Fixup framebuffer address for src coordinates */
-       paddr += (state->src.x1 >> 16) * bpp;
-       paddr += (state->src.y1 >> 16) * fb->pitches[0];
+       dma_addr += (state->src.x1 >> 16) * bpp;
+       dma_addr += (state->src.y1 >> 16) * fb->pitches[0];
 
        /* Set the line width */
        DRM_DEBUG_DRIVER("Layer line width: %d bytes\n", fb->pitches[0]);
@@ -219,11 +218,11 @@ static int sun8i_ui_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
                     SUN8I_MIXER_CHAN_UI_LAYER_PITCH(ch_base, overlay),
                     fb->pitches[0]);
 
-       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
+       DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &dma_addr);
 
        regmap_write(mixer->engine.regs,
                     SUN8I_MIXER_CHAN_UI_LAYER_TOP_LADDR(ch_base, overlay),
-                    lower_32_bits(paddr));
+                    lower_32_bits(dma_addr));
 
        return 0;
 }
@@ -246,8 +245,8 @@ static int sun8i_ui_layer_atomic_check(struct drm_plane *plane,
        if (WARN_ON(!crtc_state))
                return -EINVAL;
 
-       min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       max_scale = DRM_PLANE_HELPER_NO_SCALING;
+       min_scale = DRM_PLANE_NO_SCALING;
+       max_scale = DRM_PLANE_NO_SCALING;
 
        if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
                min_scale = SUN8I_UI_SCALER_SCALE_MIN;
index 1fee6499bdd3735f24779243f8b0a6390dedc76d..f9c0a56d3a148efb287b5cd764bf1b3a9b697fe3 100644 (file)
@@ -7,11 +7,10 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_probe_helper.h>
 
 #include "sun8i_csc.h"
@@ -309,9 +308,9 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
        struct drm_plane_state *state = plane->state;
        struct drm_framebuffer *fb = state->fb;
        const struct drm_format_info *format = fb->format;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        u32 dx, dy, src_x, src_y;
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        u32 ch_base;
        int i;
 
@@ -323,12 +322,12 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
 
        for (i = 0; i < format->num_planes; i++) {
                /* Get the physical address of the buffer in memory */
-               gem = drm_fb_cma_get_gem_obj(fb, i);
+               gem = drm_fb_dma_get_gem_obj(fb, i);
 
-               DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->paddr);
+               DRM_DEBUG_DRIVER("Using GEM @ %pad\n", &gem->dma_addr);
 
                /* Compute the start of the displayed memory */
-               paddr = gem->paddr + fb->offsets[i];
+               dma_addr = gem->dma_addr + fb->offsets[i];
 
                dx = src_x;
                dy = src_y;
@@ -339,8 +338,8 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
                }
 
                /* Fixup framebuffer address for src coordinates */
-               paddr += dx * format->cpp[i];
-               paddr += dy * fb->pitches[i];
+               dma_addr += dx * format->cpp[i];
+               dma_addr += dy * fb->pitches[i];
 
                /* Set the line width */
                DRM_DEBUG_DRIVER("Layer %d. line width: %d bytes\n",
@@ -351,12 +350,12 @@ static int sun8i_vi_layer_update_buffer(struct sun8i_mixer *mixer, int channel,
                             fb->pitches[i]);
 
                DRM_DEBUG_DRIVER("Setting %d. buffer address to %pad\n",
-                                i + 1, &paddr);
+                                i + 1, &dma_addr);
 
                regmap_write(mixer->engine.regs,
                             SUN8I_MIXER_CHAN_VI_LAYER_TOP_LADDR(ch_base,
                                                                 overlay, i),
-                            lower_32_bits(paddr));
+                            lower_32_bits(dma_addr));
        }
 
        return 0;
@@ -380,8 +379,8 @@ static int sun8i_vi_layer_atomic_check(struct drm_plane *plane,
        if (WARN_ON(!crtc_state))
                return -EINVAL;
 
-       min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       max_scale = DRM_PLANE_HELPER_NO_SCALING;
+       min_scale = DRM_PLANE_NO_SCALING;
+       max_scale = DRM_PLANE_NO_SCALING;
 
        if (layer->mixer->cfg->scaler_mask & BIT(layer->channel)) {
                min_scale = SUN8I_VI_SCALER_SCALE_MIN;
index 747abafb6a5cf78fdf246bb68e1f671649fdf517..bd0f60704467f4ab529771ae8c2088e3ffa89f78 100644 (file)
@@ -26,7 +26,6 @@
 #include <drm/drm_debugfs.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "dc.h"
index ed828de5ac01494e876c3d4e9ebd309ac5dc272a..9291209154a7a947e6d7d2bbfb4057e6e592b4d4 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 2012-2013 Avionic Design GmbH
  * Copyright (C) 2012 NVIDIA CORPORATION.  All rights reserved.
  *
- * Based on the KMS/FB CMA helpers
+ * Based on the KMS/FB DMA helpers
  *   Copyright (C) 2012 Analog Devices Inc.
  */
 
index ca9f03e3675bf097cb95b2eb789ac630c0148c28..10090116895ff929f17388772ad4f434237ce1bd 100644 (file)
@@ -12,7 +12,6 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "dc.h"
 #include "plane.h"
index 2c8273796d9de0cac38938f712d4a3c20c8c8449..91b70f7d27699c4e76892d626ba142605194a4bf 100644 (file)
@@ -1,3 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o
+obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \
+       drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \
+       drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o
diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c
new file mode 100644 (file)
index 0000000..d76f838
--- /dev/null
@@ -0,0 +1,756 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright Â© 2019 Intel Corporation
+ * Copyright Â© 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
+
+#include <drm/drm_buddy.h>
+
+#include "../lib/drm_random.h"
+
+#define IGT_TIMEOUT(name__)                                                    \
+       unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
+
+static unsigned int random_seed;
+
+static inline u64 get_size(int order, u64 chunk_size)
+{
+       return (1 << order) * chunk_size;
+}
+
+__printf(2, 3)
+static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
+{
+       va_list va;
+
+       if (!signal_pending(current)) {
+               cond_resched();
+               if (time_before(jiffies, timeout))
+                       return false;
+       }
+
+       if (fmt) {
+               va_start(va, fmt);
+               vprintk(fmt, va);
+               va_end(va);
+       }
+
+       return true;
+}
+
+static void __igt_dump_block(struct kunit *test, struct drm_buddy *mm,
+                            struct drm_buddy_block *block, bool buddy)
+{
+       kunit_err(test, "block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%d buddy=%d\n",
+                 block->header, drm_buddy_block_state(block),
+                         drm_buddy_block_order(block), drm_buddy_block_offset(block),
+                         drm_buddy_block_size(mm, block), !block->parent, buddy);
+}
+
+static void igt_dump_block(struct kunit *test, struct drm_buddy *mm,
+                          struct drm_buddy_block *block)
+{
+       struct drm_buddy_block *buddy;
+
+       __igt_dump_block(test, mm, block, false);
+
+       buddy = drm_get_buddy(block);
+       if (buddy)
+               __igt_dump_block(test, mm, buddy, true);
+}
+
+static int igt_check_block(struct kunit *test, struct drm_buddy *mm,
+                          struct drm_buddy_block *block)
+{
+       struct drm_buddy_block *buddy;
+       unsigned int block_state;
+       u64 block_size;
+       u64 offset;
+       int err = 0;
+
+       block_state = drm_buddy_block_state(block);
+
+       if (block_state != DRM_BUDDY_ALLOCATED &&
+           block_state != DRM_BUDDY_FREE && block_state != DRM_BUDDY_SPLIT) {
+               kunit_err(test, "block state mismatch\n");
+               err = -EINVAL;
+       }
+
+       block_size = drm_buddy_block_size(mm, block);
+       offset = drm_buddy_block_offset(block);
+
+       if (block_size < mm->chunk_size) {
+               kunit_err(test, "block size smaller than min size\n");
+               err = -EINVAL;
+       }
+
+       if (!is_power_of_2(block_size)) {
+               kunit_err(test, "block size not power of two\n");
+               err = -EINVAL;
+       }
+
+       if (!IS_ALIGNED(block_size, mm->chunk_size)) {
+               kunit_err(test, "block size not aligned to min size\n");
+               err = -EINVAL;
+       }
+
+       if (!IS_ALIGNED(offset, mm->chunk_size)) {
+               kunit_err(test, "block offset not aligned to min size\n");
+               err = -EINVAL;
+       }
+
+       if (!IS_ALIGNED(offset, block_size)) {
+               kunit_err(test, "block offset not aligned to block size\n");
+               err = -EINVAL;
+       }
+
+       buddy = drm_get_buddy(block);
+
+       if (!buddy && block->parent) {
+               kunit_err(test, "buddy has gone fishing\n");
+               err = -EINVAL;
+       }
+
+       if (buddy) {
+               if (drm_buddy_block_offset(buddy) != (offset ^ block_size)) {
+                       kunit_err(test, "buddy has wrong offset\n");
+                       err = -EINVAL;
+               }
+
+               if (drm_buddy_block_size(mm, buddy) != block_size) {
+                       kunit_err(test, "buddy size mismatch\n");
+                       err = -EINVAL;
+               }
+
+               if (drm_buddy_block_state(buddy) == block_state &&
+                   block_state == DRM_BUDDY_FREE) {
+                       kunit_err(test, "block and its buddy are free\n");
+                       err = -EINVAL;
+               }
+       }
+
+       return err;
+}
+
+static int igt_check_blocks(struct kunit *test, struct drm_buddy *mm,
+                           struct list_head *blocks, u64 expected_size, bool is_contiguous)
+{
+       struct drm_buddy_block *block;
+       struct drm_buddy_block *prev;
+       u64 total;
+       int err = 0;
+
+       block = NULL;
+       prev = NULL;
+       total = 0;
+
+       list_for_each_entry(block, blocks, link) {
+               err = igt_check_block(test, mm, block);
+
+               if (!drm_buddy_block_is_allocated(block)) {
+                       kunit_err(test, "block not allocated\n");
+                       err = -EINVAL;
+               }
+
+               if (is_contiguous && prev) {
+                       u64 prev_block_size;
+                       u64 prev_offset;
+                       u64 offset;
+
+                       prev_offset = drm_buddy_block_offset(prev);
+                       prev_block_size = drm_buddy_block_size(mm, prev);
+                       offset = drm_buddy_block_offset(block);
+
+                       if (offset != (prev_offset + prev_block_size)) {
+                               kunit_err(test, "block offset mismatch\n");
+                               err = -EINVAL;
+                       }
+               }
+
+               if (err)
+                       break;
+
+               total += drm_buddy_block_size(mm, block);
+               prev = block;
+       }
+
+       if (!err) {
+               if (total != expected_size) {
+                       kunit_err(test, "size mismatch, expected=%llx, found=%llx\n",
+                                 expected_size, total);
+                       err = -EINVAL;
+               }
+               return err;
+       }
+
+       if (prev) {
+               kunit_err(test, "prev block, dump:\n");
+               igt_dump_block(test, mm, prev);
+       }
+
+       kunit_err(test, "bad block, dump:\n");
+       igt_dump_block(test, mm, block);
+
+       return err;
+}
+
+static int igt_check_mm(struct kunit *test, struct drm_buddy *mm)
+{
+       struct drm_buddy_block *root;
+       struct drm_buddy_block *prev;
+       unsigned int i;
+       u64 total;
+       int err = 0;
+
+       if (!mm->n_roots) {
+               kunit_err(test, "n_roots is zero\n");
+               return -EINVAL;
+       }
+
+       if (mm->n_roots != hweight64(mm->size)) {
+               kunit_err(test, "n_roots mismatch, n_roots=%u, expected=%lu\n",
+                         mm->n_roots, hweight64(mm->size));
+               return -EINVAL;
+       }
+
+       root = NULL;
+       prev = NULL;
+       total = 0;
+
+       for (i = 0; i < mm->n_roots; ++i) {
+               struct drm_buddy_block *block;
+               unsigned int order;
+
+               root = mm->roots[i];
+               if (!root) {
+                       kunit_err(test, "root(%u) is NULL\n", i);
+                       err = -EINVAL;
+                       break;
+               }
+
+               err = igt_check_block(test, mm, root);
+
+               if (!drm_buddy_block_is_free(root)) {
+                       kunit_err(test, "root not free\n");
+                       err = -EINVAL;
+               }
+
+               order = drm_buddy_block_order(root);
+
+               if (!i) {
+                       if (order != mm->max_order) {
+                               kunit_err(test, "max order root missing\n");
+                               err = -EINVAL;
+                       }
+               }
+
+               if (prev) {
+                       u64 prev_block_size;
+                       u64 prev_offset;
+                       u64 offset;
+
+                       prev_offset = drm_buddy_block_offset(prev);
+                       prev_block_size = drm_buddy_block_size(mm, prev);
+                       offset = drm_buddy_block_offset(root);
+
+                       if (offset != (prev_offset + prev_block_size)) {
+                               kunit_err(test, "root offset mismatch\n");
+                               err = -EINVAL;
+                       }
+               }
+
+               block = list_first_entry_or_null(&mm->free_list[order],
+                                                struct drm_buddy_block, link);
+               if (block != root) {
+                       kunit_err(test, "root mismatch at order=%u\n", order);
+                       err = -EINVAL;
+               }
+
+               if (err)
+                       break;
+
+               prev = root;
+               total += drm_buddy_block_size(mm, root);
+       }
+
+       if (!err) {
+               if (total != mm->size) {
+                       kunit_err(test, "expected mm size=%llx, found=%llx\n",
+                                 mm->size, total);
+                       err = -EINVAL;
+               }
+               return err;
+       }
+
+       if (prev) {
+               kunit_err(test, "prev root(%u), dump:\n", i - 1);
+               igt_dump_block(test, mm, prev);
+       }
+
+       if (root) {
+               kunit_err(test, "bad root(%u), dump:\n", i);
+               igt_dump_block(test, mm, root);
+       }
+
+       return err;
+}
+
+static void igt_mm_config(u64 *size, u64 *chunk_size)
+{
+       DRM_RND_STATE(prng, random_seed);
+       u32 s, ms;
+
+       /* Nothing fancy, just try to get an interesting bit pattern */
+
+       prandom_seed_state(&prng, random_seed);
+
+       /* Let size be a random number of pages up to 8 GB (2M pages) */
+       s = 1 + drm_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng);
+       /* Let the chunk size be a random power of 2 less than size */
+       ms = BIT(drm_prandom_u32_max_state(ilog2(s), &prng));
+       /* Round size down to the chunk size */
+       s &= -ms;
+
+       /* Convert from pages to bytes */
+       *chunk_size = (u64)ms << 12;
+       *size = (u64)s << 12;
+}
+
+static void igt_buddy_alloc_pathological(struct kunit *test)
+{
+       u64 mm_size, size, start = 0;
+       struct drm_buddy_block *block;
+       const int max_order = 3;
+       unsigned long flags = 0;
+       int order, top;
+       struct drm_buddy mm;
+       LIST_HEAD(blocks);
+       LIST_HEAD(holes);
+       LIST_HEAD(tmp);
+
+       /*
+        * Create a pot-sized mm, then allocate one of each possible
+        * order within. This should leave the mm with exactly one
+        * page left. Free the largest block, then whittle down again.
+        * Eventually we will have a fully 50% fragmented mm.
+        */
+
+       mm_size = PAGE_SIZE << max_order;
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE),
+                              "buddy_init failed\n");
+
+       KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+       for (top = max_order; top; top--) {
+               /* Make room by freeing the largest allocated block */
+               block = list_first_entry_or_null(&blocks, typeof(*block), link);
+               if (block) {
+                       list_del(&block->link);
+                       drm_buddy_free_block(&mm, block);
+               }
+
+               for (order = top; order--;) {
+                       size = get_size(order, PAGE_SIZE);
+                       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start,
+                                                                           mm_size, size, size,
+                                                                               &tmp, flags),
+                                       "buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+                                       order, top);
+
+                       block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+                       KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+                       list_move_tail(&block->link, &blocks);
+               }
+
+               /* There should be one final page for this sub-allocation */
+               size = get_size(0, PAGE_SIZE);
+               KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                   size, size, &tmp, flags),
+                                                          "buddy_alloc hit -ENOMEM for hole\n");
+
+               block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+               KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+               list_move_tail(&block->link, &holes);
+
+               size = get_size(top, PAGE_SIZE);
+               KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                  size, size, &tmp, flags),
+                                                         "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+                                                         top, max_order);
+       }
+
+       drm_buddy_free_list(&mm, &holes);
+
+       /* Nothing larger than blocks of chunk_size now available */
+       for (order = 1; order <= max_order; order++) {
+               size = get_size(order, PAGE_SIZE);
+               KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                  size, size, &tmp, flags),
+                                                         "buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+                                                         order);
+       }
+
+       list_splice_tail(&holes, &blocks);
+       drm_buddy_free_list(&mm, &blocks);
+       drm_buddy_fini(&mm);
+}
+
+static void igt_buddy_alloc_smoke(struct kunit *test)
+{
+       u64 mm_size, chunk_size, start = 0;
+       unsigned long flags = 0;
+       struct drm_buddy mm;
+       int *order;
+       int i;
+
+       DRM_RND_STATE(prng, random_seed);
+       IGT_TIMEOUT(end_time);
+
+       igt_mm_config(&mm_size, &chunk_size);
+
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, chunk_size),
+                              "buddy_init failed\n");
+
+       order = drm_random_order(mm.max_order + 1, &prng);
+       KUNIT_ASSERT_TRUE(test, order);
+
+       for (i = 0; i <= mm.max_order; ++i) {
+               struct drm_buddy_block *block;
+               int max_order = order[i];
+               bool timeout = false;
+               LIST_HEAD(blocks);
+               u64 total, size;
+               LIST_HEAD(tmp);
+               int order, err;
+
+               KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm),
+                                      "pre-mm check failed, abort\n");
+
+               order = max_order;
+               total = 0;
+
+               do {
+retry:
+                       size = get_size(order, chunk_size);
+                       err = drm_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags);
+                       if (err) {
+                               if (err == -ENOMEM) {
+                                       KUNIT_FAIL(test, "buddy_alloc hit -ENOMEM with order=%d\n",
+                                                  order);
+                               } else {
+                                       if (order--) {
+                                               err = 0;
+                                               goto retry;
+                                       }
+
+                                       KUNIT_FAIL(test, "buddy_alloc with order=%d failed\n",
+                                                  order);
+                               }
+
+                               break;
+                       }
+
+                       block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+                       KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+                       list_move_tail(&block->link, &blocks);
+                       KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), order,
+                                           "buddy_alloc order mismatch\n");
+
+                       total += drm_buddy_block_size(&mm, block);
+
+                       if (__igt_timeout(end_time, NULL)) {
+                               timeout = true;
+                               break;
+                       }
+               } while (total < mm.size);
+
+               if (!err)
+                       err = igt_check_blocks(test, &mm, &blocks, total, false);
+
+               drm_buddy_free_list(&mm, &blocks);
+
+               if (!err) {
+                       KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm),
+                                              "post-mm check failed\n");
+               }
+
+               if (err || timeout)
+                       break;
+
+               cond_resched();
+       }
+
+       kfree(order);
+       drm_buddy_fini(&mm);
+}
+
+static void igt_buddy_alloc_pessimistic(struct kunit *test)
+{
+       u64 mm_size, size, start = 0;
+       struct drm_buddy_block *block, *bn;
+       const unsigned int max_order = 16;
+       unsigned long flags = 0;
+       struct drm_buddy mm;
+       unsigned int order;
+       LIST_HEAD(blocks);
+       LIST_HEAD(tmp);
+
+       /*
+        * Create a pot-sized mm, then allocate one of each possible
+        * order within. This should leave the mm with exactly one
+        * page left.
+        */
+
+       mm_size = PAGE_SIZE << max_order;
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE),
+                              "buddy_init failed\n");
+
+       KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+       for (order = 0; order < max_order; order++) {
+               size = get_size(order, PAGE_SIZE);
+               KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                   size, size, &tmp, flags),
+                                                          "buddy_alloc hit -ENOMEM with order=%d\n",
+                                                          order);
+
+               block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+               KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+               list_move_tail(&block->link, &blocks);
+       }
+
+       /* And now the last remaining block available */
+       size = get_size(0, PAGE_SIZE);
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                           size, size, &tmp, flags),
+                                                  "buddy_alloc hit -ENOMEM on final alloc\n");
+
+       block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+       KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+       list_move_tail(&block->link, &blocks);
+
+       /* Should be completely full! */
+       for (order = max_order; order--;) {
+               size = get_size(order, PAGE_SIZE);
+               KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                  size, size, &tmp, flags),
+                                                         "buddy_alloc unexpectedly succeeded, it should be full!");
+       }
+
+       block = list_last_entry(&blocks, typeof(*block), link);
+       list_del(&block->link);
+       drm_buddy_free_block(&mm, block);
+
+       /* As we free in increasing size, we make available larger blocks */
+       order = 1;
+       list_for_each_entry_safe(block, bn, &blocks, link) {
+               list_del(&block->link);
+               drm_buddy_free_block(&mm, block);
+
+               size = get_size(order, PAGE_SIZE);
+               KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                   size, size, &tmp, flags),
+                                                          "buddy_alloc hit -ENOMEM with order=%d\n",
+                                                          order);
+
+               block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+               KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+               list_del(&block->link);
+               drm_buddy_free_block(&mm, block);
+               order++;
+       }
+
+       /* To confirm, now the whole mm should be available */
+       size = get_size(max_order, PAGE_SIZE);
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                           size, size, &tmp, flags),
+                                                  "buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+                                                  max_order);
+
+       block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+       KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+       list_del(&block->link);
+       drm_buddy_free_block(&mm, block);
+       drm_buddy_free_list(&mm, &blocks);
+       drm_buddy_fini(&mm);
+}
+
+static void igt_buddy_alloc_optimistic(struct kunit *test)
+{
+       u64 mm_size, size, start = 0;
+       struct drm_buddy_block *block;
+       unsigned long flags = 0;
+       const int max_order = 16;
+       struct drm_buddy mm;
+       LIST_HEAD(blocks);
+       LIST_HEAD(tmp);
+       int order;
+
+       /*
+        * Create a mm with one block of each order available, and
+        * try to allocate them all.
+        */
+
+       mm_size = PAGE_SIZE * ((1 << (max_order + 1)) - 1);
+
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, PAGE_SIZE),
+                              "buddy_init failed\n");
+
+       KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+       for (order = 0; order <= max_order; order++) {
+               size = get_size(order, PAGE_SIZE);
+               KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                                   size, size, &tmp, flags),
+                                                          "buddy_alloc hit -ENOMEM with order=%d\n",
+                                                          order);
+
+               block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+               KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+               list_move_tail(&block->link, &blocks);
+       }
+
+       /* Should be completely full! */
+       size = get_size(0, PAGE_SIZE);
+       KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
+                                                          size, size, &tmp, flags),
+                                                 "buddy_alloc unexpectedly succeeded, it should be full!");
+
+       drm_buddy_free_list(&mm, &blocks);
+       drm_buddy_fini(&mm);
+}
+
+static void igt_buddy_alloc_range(struct kunit *test)
+{
+       unsigned long flags = DRM_BUDDY_RANGE_ALLOCATION;
+       u64 offset, size, rem, chunk_size, end;
+       unsigned long page_num;
+       struct drm_buddy mm;
+       LIST_HEAD(blocks);
+
+       igt_mm_config(&size, &chunk_size);
+
+       KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, size, chunk_size),
+                              "buddy_init failed");
+
+       KUNIT_ASSERT_FALSE_MSG(test, igt_check_mm(test, &mm),
+                              "pre-mm check failed, abort!");
+
+       rem = mm.size;
+       offset = 0;
+
+       for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) {
+               struct drm_buddy_block *block;
+               LIST_HEAD(tmp);
+
+               size = min(page_num * mm.chunk_size, rem);
+               end = offset + size;
+
+               KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, offset, end,
+                                                                   size, mm.chunk_size,
+                                                                       &tmp, flags),
+                               "alloc_range with offset=%llx, size=%llx failed\n", offset, size);
+
+               block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
+               KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_range has no blocks\n");
+
+               KUNIT_ASSERT_EQ_MSG(test, drm_buddy_block_offset(block), offset,
+                                   "alloc_range start offset mismatch, found=%llx, expected=%llx\n",
+                                                       drm_buddy_block_offset(block), offset);
+
+               KUNIT_ASSERT_FALSE(test, igt_check_blocks(test, &mm, &tmp, size, true));
+
+               list_splice_tail(&tmp, &blocks);
+
+               offset += size;
+
+               rem -= size;
+               if (!rem)
+                       break;
+
+               cond_resched();
+       }
+
+       drm_buddy_free_list(&mm, &blocks);
+
+       KUNIT_EXPECT_FALSE_MSG(test, igt_check_mm(test, &mm), "post-mm check failed\n");
+
+       drm_buddy_fini(&mm);
+}
+
+static void igt_buddy_alloc_limit(struct kunit *test)
+{
+       u64 size = U64_MAX, start = 0;
+       struct drm_buddy_block *block;
+       unsigned long flags = 0;
+       LIST_HEAD(allocated);
+       struct drm_buddy mm;
+
+       KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, size, PAGE_SIZE));
+
+       KUNIT_EXPECT_EQ_MSG(test, mm.max_order, DRM_BUDDY_MAX_ORDER,
+                           "mm.max_order(%d) != %d\n", mm.max_order,
+                                               DRM_BUDDY_MAX_ORDER);
+
+       size = mm.chunk_size << mm.max_order;
+       KUNIT_EXPECT_FALSE(test, drm_buddy_alloc_blocks(&mm, start, size, size,
+                                                       PAGE_SIZE, &allocated, flags));
+
+       block = list_first_entry_or_null(&allocated, struct drm_buddy_block, link);
+       KUNIT_EXPECT_TRUE(test, block);
+
+       KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), mm.max_order,
+                           "block order(%d) != %d\n",
+                                               drm_buddy_block_order(block), mm.max_order);
+
+       KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_size(&mm, block),
+                           BIT_ULL(mm.max_order) * PAGE_SIZE,
+                                               "block size(%llu) != %llu\n",
+                                               drm_buddy_block_size(&mm, block),
+                                               BIT_ULL(mm.max_order) * PAGE_SIZE);
+
+       drm_buddy_free_list(&mm, &allocated);
+       drm_buddy_fini(&mm);
+}
+
+static int drm_buddy_init_test(struct kunit *test)
+{
+       while (!random_seed)
+               random_seed = get_random_int();
+
+       return 0;
+}
+
+static struct kunit_case drm_buddy_tests[] = {
+       KUNIT_CASE(igt_buddy_alloc_limit),
+       KUNIT_CASE(igt_buddy_alloc_range),
+       KUNIT_CASE(igt_buddy_alloc_optimistic),
+       KUNIT_CASE(igt_buddy_alloc_pessimistic),
+       KUNIT_CASE(igt_buddy_alloc_smoke),
+       KUNIT_CASE(igt_buddy_alloc_pathological),
+       {}
+};
+
+static struct kunit_suite drm_buddy_test_suite = {
+       .name = "drm_buddy",
+       .init = drm_buddy_init_test,
+       .test_cases = drm_buddy_tests,
+};
+
+kunit_test_suite(drm_buddy_test_suite);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c
new file mode 100644 (file)
index 0000000..59b29cd
--- /dev/null
@@ -0,0 +1,1078 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 Bootlin
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_modes.h>
+
+static const struct drm_connector no_connector = {};
+
+static void drm_cmdline_test_force_e_only(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "e";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_force_D_only_not_digital(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "D";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static const struct drm_connector connector_hdmi = {
+       .connector_type = DRM_MODE_CONNECTOR_HDMIB,
+};
+
+static void drm_cmdline_test_force_D_only_hdmi(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "D";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &connector_hdmi, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL);
+}
+
+static const struct drm_connector connector_dvi = {
+       .connector_type = DRM_MODE_CONNECTOR_DVII,
+};
+
+static void drm_cmdline_test_force_D_only_dvi(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "D";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &connector_dvi, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL);
+}
+
+static void drm_cmdline_test_force_d_only(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "d";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF);
+}
+
+static void drm_cmdline_test_margin_only(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "m";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_interlace_only(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "i";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_missing_x(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "x480";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_missing_y(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "1024x";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_bad_y(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "1024xtest";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_missing_y_bpp(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "1024x-24";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_vesa(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480M";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_TRUE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_vesa_rblank(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480MR";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_TRUE(test, mode.rb);
+       KUNIT_EXPECT_TRUE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_rblank(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480R";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_TRUE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bpp(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bad_bpp(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-test";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_refresh(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480@60";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bad_refresh(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480@refresh";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_bpp_refresh(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24@60";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_interlaced(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24@60i";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_TRUE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_margins(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline =  "720x480-24@60m";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_TRUE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_force_off(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline =  "720x480-24@60d";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_OFF);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_force_on_off(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline =  "720x480-24@60de";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_bpp_refresh_force_on(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline =  "720x480-24@60e";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_force_on_analog(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24@60D";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_force_on_digital(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       static const struct drm_connector connector = {
+               .connector_type = DRM_MODE_CONNECTOR_DVII,
+       };
+       const char *cmdline = "720x480-24@60D";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON_DIGITAL);
+}
+
+static void drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24@60ime";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_TRUE(test, mode.refresh_specified);
+       KUNIT_EXPECT_EQ(test, mode.refresh, 60);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_TRUE(test, mode.interlace);
+       KUNIT_EXPECT_TRUE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_res_margins_force_on(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480me";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_TRUE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_res_vesa_margins(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480Mm";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_TRUE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_TRUE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_res_invalid_mode(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480f";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_res_bpp_wrong_place_mode(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480e-24";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_name(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_STREQ(test, mode.name, "NTSC");
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+}
+
+static void drm_cmdline_test_name_bpp(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC-24";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_STREQ(test, mode.name, "NTSC");
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+}
+
+static void drm_cmdline_test_name_bpp_refresh(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC-24@60";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_name_refresh(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC@60";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_name_refresh_wrong_mode(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC@60m";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_name_refresh_invalid_mode(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC@60f";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_name_option(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC,rotate=180";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_STREQ(test, mode.name, "NTSC");
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180);
+}
+
+static void drm_cmdline_test_name_bpp_option(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "NTSC-24,rotate=180";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_STREQ(test, mode.name, "NTSC");
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180);
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+}
+
+static void drm_cmdline_test_rotate_0(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=0";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_0);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_rotate_90(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=90";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_90);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_rotate_180(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=180";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_rotate_270(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=270";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_270);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_rotate_multiple(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=0,rotate=90";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_rotate_invalid_val(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=42";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_rotate_truncated(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_hmirror(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,reflect_x";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X));
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_vmirror(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,reflect_y";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y));
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_margin_options(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline =
+               "720x480,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_multiple_options(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,rotate=270,reflect_x";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, (DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X));
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_invalid_option(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480,test=42";
+
+       KUNIT_EXPECT_FALSE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                          &no_connector, &mode));
+}
+
+static void drm_cmdline_test_bpp_extra_and_option(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480-24e,rotate=180";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+
+       KUNIT_EXPECT_TRUE(test, mode.bpp_specified);
+       KUNIT_EXPECT_EQ(test, mode.bpp, 24);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_extra_and_option(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "720x480e,rotate=180";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_TRUE(test, mode.specified);
+       KUNIT_EXPECT_EQ(test, mode.xres, 720);
+       KUNIT_EXPECT_EQ(test, mode.yres, 480);
+       KUNIT_EXPECT_EQ(test, mode.rotation_reflection, DRM_MODE_ROTATE_180);
+
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_freestanding_options(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "margin_right=14,margin_left=24,margin_bottom=36,margin_top=42";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static void drm_cmdline_test_freestanding_force_e_and_options(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "e,margin_right=14,margin_left=24,margin_bottom=36,margin_top=42";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.right, 14);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.left, 24);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.bottom, 36);
+       KUNIT_EXPECT_EQ(test, mode.tv_margins.top, 42);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_ON);
+}
+
+static void drm_cmdline_test_panel_orientation(struct kunit *test)
+{
+       struct drm_cmdline_mode mode = { };
+       const char *cmdline = "panel_orientation=upside_down";
+
+       KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(cmdline,
+                                                                         &no_connector, &mode));
+       KUNIT_EXPECT_FALSE(test, mode.specified);
+       KUNIT_EXPECT_FALSE(test, mode.refresh_specified);
+       KUNIT_EXPECT_FALSE(test, mode.bpp_specified);
+
+       KUNIT_EXPECT_EQ(test, mode.panel_orientation, DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP);
+
+       KUNIT_EXPECT_FALSE(test, mode.rb);
+       KUNIT_EXPECT_FALSE(test, mode.cvt);
+       KUNIT_EXPECT_FALSE(test, mode.interlace);
+       KUNIT_EXPECT_FALSE(test, mode.margins);
+       KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED);
+}
+
+static struct kunit_case drm_cmdline_parser_tests[] = {
+       KUNIT_CASE(drm_cmdline_test_force_d_only),
+       KUNIT_CASE(drm_cmdline_test_force_D_only_dvi),
+       KUNIT_CASE(drm_cmdline_test_force_D_only_hdmi),
+       KUNIT_CASE(drm_cmdline_test_force_D_only_not_digital),
+       KUNIT_CASE(drm_cmdline_test_force_e_only),
+       KUNIT_CASE(drm_cmdline_test_margin_only),
+       KUNIT_CASE(drm_cmdline_test_interlace_only),
+       KUNIT_CASE(drm_cmdline_test_res),
+       KUNIT_CASE(drm_cmdline_test_res_missing_x),
+       KUNIT_CASE(drm_cmdline_test_res_missing_y),
+       KUNIT_CASE(drm_cmdline_test_res_bad_y),
+       KUNIT_CASE(drm_cmdline_test_res_missing_y_bpp),
+       KUNIT_CASE(drm_cmdline_test_res_vesa),
+       KUNIT_CASE(drm_cmdline_test_res_vesa_rblank),
+       KUNIT_CASE(drm_cmdline_test_res_rblank),
+       KUNIT_CASE(drm_cmdline_test_res_bpp),
+       KUNIT_CASE(drm_cmdline_test_res_bad_bpp),
+       KUNIT_CASE(drm_cmdline_test_res_refresh),
+       KUNIT_CASE(drm_cmdline_test_res_bad_refresh),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_margins),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_off),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_off),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_analog),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_force_on_digital),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on),
+       KUNIT_CASE(drm_cmdline_test_res_margins_force_on),
+       KUNIT_CASE(drm_cmdline_test_res_vesa_margins),
+       KUNIT_CASE(drm_cmdline_test_res_invalid_mode),
+       KUNIT_CASE(drm_cmdline_test_res_bpp_wrong_place_mode),
+       KUNIT_CASE(drm_cmdline_test_name),
+       KUNIT_CASE(drm_cmdline_test_name_bpp),
+       KUNIT_CASE(drm_cmdline_test_name_refresh),
+       KUNIT_CASE(drm_cmdline_test_name_bpp_refresh),
+       KUNIT_CASE(drm_cmdline_test_name_refresh_wrong_mode),
+       KUNIT_CASE(drm_cmdline_test_name_refresh_invalid_mode),
+       KUNIT_CASE(drm_cmdline_test_name_option),
+       KUNIT_CASE(drm_cmdline_test_name_bpp_option),
+       KUNIT_CASE(drm_cmdline_test_rotate_0),
+       KUNIT_CASE(drm_cmdline_test_rotate_90),
+       KUNIT_CASE(drm_cmdline_test_rotate_180),
+       KUNIT_CASE(drm_cmdline_test_rotate_270),
+       KUNIT_CASE(drm_cmdline_test_rotate_multiple),
+       KUNIT_CASE(drm_cmdline_test_rotate_invalid_val),
+       KUNIT_CASE(drm_cmdline_test_rotate_truncated),
+       KUNIT_CASE(drm_cmdline_test_hmirror),
+       KUNIT_CASE(drm_cmdline_test_vmirror),
+       KUNIT_CASE(drm_cmdline_test_margin_options),
+       KUNIT_CASE(drm_cmdline_test_multiple_options),
+       KUNIT_CASE(drm_cmdline_test_invalid_option),
+       KUNIT_CASE(drm_cmdline_test_bpp_extra_and_option),
+       KUNIT_CASE(drm_cmdline_test_extra_and_option),
+       KUNIT_CASE(drm_cmdline_test_freestanding_options),
+       KUNIT_CASE(drm_cmdline_test_freestanding_force_e_and_options),
+       KUNIT_CASE(drm_cmdline_test_panel_orientation),
+       {}
+};
+
+static struct kunit_suite drm_cmdline_parser_test_suite = {
+       .name = "drm_cmdline_parser",
+       .test_cases = drm_cmdline_parser_tests
+};
+
+kunit_test_suite(drm_cmdline_parser_test_suite);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_damage_helper_test.c b/drivers/gpu/drm/tests/drm_damage_helper_test.c
new file mode 100644 (file)
index 0000000..bf250bd
--- /dev/null
@@ -0,0 +1,634 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test case for drm_damage_helper functions
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_drv.h>
+
+struct drm_damage_mock {
+       struct drm_driver driver;
+       struct drm_device device;
+       struct drm_object_properties obj_props;
+       struct drm_plane plane;
+       struct drm_property prop;
+       struct drm_framebuffer fb;
+       struct drm_plane_state state;
+       struct drm_plane_state old_state;
+};
+
+static int drm_damage_helper_init(struct kunit *test)
+{
+       struct drm_damage_mock *mock;
+
+       mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mock);
+
+       mock->fb.width = 2048;
+       mock->fb.height = 2048;
+
+       mock->state.crtc = ZERO_SIZE_PTR;
+       mock->state.fb = &mock->fb;
+       mock->state.visible = true;
+
+       mock->old_state.plane = &mock->plane;
+       mock->state.plane = &mock->plane;
+
+       /* just enough so that drm_plane_enable_fb_damage_clips() works */
+       mock->device.driver = &mock->driver;
+       mock->device.mode_config.prop_fb_damage_clips = &mock->prop;
+       mock->plane.dev = &mock->device;
+       mock->obj_props.count = 0;
+       mock->plane.base.properties = &mock->obj_props;
+       mock->prop.base.id = 1; /* 0 is an invalid id */
+       mock->prop.dev = &mock->device;
+
+       drm_plane_enable_fb_damage_clips(&mock->plane);
+
+       test->priv = mock;
+
+       return 0;
+}
+
+static void set_plane_src(struct drm_plane_state *state, int x1, int y1, int x2,
+                         int y2)
+{
+       state->src.x1 = x1;
+       state->src.y1 = y1;
+       state->src.x2 = x2;
+       state->src.y2 = y2;
+}
+
+static void set_damage_clip(struct drm_mode_rect *r, int x1, int y1, int x2,
+                           int y2)
+{
+       r->x1 = x1;
+       r->y1 = y1;
+       r->x2 = x2;
+       r->y2 = y2;
+}
+
+static void set_damage_blob(struct drm_property_blob *damage_blob,
+                           struct drm_mode_rect *r, u32 size)
+{
+       damage_blob->length = size;
+       damage_blob->data = r;
+}
+
+static void set_plane_damage(struct drm_plane_state *state,
+                            struct drm_property_blob *damage_blob)
+{
+       state->fb_damage_clips = damage_blob;
+}
+
+static void check_damage_clip(struct kunit *test, struct drm_rect *r,
+                             int x1, int y1, int x2, int y2)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_plane_state state = mock->state;
+
+       /*
+        * Round down x1/y1 and round up x2/y2. This is because damage is not in
+        * 16.16 fixed point so to catch all pixels.
+        */
+       int src_x1 = state.src.x1 >> 16;
+       int src_y1 = state.src.y1 >> 16;
+       int src_x2 = (state.src.x2 >> 16) + !!(state.src.x2 & 0xFFFF);
+       int src_y2 = (state.src.y2 >> 16) + !!(state.src.y2 & 0xFFFF);
+
+       if (x1 >= x2 || y1 >= y2)
+               KUNIT_FAIL(test, "Cannot have damage clip with no dimension.");
+       if (x1 < src_x1 || y1 < src_y1 || x2 > src_x2 || y2 > src_y2)
+               KUNIT_FAIL(test, "Damage cannot be outside rounded plane src.");
+       if (r->x1 != x1 || r->y1 != y1 || r->x2 != x2 || r->y2 != y2)
+               KUNIT_FAIL(test, "Damage = %d %d %d %d, want = %d %d %d %d",
+                          r->x1, r->y1, r->x2, r->y2, x1, y1, x2, y2);
+}
+
+static void igt_damage_iter_no_damage(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src same as fb size. */
+       set_plane_src(&mock->old_state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
+       set_plane_src(&mock->state, 0, 0, mock->fb.width << 16, mock->fb.height << 16);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
+       check_damage_clip(test, &clip, 0, 0, 2048, 2048);
+}
+
+static void igt_damage_iter_no_damage_fractional_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src has fractional part. */
+       set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
+                           "Should return rounded off plane src as damage.");
+       check_damage_clip(test, &clip, 3, 3, 1028, 772);
+}
+
+static void igt_damage_iter_no_damage_src_moved(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src moved since old plane state. */
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 10 << 16, 10 << 16,
+                     (10 + 1024) << 16, (10 + 768) << 16);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
+       check_damage_clip(test, &clip, 10, 10, 1034, 778);
+}
+
+static void igt_damage_iter_no_damage_fractional_src_moved(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src has fractional part and it moved since old plane state. */
+       set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return plane src as damage.");
+       check_damage_clip(test, &clip, 4, 4, 1029, 773);
+}
+
+static void igt_damage_iter_no_damage_not_visible(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       mock->state.visible = false;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
+}
+
+static void igt_damage_iter_no_damage_no_crtc(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       mock->state.crtc = NULL;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
+}
+
+static void igt_damage_iter_no_damage_no_fb(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       mock->state.fb = NULL;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
+}
+
+static void igt_damage_iter_simple_damage(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       /* Damage set to plane src */
+       set_damage_clip(&damage, 0, 0, 1024, 768);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
+       check_damage_clip(test, &clip, 0, 0, 1024, 768);
+}
+
+static void igt_damage_iter_single_damage(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       set_damage_clip(&damage, 256, 192, 768, 576);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
+       check_damage_clip(test, &clip, 256, 192, 768, 576);
+}
+
+static void igt_damage_iter_single_damage_intersect_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       /* Damage intersect with plane src. */
+       set_damage_clip(&damage, 256, 192, 1360, 768);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage clipped to src.");
+       check_damage_clip(test, &clip, 256, 192, 1024, 768);
+}
+
+static void igt_damage_iter_single_damage_outside_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       /* Damage clip outside plane src */
+       set_damage_clip(&damage, 1360, 1360, 1380, 1380);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
+}
+
+static void igt_damage_iter_single_damage_fractional_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src has fractional part. */
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_damage_clip(&damage, 10, 10, 256, 330);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
+       check_damage_clip(test, &clip, 10, 10, 256, 330);
+}
+
+static void igt_damage_iter_single_damage_intersect_fractional_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src has fractional part. */
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       /* Damage intersect with plane src. */
+       set_damage_clip(&damage, 10, 1, 1360, 330);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
+                           "Should return damage clipped to rounded off src.");
+       check_damage_clip(test, &clip, 10, 4, 1029, 330);
+}
+
+static void igt_damage_iter_single_damage_outside_fractional_src(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src has fractional part. */
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       /* Damage clip outside plane src */
+       set_damage_clip(&damage, 1360, 1360, 1380, 1380);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should have no damage.");
+}
+
+static void igt_damage_iter_single_damage_src_moved(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src moved since old plane state. */
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 10 << 16, 10 << 16,
+                     (10 + 1024) << 16, (10 + 768) << 16);
+       set_damage_clip(&damage, 20, 30, 256, 256);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
+                           "Should return plane src as damage.");
+       check_damage_clip(test, &clip, 10, 10, 1034, 778);
+}
+
+static void igt_damage_iter_single_damage_fractional_src_moved(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage;
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       /* Plane src with fractional part moved since old plane state. */
+       set_plane_src(&mock->old_state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       /* Damage intersect with plane src. */
+       set_damage_clip(&damage, 20, 30, 1360, 256);
+       set_damage_blob(&damage_blob, &damage, sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
+                           "Should return rounded off plane as damage.");
+       check_damage_clip(test, &clip, 4, 4, 1029, 773);
+}
+
+static void igt_damage_iter_damage(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage[2];
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       /* 2 damage clips. */
+       set_damage_clip(&damage[0], 20, 30, 200, 180);
+       set_damage_clip(&damage[1], 240, 200, 280, 250);
+       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip) {
+               if (num_hits == 0)
+                       check_damage_clip(test, &clip, 20, 30, 200, 180);
+               if (num_hits == 1)
+                       check_damage_clip(test, &clip, 240, 200, 280, 250);
+               num_hits++;
+       }
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
+}
+
+static void igt_damage_iter_damage_one_intersect(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage[2];
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       /* 2 damage clips, one intersect plane src. */
+       set_damage_clip(&damage[0], 20, 30, 200, 180);
+       set_damage_clip(&damage[1], 2, 2, 1360, 1360);
+       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip) {
+               if (num_hits == 0)
+                       check_damage_clip(test, &clip, 20, 30, 200, 180);
+               if (num_hits == 1)
+                       check_damage_clip(test, &clip, 4, 4, 1029, 773);
+               num_hits++;
+       }
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 2, "Should return damage when set.");
+}
+
+static void igt_damage_iter_damage_one_outside(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage[2];
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0, 0, 1024 << 16, 768 << 16);
+       set_plane_src(&mock->state, 0, 0, 1024 << 16, 768 << 16);
+       /* 2 damage clips, one outside plane src. */
+       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
+       set_damage_clip(&damage[1], 240, 200, 280, 250);
+       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1, "Should return damage when set.");
+       check_damage_clip(test, &clip, 240, 200, 280, 250);
+}
+
+static void igt_damage_iter_damage_src_moved(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage[2];
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       /* 2 damage clips, one outside plane src. */
+       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
+       set_damage_clip(&damage[1], 240, 200, 280, 250);
+       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 1,
+                           "Should return round off plane src as damage.");
+       check_damage_clip(test, &clip, 3, 3, 1028, 772);
+}
+
+static void igt_damage_iter_damage_not_visible(struct kunit *test)
+{
+       struct drm_damage_mock *mock = test->priv;
+       struct drm_atomic_helper_damage_iter iter;
+       struct drm_property_blob damage_blob;
+       struct drm_mode_rect damage[2];
+       struct drm_rect clip;
+       u32 num_hits = 0;
+
+       mock->state.visible = false;
+
+       set_plane_src(&mock->old_state, 0x40002, 0x40002,
+                     0x40002 + (1024 << 16), 0x40002 + (768 << 16));
+       set_plane_src(&mock->state, 0x3fffe, 0x3fffe,
+                     0x3fffe + (1024 << 16), 0x3fffe + (768 << 16));
+       /* 2 damage clips, one outside plane src. */
+       set_damage_clip(&damage[0], 1360, 1360, 1380, 1380);
+       set_damage_clip(&damage[1], 240, 200, 280, 250);
+       set_damage_blob(&damage_blob, &damage[0], sizeof(damage));
+       set_plane_damage(&mock->state, &damage_blob);
+       drm_atomic_helper_damage_iter_init(&iter, &mock->old_state, &mock->state);
+       drm_atomic_for_each_plane_damage(&iter, &clip)
+               num_hits++;
+
+       KUNIT_EXPECT_EQ_MSG(test, num_hits, 0, "Should not return any damage.");
+}
+
+static struct kunit_case drm_damage_helper_tests[] = {
+       KUNIT_CASE(igt_damage_iter_no_damage),
+       KUNIT_CASE(igt_damage_iter_no_damage_fractional_src),
+       KUNIT_CASE(igt_damage_iter_no_damage_src_moved),
+       KUNIT_CASE(igt_damage_iter_no_damage_fractional_src_moved),
+       KUNIT_CASE(igt_damage_iter_no_damage_not_visible),
+       KUNIT_CASE(igt_damage_iter_no_damage_no_crtc),
+       KUNIT_CASE(igt_damage_iter_no_damage_no_fb),
+       KUNIT_CASE(igt_damage_iter_simple_damage),
+       KUNIT_CASE(igt_damage_iter_single_damage),
+       KUNIT_CASE(igt_damage_iter_single_damage_intersect_src),
+       KUNIT_CASE(igt_damage_iter_single_damage_outside_src),
+       KUNIT_CASE(igt_damage_iter_single_damage_fractional_src),
+       KUNIT_CASE(igt_damage_iter_single_damage_intersect_fractional_src),
+       KUNIT_CASE(igt_damage_iter_single_damage_outside_fractional_src),
+       KUNIT_CASE(igt_damage_iter_single_damage_src_moved),
+       KUNIT_CASE(igt_damage_iter_single_damage_fractional_src_moved),
+       KUNIT_CASE(igt_damage_iter_damage),
+       KUNIT_CASE(igt_damage_iter_damage_one_intersect),
+       KUNIT_CASE(igt_damage_iter_damage_one_outside),
+       KUNIT_CASE(igt_damage_iter_damage_src_moved),
+       KUNIT_CASE(igt_damage_iter_damage_not_visible),
+       { }
+};
+
+static struct kunit_suite drm_damage_helper_test_suite = {
+       .name = "drm_damage_helper",
+       .init = drm_damage_helper_init,
+       .test_cases = drm_damage_helper_tests,
+};
+
+kunit_test_suite(drm_damage_helper_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
new file mode 100644 (file)
index 0000000..1d2fade
--- /dev/null
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for the DRM DP MST helpers
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#define PREFIX_STR "[drm_dp_mst_helper]"
+
+#include <kunit/test.h>
+
+#include <linux/random.h>
+
+#include <drm/display/drm_dp_mst_helper.h>
+#include <drm/drm_print.h>
+
+#include "../display/drm_dp_mst_topology_internal.h"
+
+static void igt_dp_mst_calc_pbn_mode(struct kunit *test)
+{
+       int pbn, i;
+       const struct {
+               int rate;
+               int bpp;
+               int expected;
+               bool dsc;
+       } test_params[] = {
+               { 154000, 30, 689, false },
+               { 234000, 30, 1047, false },
+               { 297000, 24, 1063, false },
+               { 332880, 24, 50, true },
+               { 324540, 24, 49, true },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(test_params); i++) {
+               pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
+                                          test_params[i].bpp,
+                                          test_params[i].dsc);
+               KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
+                                   "Expected PBN %d for clock %d bpp %d, got %d\n",
+                    test_params[i].expected, test_params[i].rate,
+                    test_params[i].bpp, pbn);
+       }
+}
+
+static bool
+sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
+                      const struct drm_dp_sideband_msg_req_body *out)
+{
+       const struct drm_dp_remote_i2c_read_tx *txin, *txout;
+       int i;
+
+       if (in->req_type != out->req_type)
+               return false;
+
+       switch (in->req_type) {
+       /*
+        * Compare struct members manually for request types which can't be
+        * compared simply using memcmp(). This is because said request types
+        * contain pointers to other allocated structs
+        */
+       case DP_REMOTE_I2C_READ:
+#define IN in->u.i2c_read
+#define OUT out->u.i2c_read
+               if (IN.num_bytes_read != OUT.num_bytes_read ||
+                   IN.num_transactions != OUT.num_transactions ||
+                   IN.port_number != OUT.port_number ||
+                   IN.read_i2c_device_id != OUT.read_i2c_device_id)
+                       return false;
+
+               for (i = 0; i < IN.num_transactions; i++) {
+                       txin = &IN.transactions[i];
+                       txout = &OUT.transactions[i];
+
+                       if (txin->i2c_dev_id != txout->i2c_dev_id ||
+                           txin->no_stop_bit != txout->no_stop_bit ||
+                           txin->num_bytes != txout->num_bytes ||
+                           txin->i2c_transaction_delay !=
+                           txout->i2c_transaction_delay)
+                               return false;
+
+                       if (memcmp(txin->bytes, txout->bytes,
+                                  txin->num_bytes) != 0)
+                               return false;
+               }
+               break;
+#undef IN
+#undef OUT
+
+       case DP_REMOTE_DPCD_WRITE:
+#define IN in->u.dpcd_write
+#define OUT out->u.dpcd_write
+               if (IN.dpcd_address != OUT.dpcd_address ||
+                   IN.num_bytes != OUT.num_bytes ||
+                   IN.port_number != OUT.port_number)
+                       return false;
+
+               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+       case DP_REMOTE_I2C_WRITE:
+#define IN in->u.i2c_write
+#define OUT out->u.i2c_write
+               if (IN.port_number != OUT.port_number ||
+                   IN.write_i2c_device_id != OUT.write_i2c_device_id ||
+                   IN.num_bytes != OUT.num_bytes)
+                       return false;
+
+               return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+       default:
+               return memcmp(in, out, sizeof(*in)) == 0;
+       }
+
+       return true;
+}
+
+static bool
+sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
+{
+       struct drm_dp_sideband_msg_req_body *out;
+       struct drm_printer p = drm_err_printer(PREFIX_STR);
+       struct drm_dp_sideband_msg_tx *txmsg;
+       int i, ret;
+       bool result = true;
+
+       out = kzalloc(sizeof(*out), GFP_KERNEL);
+       if (!out)
+               return false;
+
+       txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+       if (!txmsg) {
+               kfree(out);
+               return false;
+       }
+
+       drm_dp_encode_sideband_req(in, txmsg);
+       ret = drm_dp_decode_sideband_req(txmsg, out);
+       if (ret < 0) {
+               drm_printf(&p, "Failed to decode sideband request: %d\n",
+                          ret);
+               result = false;
+               goto out;
+       }
+
+       if (!sideband_msg_req_equal(in, out)) {
+               drm_printf(&p, "Encode/decode failed, expected:\n");
+               drm_dp_dump_sideband_msg_req_body(in, 1, &p);
+               drm_printf(&p, "Got:\n");
+               drm_dp_dump_sideband_msg_req_body(out, 1, &p);
+               result = false;
+               goto out;
+       }
+
+       switch (in->req_type) {
+       case DP_REMOTE_DPCD_WRITE:
+               kfree(out->u.dpcd_write.bytes);
+               break;
+       case DP_REMOTE_I2C_READ:
+               for (i = 0; i < out->u.i2c_read.num_transactions; i++)
+                       kfree(out->u.i2c_read.transactions[i].bytes);
+               break;
+       case DP_REMOTE_I2C_WRITE:
+               kfree(out->u.i2c_write.bytes);
+               break;
+       }
+
+       /* Clear everything but the req_type for the input */
+       memset(&in->u, 0, sizeof(in->u));
+
+out:
+       kfree(out);
+       kfree(txmsg);
+       return result;
+}
+
+static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test)
+{
+       struct drm_dp_sideband_msg_req_body in = { 0 };
+       u8 data[] = { 0xff, 0x0, 0xdd };
+       int i;
+
+       in.req_type = DP_ENUM_PATH_RESOURCES;
+       in.u.port_num.port_number = 5;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_POWER_UP_PHY;
+       in.u.port_num.port_number = 5;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_POWER_DOWN_PHY;
+       in.u.port_num.port_number = 5;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_ALLOCATE_PAYLOAD;
+       in.u.allocate_payload.number_sdp_streams = 3;
+       for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
+               in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.allocate_payload.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.allocate_payload.vcpi = 0x7f;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.allocate_payload.pbn = U16_MAX;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_QUERY_PAYLOAD;
+       in.u.query_payload.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.query_payload.vcpi = 0x7f;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_REMOTE_DPCD_READ;
+       in.u.dpcd_read.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.dpcd_read.dpcd_address = 0xfedcb;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.dpcd_read.num_bytes = U8_MAX;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_REMOTE_DPCD_WRITE;
+       in.u.dpcd_write.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.dpcd_write.dpcd_address = 0xfedcb;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
+       in.u.dpcd_write.bytes = data;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_REMOTE_I2C_READ;
+       in.u.i2c_read.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.i2c_read.read_i2c_device_id = 0x7f;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.i2c_read.num_transactions = 3;
+       in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
+       for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
+               in.u.i2c_read.transactions[i].bytes = data;
+               in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
+               in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
+               in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
+       }
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_REMOTE_I2C_WRITE;
+       in.u.i2c_write.port_number = 0xf;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.i2c_write.write_i2c_device_id = 0x7f;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
+       in.u.i2c_write.bytes = data;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+       in.req_type = DP_QUERY_STREAM_ENC_STATUS;
+       in.u.enc_status.stream_id = 1;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       get_random_bytes(in.u.enc_status.client_id,
+                        sizeof(in.u.enc_status.client_id));
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.enc_status.stream_event = 3;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.enc_status.valid_stream_event = 0;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.enc_status.stream_behavior = 3;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+       in.u.enc_status.valid_stream_behavior = 1;
+       KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+}
+
+static struct kunit_case drm_dp_mst_helper_tests[] = {
+       KUNIT_CASE(igt_dp_mst_calc_pbn_mode),
+       KUNIT_CASE(igt_dp_mst_sideband_msg_req_decode),
+       { }
+};
+
+static struct kunit_suite drm_dp_mst_helper_test_suite = {
+       .name = "drm_dp_mst_helper",
+       .test_cases = drm_dp_mst_helper_tests,
+};
+
+kunit_test_suite(drm_dp_mst_helper_test_suite);
+
+MODULE_LICENSE("GPL");
index 98583bf56044b9737a318e0560f4e2346deb302e..8284870717969f90eaeb275b9be6e883b53bfb86 100644 (file)
 
 #define TEST_BUF_SIZE 50
 
-struct xrgb8888_to_rgb332_case {
+struct convert_to_rgb332_result {
+       unsigned int dst_pitch;
+       const u8 expected[TEST_BUF_SIZE];
+};
+
+struct convert_to_rgb565_result {
+       unsigned int dst_pitch;
+       const u16 expected[TEST_BUF_SIZE];
+       const u16 expected_swab[TEST_BUF_SIZE];
+};
+
+struct convert_xrgb8888_case {
        const char *name;
        unsigned int pitch;
-       unsigned int dst_pitch;
        struct drm_rect clip;
        const u32 xrgb8888[TEST_BUF_SIZE];
-       const u8 expected[4 * TEST_BUF_SIZE];
+       struct convert_to_rgb332_result rgb332_result;
+       struct convert_to_rgb565_result rgb565_result;
 };
 
-static struct xrgb8888_to_rgb332_case xrgb8888_to_rgb332_cases[] = {
+static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
        {
                .name = "single_pixel_source_buffer",
                .pitch = 1 * 4,
-               .dst_pitch = 0,
                .clip = DRM_RECT_INIT(0, 0, 1, 1),
                .xrgb8888 = { 0x01FF0000 },
-               .expected = { 0xE0 },
+               .rgb332_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xE0 },
+               },
+               .rgb565_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xF800 },
+                       .expected_swab = { 0x00F8 },
+               },
        },
        {
                .name = "single_pixel_clip_rectangle",
                .pitch = 2 * 4,
-               .dst_pitch = 0,
                .clip = DRM_RECT_INIT(1, 1, 1, 1),
                .xrgb8888 = {
                        0x00000000, 0x00000000,
                        0x00000000, 0x10FF0000,
                },
-               .expected = { 0xE0 },
+               .rgb332_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xE0 },
+               },
+               .rgb565_result = {
+                       .dst_pitch = 0,
+                       .expected = { 0xF800 },
+                       .expected_swab = { 0x00F8 },
+               },
        },
        {
                /* Well known colors: White, black, red, green, blue, magenta,
@@ -52,7 +77,6 @@ static struct xrgb8888_to_rgb332_case xrgb8888_to_rgb332_cases[] = {
                 */
                .name = "well_known_colors",
                .pitch = 4 * 4,
-               .dst_pitch = 0,
                .clip = DRM_RECT_INIT(1, 1, 2, 4),
                .xrgb8888 = {
                        0x00000000, 0x00000000, 0x00000000, 0x00000000,
@@ -61,28 +85,61 @@ static struct xrgb8888_to_rgb332_case xrgb8888_to_rgb332_cases[] = {
                        0x00000000, 0x550000FF, 0x66FF00FF, 0x00000000,
                        0x00000000, 0x77FFFF00, 0x8800FFFF, 0x00000000,
                },
-               .expected = {
-                       0xFF, 0x00,
-                       0xE0, 0x1C,
-                       0x03, 0xE3,
-                       0xFC, 0x1F,
+               .rgb332_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFF, 0x00,
+                               0xE0, 0x1C,
+                               0x03, 0xE3,
+                               0xFC, 0x1F,
+                       },
+               },
+               .rgb565_result = {
+                       .dst_pitch = 0,
+                       .expected = {
+                               0xFFFF, 0x0000,
+                               0xF800, 0x07E0,
+                               0x001F, 0xF81F,
+                               0xFFE0, 0x07FF,
+                       },
+                       .expected_swab = {
+                               0xFFFF, 0x0000,
+                               0x00F8, 0xE007,
+                               0x1F00, 0x1FF8,
+                               0xE0FF, 0xFF07,
+                       },
                },
        },
        {
                /* Randomly picked colors. Full buffer within the clip area. */
                .name = "destination_pitch",
                .pitch = 3 * 4,
-               .dst_pitch = 5,
                .clip = DRM_RECT_INIT(0, 0, 3, 3),
                .xrgb8888 = {
                        0xA10E449C, 0xB1114D05, 0xC1A80303,
                        0xD16C7073, 0xA20E449C, 0xB2114D05,
                        0xC2A80303, 0xD26C7073, 0xA30E449C,
                },
-               .expected = {
-                       0x0A, 0x08, 0xA0, 0x00, 0x00,
-                       0x6D, 0x0A, 0x08, 0x00, 0x00,
-                       0xA0, 0x6D, 0x0A, 0x00, 0x00,
+               .rgb332_result = {
+                       .dst_pitch = 5,
+                       .expected = {
+                               0x0A, 0x08, 0xA0, 0x00, 0x00,
+                               0x6D, 0x0A, 0x08, 0x00, 0x00,
+                               0xA0, 0x6D, 0x0A, 0x00, 0x00,
+                       },
+               },
+               .rgb565_result = {
+                       .dst_pitch = 10,
+                       .expected = {
+                               0x0A33, 0x1260, 0xA800, 0x0000, 0x0000,
+                               0x6B8E, 0x0A33, 0x1260, 0x0000, 0x0000,
+                               0xA800, 0x6B8E, 0x0A33, 0x0000, 0x0000,
+                       },
+                       .expected_swab = {
+                               0x330A, 0x6012, 0x00A8, 0x0000, 0x0000,
+                               0x8E6B, 0x330A, 0x6012, 0x0000, 0x0000,
+                               0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000,
+                       },
                },
        },
 };
@@ -111,41 +168,96 @@ static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
        return dst_pitch * drm_rect_height(clip);
 }
 
-static void xrgb8888_to_rgb332_case_desc(struct xrgb8888_to_rgb332_case *t,
-                                        char *desc)
+static u32 *le32buf_to_cpu(struct kunit *test, const u32 *buf, size_t buf_size)
+{
+       u32 *dst = NULL;
+       int n;
+
+       dst = kunit_kzalloc(test, sizeof(*dst) * buf_size, GFP_KERNEL);
+       if (!dst)
+               return NULL;
+
+       for (n = 0; n < buf_size; n++)
+               dst[n] = le32_to_cpu((__force __le32)buf[n]);
+
+       return dst;
+}
+
+static void convert_xrgb8888_case_desc(struct convert_xrgb8888_case *t,
+                                      char *desc)
 {
        strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
 }
 
-KUNIT_ARRAY_PARAM(xrgb8888_to_rgb332, xrgb8888_to_rgb332_cases,
-                 xrgb8888_to_rgb332_case_desc);
+KUNIT_ARRAY_PARAM(convert_xrgb8888, convert_xrgb8888_cases,
+                 convert_xrgb8888_case_desc);
 
 static void xrgb8888_to_rgb332_test(struct kunit *test)
 {
-       const struct xrgb8888_to_rgb332_case *params = test->param_value;
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_rgb332_result *result = &params->rgb332_result;
+       size_t dst_size;
+       __u8 *buf = NULL;
+       __u32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
+
+       struct drm_framebuffer fb = {
+               .format = drm_format_info(DRM_FORMAT_XRGB8888),
+               .pitches = { params->pitch, 0, 0 },
+       };
+
+       dst_size = conversion_buf_size(DRM_FORMAT_RGB332, result->dst_pitch,
+                                      &params->clip);
+       KUNIT_ASSERT_GT(test, dst_size, 0);
+
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, &params->clip);
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+}
+
+static void xrgb8888_to_rgb565_test(struct kunit *test)
+{
+       const struct convert_xrgb8888_case *params = test->param_value;
+       const struct convert_to_rgb565_result *result = &params->rgb565_result;
        size_t dst_size;
-       __u8 *dst = NULL;
+       __u16 *buf = NULL;
+       __u32 *xrgb8888 = NULL;
+       struct iosys_map dst, src;
 
        struct drm_framebuffer fb = {
                .format = drm_format_info(DRM_FORMAT_XRGB8888),
                .pitches = { params->pitch, 0, 0 },
        };
 
-       dst_size = conversion_buf_size(DRM_FORMAT_RGB332, params->dst_pitch,
+       dst_size = conversion_buf_size(DRM_FORMAT_RGB565, result->dst_pitch,
                                       &params->clip);
        KUNIT_ASSERT_GT(test, dst_size, 0);
 
-       dst = kunit_kzalloc(test, dst_size, GFP_KERNEL);
-       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dst);
+       buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
+       iosys_map_set_vaddr(&dst, buf);
+
+       xrgb8888 = le32buf_to_cpu(test, params->xrgb8888, TEST_BUF_SIZE);
+       KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
+       iosys_map_set_vaddr(&src, xrgb8888);
+
+       drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false);
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
 
-       drm_fb_xrgb8888_to_rgb332(dst, params->dst_pitch, params->xrgb8888,
-                                 &fb, &params->clip);
-       KUNIT_EXPECT_EQ(test, memcmp(dst, params->expected, dst_size), 0);
+       drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
+       KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected_swab, dst_size), 0);
 }
 
 static struct kunit_case drm_format_helper_test_cases[] = {
-       KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test,
-                        xrgb8888_to_rgb332_gen_params),
+       KUNIT_CASE_PARAM(xrgb8888_to_rgb332_test, convert_xrgb8888_gen_params),
+       KUNIT_CASE_PARAM(xrgb8888_to_rgb565_test, convert_xrgb8888_gen_params),
        {}
 };
 
diff --git a/drivers/gpu/drm/tests/drm_format_test.c b/drivers/gpu/drm/tests/drm_format_test.c
new file mode 100644 (file)
index 0000000..afb4bca
--- /dev/null
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for the drm_format functions
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_fourcc.h>
+
+static void igt_check_drm_format_block_width(struct kunit *test)
+{
+       const struct drm_format_info *info = NULL;
+
+       /* Test invalid arguments */
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1));
+
+       /* Test 1 plane format */
+       info = drm_format_info(DRM_FORMAT_XRGB4444);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1));
+
+       /* Test 2 planes format */
+       info = drm_format_info(DRM_FORMAT_NV12);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 2));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1));
+
+       /* Test 3 planes format */
+       info = drm_format_info(DRM_FORMAT_YUV422);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 0));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 1));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_width(info, 2));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 3));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1));
+
+       /* Test a tiled format */
+       info = drm_format_info(DRM_FORMAT_X0L0);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_EQ(test, drm_format_info_block_width(info, 0), 2);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, 1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_width(info, -1));
+}
+
+static void igt_check_drm_format_block_height(struct kunit *test)
+{
+       const struct drm_format_info *info = NULL;
+
+       /* Test invalid arguments */
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1));
+
+       /* Test 1 plane format */
+       info = drm_format_info(DRM_FORMAT_XRGB4444);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1));
+
+       /* Test 2 planes format */
+       info = drm_format_info(DRM_FORMAT_NV12);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 2));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1));
+
+       /* Test 3 planes format */
+       info = drm_format_info(DRM_FORMAT_YUV422);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 0));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 1));
+       KUNIT_EXPECT_TRUE(test, drm_format_info_block_height(info, 2));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 3));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1));
+
+       /* Test a tiled format */
+       info = drm_format_info(DRM_FORMAT_X0L0);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_EQ(test, drm_format_info_block_height(info, 0), 2);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, 1));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_block_height(info, -1));
+}
+
+static void igt_check_drm_format_min_pitch_for_single_plane(struct kunit *test)
+{
+       const struct drm_format_info *info = NULL;
+
+       /* Test invalid arguments */
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       /* Test 1 plane 8 bits per pixel format */
+       info = drm_format_info(DRM_FORMAT_RGB332);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)),
+                       (uint64_t)(UINT_MAX - 1));
+
+       /* Test 1 plane 16 bits per pixel format */
+       info = drm_format_info(DRM_FORMAT_XRGB4444);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1280);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 2048);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 3840);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 8192);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 1342);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX * 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)),
+                       (uint64_t)(UINT_MAX - 1) * 2);
+
+       /* Test 1 plane 24 bits per pixel format */
+       info = drm_format_info(DRM_FORMAT_RGB888);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 3);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 6);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1920);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 3072);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 5760);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 12288);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2013);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX * 3);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)),
+                       (uint64_t)(UINT_MAX - 1) * 3);
+
+       /* Test 1 plane 32 bits per pixel format */
+       info = drm_format_info(DRM_FORMAT_ABGR8888);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 4);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 8);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 2560);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 4096);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 7680);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 16384);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 2684);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX * 4);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)),
+                       (uint64_t)(UINT_MAX - 1) * 4);
+}
+
+static void igt_check_drm_format_min_pitch_for_multi_planar(struct kunit *test)
+{
+       const struct drm_format_info *info = NULL;
+
+       /* Test 2 planes format */
+       info = drm_format_info(DRM_FORMAT_NV12);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 320), 640);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 512), 1024);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 960), 1920);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2048), 4096);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 336), 672);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1),
+                       (uint64_t)UINT_MAX + 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1)),
+                       (uint64_t)(UINT_MAX - 1));
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) /  2),
+                       (uint64_t)(UINT_MAX - 1));
+
+       /* Test 3 planes 8 bits per pixel format */
+       info = drm_format_info(DRM_FORMAT_YUV422);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 2, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 3, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 1), 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 1), 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 2), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 640);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 320), 320);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 320), 320);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 1024);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 512), 512);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 512), 512);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 1920);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 960), 960);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 960), 960);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 4096);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 2048), 2048);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 2048), 2048);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 671);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, 336), 336);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, 336), 336);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, UINT_MAX / 2 + 1),
+                       (uint64_t)UINT_MAX / 2 + 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, UINT_MAX / 2 + 1),
+                       (uint64_t)UINT_MAX / 2 + 1);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, (UINT_MAX - 1) / 2),
+                       (uint64_t)(UINT_MAX - 1) / 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 1, (UINT_MAX - 1) / 2),
+                       (uint64_t)(UINT_MAX - 1) / 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 2, (UINT_MAX - 1) / 2),
+                       (uint64_t)(UINT_MAX - 1) / 2);
+}
+
+static void igt_check_drm_format_min_pitch_for_tiled_format(struct kunit *test)
+{
+       const struct drm_format_info *info = NULL;
+
+       /* Test tiled format */
+       info = drm_format_info(DRM_FORMAT_X0L2);
+       KUNIT_EXPECT_TRUE(test, info);
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 0, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, -1, 0));
+       KUNIT_EXPECT_FALSE(test, drm_format_info_min_pitch(info, 1, 0));
+
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1), 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 2), 4);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 640), 1280);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1024), 2048);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 1920), 3840);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 4096), 8192);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, 671), 1342);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX),
+                       (uint64_t)UINT_MAX * 2);
+       KUNIT_EXPECT_EQ(test, drm_format_info_min_pitch(info, 0, UINT_MAX - 1),
+                       (uint64_t)(UINT_MAX - 1) * 2);
+}
+
+static struct kunit_case drm_format_tests[] = {
+       KUNIT_CASE(igt_check_drm_format_block_width),
+       KUNIT_CASE(igt_check_drm_format_block_height),
+       KUNIT_CASE(igt_check_drm_format_min_pitch_for_single_plane),
+       KUNIT_CASE(igt_check_drm_format_min_pitch_for_multi_planar),
+       KUNIT_CASE(igt_check_drm_format_min_pitch_for_tiled_format),
+       { }
+};
+
+static struct kunit_suite drm_format_test_suite = {
+       .name = "drm_format",
+       .test_cases = drm_format_tests,
+};
+
+kunit_test_suite(drm_format_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_framebuffer_test.c b/drivers/gpu/drm/tests/drm_framebuffer_test.c
new file mode 100644 (file)
index 0000000..ec7a08b
--- /dev/null
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for the drm_framebuffer functions
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_device.h>
+#include <drm/drm_mode.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_print.h>
+
+#include "../drm_crtc_internal.h"
+
+#define MIN_WIDTH 4
+#define MAX_WIDTH 4096
+#define MIN_HEIGHT 4
+#define MAX_HEIGHT 4096
+
+struct drm_framebuffer_test {
+       int buffer_created;
+       struct drm_mode_fb_cmd2 cmd;
+       const char *name;
+};
+
+static struct drm_framebuffer_test createbuffer_tests[] = {
+{ .buffer_created = 1, .name = "ABGR8888 normal sizes",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * 600, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 max sizes",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 pitch greater than min required",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH + 1, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 pitch less than min required",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH - 1, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Invalid width",
+       .cmd = { .width = MAX_WIDTH + 1, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * (MAX_WIDTH + 1), 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Invalid buffer handle",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 0, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "No pixel format",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = 0,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Width 0",
+       .cmd = { .width = 0, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Height 0",
+       .cmd = { .width = MAX_WIDTH, .height = 0, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Out of bound height * pitch combination",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX - 1, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 Large buffer offset",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 Valid buffer modifier",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { AFBC_FORMAT_MOD_YTR, 0, 0 },
+       }
+},
+{ .buffer_created = 0,
+       .name = "ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .offsets = { UINT_MAX / 2, 0, 0 },
+                .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_ABGR8888,
+                .handles = { 1, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .pitches = { 4 * MAX_WIDTH, 4 * MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "NV12 Normal sizes",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .pitches = { 600, 600, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "NV12 Max sizes",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 Invalid pitch",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .pitches = { MAX_WIDTH, MAX_WIDTH - 1, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 different  modifier per-plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0, 0 },
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
+                        DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
+                                                      DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, 0 },
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 Modifier for inexistent plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
+                              DRM_FORMAT_MOD_SAMSUNG_64_32_TILE },
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 0, .name = "NV12 Handle for inexistent plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .pitches = { MAX_WIDTH, MAX_WIDTH, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_NV12,
+                .handles = { 1, 1, 1 }, .pitches = { 600, 600, 600 },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 Normal sizes",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .pitches = { 600, 300, 300 },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 DRM_MODE_FB_MODIFIERS set without modifier",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .pitches = { 600, 300, 300 },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 Max sizes",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2),
+                                                     DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 0, .name = "YVU420 Invalid pitch",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) - 1,
+                                                     DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 Different pitches",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1,
+                                                     DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 Different buffer offsets/pitches",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .offsets = { MAX_WIDTH, MAX_WIDTH  +
+                        MAX_WIDTH * MAX_HEIGHT, MAX_WIDTH  + 2 * MAX_WIDTH * MAX_HEIGHT },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2) + 1,
+                        DIV_ROUND_UP(MAX_WIDTH, 2) + 7 },
+       }
+},
+{ .buffer_created = 0,
+       .name = "YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 0,
+       .name = "YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 },
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 0,
+       .name = "YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 1, .name = "YVU420 Valid modifier",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE,
+                        AFBC_FORMAT_MOD_SPARSE },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 0, .name = "YVU420 Different modifiers per plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_YTR,
+                              AFBC_FORMAT_MOD_SPARSE },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 0, .name = "YVU420 Modifier for inexistent plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_YVU420,
+                .handles = { 1, 1, 1 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE,
+                        AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE },
+                .pitches = { MAX_WIDTH, DIV_ROUND_UP(MAX_WIDTH, 2), DIV_ROUND_UP(MAX_WIDTH, 2) },
+       }
+},
+{ .buffer_created = 1, .name = "X0L2 Normal sizes",
+       .cmd = { .width = 600, .height = 600, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 1200, 0, 0 }
+       }
+},
+{ .buffer_created = 1, .name = "X0L2 Max sizes",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH, 0, 0 }
+       }
+},
+{ .buffer_created = 0, .name = "X0L2 Invalid pitch",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH - 1, 0, 0 }
+       }
+},
+{ .buffer_created = 1, .name = "X0L2 Pitch greater than minimum required",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
+       }
+},
+{ .buffer_created = 0, .name = "X0L2 Handle for inexistent plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 1, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
+       }
+},
+{ .buffer_created = 1,
+       .name = "X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .offsets = { 0, 0, 3 },
+                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 }
+       }
+},
+{ .buffer_created = 0, .name = "X0L2 Modifier without DRM_MODE_FB_MODIFIERS set",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 },
+       }
+},
+{ .buffer_created = 1, .name = "X0L2 Valid modifier",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT, .pixel_format = DRM_FORMAT_X0L2,
+                .handles = { 1, 0, 0 }, .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, 0, 0 }, .flags = DRM_MODE_FB_MODIFIERS,
+       }
+},
+{ .buffer_created = 0, .name = "X0L2 Modifier for inexistent plane",
+       .cmd = { .width = MAX_WIDTH, .height = MAX_HEIGHT,
+                .pixel_format = DRM_FORMAT_X0L2, .handles = { 1, 0, 0 },
+                .pitches = { 2 * MAX_WIDTH + 1, 0, 0 },
+                .modifier = { AFBC_FORMAT_MOD_SPARSE, AFBC_FORMAT_MOD_SPARSE, 0 },
+                .flags = DRM_MODE_FB_MODIFIERS,
+       }
+},
+};
+
+static struct drm_framebuffer *fb_create_mock(struct drm_device *dev,
+                                             struct drm_file *file_priv,
+                                             const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+       int *buffer_created = dev->dev_private;
+       *buffer_created = 1;
+       return ERR_PTR(-EINVAL);
+}
+
+static struct drm_mode_config_funcs mock_config_funcs = {
+       .fb_create = fb_create_mock,
+};
+
+static struct drm_device mock_drm_device = {
+       .mode_config = {
+               .min_width = MIN_WIDTH,
+               .max_width = MAX_WIDTH,
+               .min_height = MIN_HEIGHT,
+               .max_height = MAX_HEIGHT,
+               .funcs = &mock_config_funcs,
+       },
+};
+
+static int execute_drm_mode_fb_cmd2(struct drm_mode_fb_cmd2 *r)
+{
+       int buffer_created = 0;
+
+       mock_drm_device.dev_private = &buffer_created;
+       drm_internal_framebuffer_create(&mock_drm_device, r, NULL);
+       return buffer_created;
+}
+
+static void igt_check_drm_framebuffer_create(struct kunit *test)
+{
+       int i = 0;
+
+       for (i = 0; i < ARRAY_SIZE(createbuffer_tests); i++) {
+               KUNIT_EXPECT_EQ_MSG(test, createbuffer_tests[i].buffer_created,
+                                   execute_drm_mode_fb_cmd2(&createbuffer_tests[i].cmd),
+                    "Test %d: \"%s\" failed\n", i, createbuffer_tests[i].name);
+       }
+}
+
+static struct kunit_case drm_framebuffer_tests[] = {
+       KUNIT_CASE(igt_check_drm_framebuffer_create),
+       { }
+};
+
+static struct kunit_suite drm_framebuffer_test_suite = {
+       .name = "drm_framebuffer",
+       .test_cases = drm_framebuffer_tests,
+};
+
+kunit_test_suite(drm_framebuffer_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c
new file mode 100644 (file)
index 0000000..1e2c1aa
--- /dev/null
@@ -0,0 +1,2255 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for the drm_mm range manager
+ *
+ * Copyright (c) 2022 Arthur Grillo <arthur.grillo@usp.br>
+ */
+
+#include <kunit/test.h>
+
+#include <linux/prime_numbers.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/vmalloc.h>
+#include <linux/ktime.h>
+
+#include <drm/drm_mm.h>
+
+#include "../lib/drm_random.h"
+
+static unsigned int random_seed;
+static unsigned int max_iterations = 8192;
+static unsigned int max_prime = 128;
+
+enum {
+       BEST,
+       BOTTOMUP,
+       TOPDOWN,
+       EVICT,
+};
+
+static const struct insert_mode {
+       const char *name;
+       enum drm_mm_insert_mode mode;
+} insert_modes[] = {
+       [BEST] = { "best", DRM_MM_INSERT_BEST },
+       [BOTTOMUP] = { "bottom-up", DRM_MM_INSERT_LOW },
+       [TOPDOWN] = { "top-down", DRM_MM_INSERT_HIGH },
+       [EVICT] = { "evict", DRM_MM_INSERT_EVICT },
+       {}
+}, evict_modes[] = {
+       { "bottom-up", DRM_MM_INSERT_LOW },
+       { "top-down", DRM_MM_INSERT_HIGH },
+       {}
+};
+
+static bool assert_no_holes(struct kunit *test, const struct drm_mm *mm)
+{
+       struct drm_mm_node *hole;
+       u64 hole_start, __always_unused hole_end;
+       unsigned long count;
+
+       count = 0;
+       drm_mm_for_each_hole(hole, mm, hole_start, hole_end)
+               count++;
+       if (count) {
+               KUNIT_FAIL(test,
+                          "Expected to find no holes (after reserve), found %lu instead\n", count);
+               return false;
+       }
+
+       drm_mm_for_each_node(hole, mm) {
+               if (drm_mm_hole_follows(hole)) {
+                       KUNIT_FAIL(test, "Hole follows node, expected none!\n");
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static bool assert_one_hole(struct kunit *test, const struct drm_mm *mm, u64 start, u64 end)
+{
+       struct drm_mm_node *hole;
+       u64 hole_start, hole_end;
+       unsigned long count;
+       bool ok = true;
+
+       if (end <= start)
+               return true;
+
+       count = 0;
+       drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
+               if (start != hole_start || end != hole_end) {
+                       if (ok)
+                               KUNIT_FAIL(test,
+                                          "empty mm has incorrect hole, found (%llx, %llx), expect (%llx, %llx)\n",
+                                          hole_start, hole_end, start, end);
+                       ok = false;
+               }
+               count++;
+       }
+       if (count != 1) {
+               KUNIT_FAIL(test, "Expected to find one hole, found %lu instead\n", count);
+               ok = false;
+       }
+
+       return ok;
+}
+
+static bool assert_continuous(struct kunit *test, const struct drm_mm *mm, u64 size)
+{
+       struct drm_mm_node *node, *check, *found;
+       unsigned long n;
+       u64 addr;
+
+       if (!assert_no_holes(test, mm))
+               return false;
+
+       n = 0;
+       addr = 0;
+       drm_mm_for_each_node(node, mm) {
+               if (node->start != addr) {
+                       KUNIT_FAIL(test, "node[%ld] list out of order, expected %llx found %llx\n",
+                                  n, addr, node->start);
+                       return false;
+               }
+
+               if (node->size != size) {
+                       KUNIT_FAIL(test, "node[%ld].size incorrect, expected %llx, found %llx\n",
+                                  n, size, node->size);
+                       return false;
+               }
+
+               if (drm_mm_hole_follows(node)) {
+                       KUNIT_FAIL(test, "node[%ld] is followed by a hole!\n", n);
+                       return false;
+               }
+
+               found = NULL;
+               drm_mm_for_each_node_in_range(check, mm, addr, addr + size) {
+                       if (node != check) {
+                               KUNIT_FAIL(test,
+                                          "lookup return wrong node, expected start %llx, found %llx\n",
+                                          node->start, check->start);
+                               return false;
+                       }
+                       found = check;
+               }
+               if (!found) {
+                       KUNIT_FAIL(test, "lookup failed for node %llx + %llx\n", addr, size);
+                       return false;
+               }
+
+               addr += size;
+               n++;
+       }
+
+       return true;
+}
+
+static u64 misalignment(struct drm_mm_node *node, u64 alignment)
+{
+       u64 rem;
+
+       if (!alignment)
+               return 0;
+
+       div64_u64_rem(node->start, alignment, &rem);
+       return rem;
+}
+
+static bool assert_node(struct kunit *test, struct drm_mm_node *node, struct drm_mm *mm,
+                       u64 size, u64 alignment, unsigned long color)
+{
+       bool ok = true;
+
+       if (!drm_mm_node_allocated(node) || node->mm != mm) {
+               KUNIT_FAIL(test, "node not allocated\n");
+               ok = false;
+       }
+
+       if (node->size != size) {
+               KUNIT_FAIL(test, "node has wrong size, found %llu, expected %llu\n",
+                          node->size, size);
+               ok = false;
+       }
+
+       if (misalignment(node, alignment)) {
+               KUNIT_FAIL(test,
+                          "node is misaligned, start %llx rem %llu, expected alignment %llu\n",
+                          node->start, misalignment(node, alignment), alignment);
+               ok = false;
+       }
+
+       if (node->color != color) {
+               KUNIT_FAIL(test, "node has wrong color, found %lu, expected %lu\n",
+                          node->color, color);
+               ok = false;
+       }
+
+       return ok;
+}
+
+static void igt_mm_init(struct kunit *test)
+{
+       const unsigned int size = 4096;
+       struct drm_mm mm;
+       struct drm_mm_node tmp;
+
+       /* Start with some simple checks on initialising the struct drm_mm */
+       memset(&mm, 0, sizeof(mm));
+       KUNIT_ASSERT_FALSE_MSG(test, drm_mm_initialized(&mm),
+                              "zeroed mm claims to be initialized\n");
+
+       memset(&mm, 0xff, sizeof(mm));
+       drm_mm_init(&mm, 0, size);
+       if (!drm_mm_initialized(&mm)) {
+               KUNIT_FAIL(test, "mm claims not to be initialized\n");
+               goto out;
+       }
+
+       if (!drm_mm_clean(&mm)) {
+               KUNIT_FAIL(test, "mm not empty on creation\n");
+               goto out;
+       }
+
+       /* After creation, it should all be one massive hole */
+       if (!assert_one_hole(test, &mm, 0, size)) {
+               KUNIT_FAIL(test, "");
+               goto out;
+       }
+
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.start = 0;
+       tmp.size = size;
+       if (drm_mm_reserve_node(&mm, &tmp)) {
+               KUNIT_FAIL(test, "failed to reserve whole drm_mm\n");
+               goto out;
+       }
+
+       /* After filling the range entirely, there should be no holes */
+       if (!assert_no_holes(test, &mm)) {
+               KUNIT_FAIL(test, "");
+               goto out;
+       }
+
+       /* And then after emptying it again, the massive hole should be back */
+       drm_mm_remove_node(&tmp);
+       if (!assert_one_hole(test, &mm, 0, size)) {
+               KUNIT_FAIL(test, "");
+               goto out;
+       }
+
+out:
+       drm_mm_takedown(&mm);
+}
+
+static void igt_mm_debug(struct kunit *test)
+{
+       struct drm_mm mm;
+       struct drm_mm_node nodes[2];
+
+       /* Create a small drm_mm with a couple of nodes and a few holes, and
+        * check that the debug iterator doesn't explode over a trivial drm_mm.
+        */
+
+       drm_mm_init(&mm, 0, 4096);
+
+       memset(nodes, 0, sizeof(nodes));
+       nodes[0].start = 512;
+       nodes[0].size = 1024;
+       KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[0]),
+                              "failed to reserve node[0] {start=%lld, size=%lld)\n",
+                              nodes[0].start, nodes[0].size);
+
+       nodes[1].size = 1024;
+       nodes[1].start = 4096 - 512 - nodes[1].size;
+       KUNIT_ASSERT_FALSE_MSG(test, drm_mm_reserve_node(&mm, &nodes[1]),
+                              "failed to reserve node[0] {start=%lld, size=%lld)\n",
+                              nodes[0].start, nodes[0].size);
+}
+
+static struct drm_mm_node *set_node(struct drm_mm_node *node,
+                                   u64 start, u64 size)
+{
+       node->start = start;
+       node->size = size;
+       return node;
+}
+
+static bool expect_reserve_fail(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node)
+{
+       int err;
+
+       err = drm_mm_reserve_node(mm, node);
+       if (likely(err == -ENOSPC))
+               return true;
+
+       if (!err) {
+               KUNIT_FAIL(test, "impossible reserve succeeded, node %llu + %llu\n",
+                          node->start, node->size);
+               drm_mm_remove_node(node);
+       } else {
+               KUNIT_FAIL(test,
+                          "impossible reserve failed with wrong error %d [expected %d], node %llu + %llu\n",
+                      err, -ENOSPC, node->start, node->size);
+       }
+       return false;
+}
+
+static bool check_reserve_boundaries(struct kunit *test, struct drm_mm *mm,
+                                    unsigned int count,
+                                    u64 size)
+{
+       const struct boundary {
+               u64 start, size;
+               const char *name;
+       } boundaries[] = {
+#define B(st, sz) { (st), (sz), "{ " #st ", " #sz "}" }
+               B(0, 0),
+               B(-size, 0),
+               B(size, 0),
+               B(size * count, 0),
+               B(-size, size),
+               B(-size, -size),
+               B(-size, 2 * size),
+               B(0, -size),
+               B(size, -size),
+               B(count * size, size),
+               B(count * size, -size),
+               B(count * size, count * size),
+               B(count * size, -count * size),
+               B(count * size, -(count + 1) * size),
+               B((count + 1) * size, size),
+               B((count + 1) * size, -size),
+               B((count + 1) * size, -2 * size),
+#undef B
+       };
+       struct drm_mm_node tmp = {};
+       int n;
+
+       for (n = 0; n < ARRAY_SIZE(boundaries); n++) {
+               if (!expect_reserve_fail(test, mm, set_node(&tmp, boundaries[n].start,
+                                                           boundaries[n].size))) {
+                       KUNIT_FAIL(test, "boundary[%d:%s] failed, count=%u, size=%lld\n",
+                                  n, boundaries[n].name, count, size);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int __igt_reserve(struct kunit *test, unsigned int count, u64 size)
+{
+       DRM_RND_STATE(prng, random_seed);
+       struct drm_mm mm;
+       struct drm_mm_node tmp, *nodes, *node, *next;
+       unsigned int *order, n, m, o = 0;
+       int ret, err;
+
+       /* For exercising drm_mm_reserve_node(struct kunit *test, ), we want to check that
+        * reservations outside of the drm_mm range are rejected, and to
+        * overlapping and otherwise already occupied ranges. Afterwards,
+        * the tree and nodes should be intact.
+        */
+
+       DRM_MM_BUG_ON(!count);
+       DRM_MM_BUG_ON(!size);
+
+       ret = -ENOMEM;
+       order = drm_random_order(count, &prng);
+       if (!order)
+               goto err;
+
+       nodes = vzalloc(array_size(count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       ret = -EINVAL;
+       drm_mm_init(&mm, 0, count * size);
+
+       if (!check_reserve_boundaries(test, &mm, count, size))
+               goto out;
+
+       for (n = 0; n < count; n++) {
+               nodes[n].start = order[n] * size;
+               nodes[n].size = size;
+
+               err = drm_mm_reserve_node(&mm, &nodes[n]);
+               if (err) {
+                       KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n",
+                                  n, nodes[n].start);
+                       ret = err;
+                       goto out;
+               }
+
+               if (!drm_mm_node_allocated(&nodes[n])) {
+                       KUNIT_FAIL(test, "reserved node not allocated! step %d, start %llu\n",
+                                  n, nodes[n].start);
+                       goto out;
+               }
+
+               if (!expect_reserve_fail(test, &mm, &nodes[n]))
+                       goto out;
+       }
+
+       /* After random insertion the nodes should be in order */
+       if (!assert_continuous(test, &mm, size))
+               goto out;
+
+       /* Repeated use should then fail */
+       drm_random_reorder(order, count, &prng);
+       for (n = 0; n < count; n++) {
+               if (!expect_reserve_fail(test, &mm, set_node(&tmp, order[n] * size, 1)))
+                       goto out;
+
+               /* Remove and reinsert should work */
+               drm_mm_remove_node(&nodes[order[n]]);
+               err = drm_mm_reserve_node(&mm, &nodes[order[n]]);
+               if (err) {
+                       KUNIT_FAIL(test, "reserve failed, step %d, start %llu\n",
+                                  n, nodes[n].start);
+                       ret = err;
+                       goto out;
+               }
+       }
+
+       if (!assert_continuous(test, &mm, size))
+               goto out;
+
+       /* Overlapping use should then fail */
+       for (n = 0; n < count; n++) {
+               if (!expect_reserve_fail(test, &mm, set_node(&tmp, 0, size * count)))
+                       goto out;
+       }
+       for (n = 0; n < count; n++) {
+               if (!expect_reserve_fail(test, &mm, set_node(&tmp, size * n, size * (count - n))))
+                       goto out;
+       }
+
+       /* Remove several, reinsert, check full */
+       for_each_prime_number(n, min(max_prime, count)) {
+               for (m = 0; m < n; m++) {
+                       node = &nodes[order[(o + m) % count]];
+                       drm_mm_remove_node(node);
+               }
+
+               for (m = 0; m < n; m++) {
+                       node = &nodes[order[(o + m) % count]];
+                       err = drm_mm_reserve_node(&mm, node);
+                       if (err) {
+                               KUNIT_FAIL(test, "reserve failed, step %d/%d, start %llu\n",
+                                          m, n, node->start);
+                               ret = err;
+                               goto out;
+                       }
+               }
+
+               o += n;
+
+               if (!assert_continuous(test, &mm, size))
+                       goto out;
+       }
+
+       ret = 0;
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       vfree(nodes);
+       kfree(order);
+err:
+       return ret;
+}
+
+static void igt_mm_reserve(struct kunit *test)
+{
+       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
+       int n;
+
+       for_each_prime_number_from(n, 1, 54) {
+               u64 size = BIT_ULL(n);
+
+               KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size - 1));
+               KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size));
+               KUNIT_ASSERT_FALSE(test, __igt_reserve(test, count, size + 1));
+
+               cond_resched();
+       }
+}
+
+static bool expect_insert(struct kunit *test, struct drm_mm *mm,
+                         struct drm_mm_node *node, u64 size, u64 alignment, unsigned long color,
+                       const struct insert_mode *mode)
+{
+       int err;
+
+       err = drm_mm_insert_node_generic(mm, node,
+                                        size, alignment, color,
+                                        mode->mode);
+       if (err) {
+               KUNIT_FAIL(test,
+                          "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) failed with err=%d\n",
+                          size, alignment, color, mode->name, err);
+               return false;
+       }
+
+       if (!assert_node(test, node, mm, size, alignment, color)) {
+               drm_mm_remove_node(node);
+               return false;
+       }
+
+       return true;
+}
+
+static bool expect_insert_fail(struct kunit *test, struct drm_mm *mm, u64 size)
+{
+       struct drm_mm_node tmp = {};
+       int err;
+
+       err = drm_mm_insert_node(mm, &tmp, size);
+       if (likely(err == -ENOSPC))
+               return true;
+
+       if (!err) {
+               KUNIT_FAIL(test, "impossible insert succeeded, node %llu + %llu\n",
+                          tmp.start, tmp.size);
+               drm_mm_remove_node(&tmp);
+       } else {
+               KUNIT_FAIL(test,
+                          "impossible insert failed with wrong error %d [expected %d], size %llu\n",
+                          err, -ENOSPC, size);
+       }
+       return false;
+}
+
+static int __igt_insert(struct kunit *test, unsigned int count, u64 size, bool replace)
+{
+       DRM_RND_STATE(prng, random_seed);
+       const struct insert_mode *mode;
+       struct drm_mm mm;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int *order, n, m, o = 0;
+       int ret;
+
+       /* Fill a range with lots of nodes, check it doesn't fail too early */
+
+       DRM_MM_BUG_ON(!count);
+       DRM_MM_BUG_ON(!size);
+
+       ret = -ENOMEM;
+       nodes = vmalloc(array_size(count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       order = drm_random_order(count, &prng);
+       if (!order)
+               goto err_nodes;
+
+       ret = -EINVAL;
+       drm_mm_init(&mm, 0, count * size);
+
+       for (mode = insert_modes; mode->name; mode++) {
+               for (n = 0; n < count; n++) {
+                       struct drm_mm_node tmp;
+
+                       node = replace ? &tmp : &nodes[n];
+                       memset(node, 0, sizeof(*node));
+                       if (!expect_insert(test, &mm, node, size, 0, n, mode)) {
+                               KUNIT_FAIL(test, "%s insert failed, size %llu step %d\n",
+                                          mode->name, size, n);
+                               goto out;
+                       }
+
+                       if (replace) {
+                               drm_mm_replace_node(&tmp, &nodes[n]);
+                               if (drm_mm_node_allocated(&tmp)) {
+                                       KUNIT_FAIL(test,
+                                                  "replaced old-node still allocated! step %d\n",
+                                                  n);
+                                       goto out;
+                               }
+
+                               if (!assert_node(test, &nodes[n], &mm, size, 0, n)) {
+                                       KUNIT_FAIL(test,
+                                                  "replaced node did not inherit parameters, size %llu step %d\n",
+                                                  size, n);
+                                       goto out;
+                               }
+
+                               if (tmp.start != nodes[n].start) {
+                                       KUNIT_FAIL(test,
+                                                  "replaced node mismatch location expected [%llx + %llx], found [%llx + %llx]\n",
+                                                  tmp.start, size, nodes[n].start, nodes[n].size);
+                                       goto out;
+                               }
+                       }
+               }
+
+               /* After random insertion the nodes should be in order */
+               if (!assert_continuous(test, &mm, size))
+                       goto out;
+
+               /* Repeated use should then fail */
+               if (!expect_insert_fail(test, &mm, size))
+                       goto out;
+
+               /* Remove one and reinsert, as the only hole it should refill itself */
+               for (n = 0; n < count; n++) {
+                       u64 addr = nodes[n].start;
+
+                       drm_mm_remove_node(&nodes[n]);
+                       if (!expect_insert(test, &mm, &nodes[n], size, 0, n, mode)) {
+                               KUNIT_FAIL(test, "%s reinsert failed, size %llu step %d\n",
+                                          mode->name, size, n);
+                               goto out;
+                       }
+
+                       if (nodes[n].start != addr) {
+                               KUNIT_FAIL(test,
+                                          "%s reinsert node moved, step %d, expected %llx, found %llx\n",
+                                          mode->name, n, addr, nodes[n].start);
+                               goto out;
+                       }
+
+                       if (!assert_continuous(test, &mm, size))
+                               goto out;
+               }
+
+               /* Remove several, reinsert, check full */
+               for_each_prime_number(n, min(max_prime, count)) {
+                       for (m = 0; m < n; m++) {
+                               node = &nodes[order[(o + m) % count]];
+                               drm_mm_remove_node(node);
+                       }
+
+                       for (m = 0; m < n; m++) {
+                               node = &nodes[order[(o + m) % count]];
+                               if (!expect_insert(test, &mm, node, size, 0, n, mode)) {
+                                       KUNIT_FAIL(test,
+                                                  "%s multiple reinsert failed, size %llu step %d\n",
+                                                          mode->name, size, n);
+                                       goto out;
+                               }
+                       }
+
+                       o += n;
+
+                       if (!assert_continuous(test, &mm, size))
+                               goto out;
+
+                       if (!expect_insert_fail(test, &mm, size))
+                               goto out;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
+               cond_resched();
+       }
+
+       ret = 0;
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_nodes:
+       vfree(nodes);
+       return ret;
+}
+
+static void igt_mm_insert(struct kunit *test)
+{
+       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
+       unsigned int n;
+
+       for_each_prime_number_from(n, 1, 54) {
+               u64 size = BIT_ULL(n);
+
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, false));
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, false));
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, false));
+
+               cond_resched();
+       }
+}
+
+static void igt_mm_replace(struct kunit *test)
+{
+       const unsigned int count = min_t(unsigned int, BIT(10), max_iterations);
+       unsigned int n;
+
+       /* Reuse igt_insert to exercise replacement by inserting a dummy node,
+        * then replacing it with the intended node. We want to check that
+        * the tree is intact and all the information we need is carried
+        * across to the target node.
+        */
+
+       for_each_prime_number_from(n, 1, 54) {
+               u64 size = BIT_ULL(n);
+
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size - 1, true));
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size, true));
+               KUNIT_ASSERT_FALSE(test, __igt_insert(test, count, size + 1, true));
+
+               cond_resched();
+       }
+}
+
+static bool expect_insert_in_range(struct kunit *test, struct drm_mm *mm, struct drm_mm_node *node,
+                                  u64 size, u64 alignment, unsigned long color,
+                                  u64 range_start, u64 range_end, const struct insert_mode *mode)
+{
+       int err;
+
+       err = drm_mm_insert_node_in_range(mm, node,
+                                         size, alignment, color,
+                                         range_start, range_end,
+                                         mode->mode);
+       if (err) {
+               KUNIT_FAIL(test,
+                          "insert (size=%llu, alignment=%llu, color=%lu, mode=%s) nto range [%llx, %llx] failed with err=%d\n",
+                                  size, alignment, color, mode->name,
+                                  range_start, range_end, err);
+               return false;
+       }
+
+       if (!assert_node(test, node, mm, size, alignment, color)) {
+               drm_mm_remove_node(node);
+               return false;
+       }
+
+       return true;
+}
+
+static bool expect_insert_in_range_fail(struct kunit *test, struct drm_mm *mm,
+                                       u64 size, u64 range_start, u64 range_end)
+{
+       struct drm_mm_node tmp = {};
+       int err;
+
+       err = drm_mm_insert_node_in_range(mm, &tmp, size, 0, 0, range_start, range_end,
+                                         0);
+       if (likely(err == -ENOSPC))
+               return true;
+
+       if (!err) {
+               KUNIT_FAIL(test,
+                          "impossible insert succeeded, node %llx + %llu, range [%llx, %llx]\n",
+                                  tmp.start, tmp.size, range_start, range_end);
+               drm_mm_remove_node(&tmp);
+       } else {
+               KUNIT_FAIL(test,
+                          "impossible insert failed with wrong error %d [expected %d], size %llu, range [%llx, %llx]\n",
+                                  err, -ENOSPC, size, range_start, range_end);
+       }
+
+       return false;
+}
+
+static bool assert_contiguous_in_range(struct kunit *test, struct drm_mm *mm,
+                                      u64 size, u64 start, u64 end)
+{
+       struct drm_mm_node *node;
+       unsigned int n;
+
+       if (!expect_insert_in_range_fail(test, mm, size, start, end))
+               return false;
+
+       n = div64_u64(start + size - 1, size);
+       drm_mm_for_each_node(node, mm) {
+               if (node->start < start || node->start + node->size > end) {
+                       KUNIT_FAIL(test,
+                                  "node %d out of range, address [%llx + %llu], range [%llx, %llx]\n",
+                                          n, node->start, node->start + node->size, start, end);
+                       return false;
+               }
+
+               if (node->start != n * size) {
+                       KUNIT_FAIL(test, "node %d out of order, expected start %llx, found %llx\n",
+                                  n, n * size, node->start);
+                       return false;
+               }
+
+               if (node->size != size) {
+                       KUNIT_FAIL(test, "node %d has wrong size, expected size %llx, found %llx\n",
+                                  n, size, node->size);
+                       return false;
+               }
+
+               if (drm_mm_hole_follows(node) && drm_mm_hole_node_end(node) < end) {
+                       KUNIT_FAIL(test, "node %d is followed by a hole!\n", n);
+                       return false;
+               }
+
+               n++;
+       }
+
+       if (start > 0) {
+               node = __drm_mm_interval_first(mm, 0, start - 1);
+               if (drm_mm_node_allocated(node)) {
+                       KUNIT_FAIL(test, "node before start: node=%llx+%llu, start=%llx\n",
+                                  node->start, node->size, start);
+                       return false;
+               }
+       }
+
+       if (end < U64_MAX) {
+               node = __drm_mm_interval_first(mm, end, U64_MAX);
+               if (drm_mm_node_allocated(node)) {
+                       KUNIT_FAIL(test, "node after end: node=%llx+%llu, end=%llx\n",
+                                  node->start, node->size, end);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static int __igt_insert_range(struct kunit *test, unsigned int count, u64 size, u64 start, u64 end)
+{
+       const struct insert_mode *mode;
+       struct drm_mm mm;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int n, start_n, end_n;
+       int ret;
+
+       DRM_MM_BUG_ON(!count);
+       DRM_MM_BUG_ON(!size);
+       DRM_MM_BUG_ON(end <= start);
+
+       /* Very similar to __igt_insert(struct kunit *test, ), but now instead of populating the
+        * full range of the drm_mm, we try to fill a small portion of it.
+        */
+
+       ret = -ENOMEM;
+       nodes = vzalloc(array_size(count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       ret = -EINVAL;
+       drm_mm_init(&mm, 0, count * size);
+
+       start_n = div64_u64(start + size - 1, size);
+       end_n = div64_u64(end - size, size);
+
+       for (mode = insert_modes; mode->name; mode++) {
+               for (n = start_n; n <= end_n; n++) {
+                       if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n,
+                                                   start, end, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s insert failed, size %llu, step %d [%d, %d], range [%llx, %llx]\n",
+                                                  mode->name, size, n, start_n, end_n, start, end);
+                               goto out;
+                       }
+               }
+
+               if (!assert_contiguous_in_range(test, &mm, size, start, end)) {
+                       KUNIT_FAIL(test,
+                                  "%s: range [%llx, %llx] not full after initialisation, size=%llu\n",
+                                  mode->name, start, end, size);
+                       goto out;
+               }
+
+               /* Remove one and reinsert, it should refill itself */
+               for (n = start_n; n <= end_n; n++) {
+                       u64 addr = nodes[n].start;
+
+                       drm_mm_remove_node(&nodes[n]);
+                       if (!expect_insert_in_range(test, &mm, &nodes[n], size, size, n,
+                                                   start, end, mode)) {
+                               KUNIT_FAIL(test, "%s reinsert failed, step %d\n", mode->name, n);
+                               goto out;
+                       }
+
+                       if (nodes[n].start != addr) {
+                               KUNIT_FAIL(test,
+                                          "%s reinsert node moved, step %d, expected %llx, found %llx\n",
+                                          mode->name, n, addr, nodes[n].start);
+                               goto out;
+                       }
+               }
+
+               if (!assert_contiguous_in_range(test, &mm, size, start, end)) {
+                       KUNIT_FAIL(test,
+                                  "%s: range [%llx, %llx] not full after reinsertion, size=%llu\n",
+                                  mode->name, start, end, size);
+                       goto out;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
+               cond_resched();
+       }
+
+       ret = 0;
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       vfree(nodes);
+       return ret;
+}
+
+static int insert_outside_range(struct kunit *test)
+{
+       struct drm_mm mm;
+       const unsigned int start = 1024;
+       const unsigned int end = 2048;
+       const unsigned int size = end - start;
+
+       drm_mm_init(&mm, start, size);
+
+       if (!expect_insert_in_range_fail(test, &mm, 1, 0, start))
+               return -EINVAL;
+
+       if (!expect_insert_in_range_fail(test, &mm, size,
+                                        start - size / 2, start + (size + 1) / 2))
+               return -EINVAL;
+
+       if (!expect_insert_in_range_fail(test, &mm, size,
+                                        end - (size + 1) / 2, end + size / 2))
+               return -EINVAL;
+
+       if (!expect_insert_in_range_fail(test, &mm, 1, end, end + size))
+               return -EINVAL;
+
+       drm_mm_takedown(&mm);
+       return 0;
+}
+
+static void igt_mm_insert_range(struct kunit *test)
+{
+       const unsigned int count = min_t(unsigned int, BIT(13), max_iterations);
+       unsigned int n;
+
+       /* Check that requests outside the bounds of drm_mm are rejected. */
+       KUNIT_ASSERT_FALSE(test, insert_outside_range(test));
+
+       for_each_prime_number_from(n, 1, 50) {
+               const u64 size = BIT_ULL(n);
+               const u64 max = count * size;
+
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max));
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 1, max));
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max - 1));
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, 0, max / 2));
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size, max / 2, max / 2));
+               KUNIT_ASSERT_FALSE(test, __igt_insert_range(test, count, size,
+                                                           max / 4 + 1, 3 * max / 4 - 1));
+
+               cond_resched();
+       }
+}
+
+static int prepare_igt_frag(struct kunit *test, struct drm_mm *mm,
+                           struct drm_mm_node *nodes, unsigned int num_insert,
+                           const struct insert_mode *mode)
+{
+       unsigned int size = 4096;
+       unsigned int i;
+
+       for (i = 0; i < num_insert; i++) {
+               if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) {
+                       KUNIT_FAIL(test, "%s insert failed\n", mode->name);
+                       return -EINVAL;
+               }
+       }
+
+       /* introduce fragmentation by freeing every other node */
+       for (i = 0; i < num_insert; i++) {
+               if (i % 2 == 0)
+                       drm_mm_remove_node(&nodes[i]);
+       }
+
+       return 0;
+}
+
+static u64 get_insert_time(struct kunit *test, struct drm_mm *mm,
+                          unsigned int num_insert, struct drm_mm_node *nodes,
+                          const struct insert_mode *mode)
+{
+       unsigned int size = 8192;
+       ktime_t start;
+       unsigned int i;
+
+       start = ktime_get();
+       for (i = 0; i < num_insert; i++) {
+               if (!expect_insert(test, mm, &nodes[i], size, 0, i, mode) != 0) {
+                       KUNIT_FAIL(test, "%s insert failed\n", mode->name);
+                       return 0;
+               }
+       }
+
+       return ktime_to_ns(ktime_sub(ktime_get(), start));
+}
+
+static void igt_mm_frag(struct kunit *test)
+{
+       struct drm_mm mm;
+       const struct insert_mode *mode;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int insert_size = 10000;
+       unsigned int scale_factor = 4;
+
+       /* We need 4 * insert_size nodes to hold intermediate allocated
+        * drm_mm nodes.
+        * 1 times for prepare_igt_frag(struct kunit *test, )
+        * 1 times for get_insert_time(struct kunit *test, )
+        * 2 times for get_insert_time(struct kunit *test, )
+        */
+       nodes = vzalloc(array_size(insert_size * 4, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       /* For BOTTOMUP and TOPDOWN, we first fragment the
+        * address space using prepare_igt_frag(struct kunit *test, ) and then try to verify
+        * that insertions scale quadratically from 10k to 20k insertions
+        */
+       drm_mm_init(&mm, 1, U64_MAX - 2);
+       for (mode = insert_modes; mode->name; mode++) {
+               u64 insert_time1, insert_time2;
+
+               if (mode->mode != DRM_MM_INSERT_LOW &&
+                   mode->mode != DRM_MM_INSERT_HIGH)
+                       continue;
+
+               if (prepare_igt_frag(test, &mm, nodes, insert_size, mode))
+                       goto err;
+
+               insert_time1 = get_insert_time(test, &mm, insert_size,
+                                              nodes + insert_size, mode);
+               if (insert_time1 == 0)
+                       goto err;
+
+               insert_time2 = get_insert_time(test, &mm, (insert_size * 2),
+                                              nodes + insert_size * 2, mode);
+               if (insert_time2 == 0)
+                       goto err;
+
+               kunit_info(test, "%s fragmented insert of %u and %u insertions took %llu and %llu nsecs\n",
+                          mode->name, insert_size, insert_size * 2, insert_time1, insert_time2);
+
+               if (insert_time2 > (scale_factor * insert_time1)) {
+                       KUNIT_FAIL(test, "%s fragmented insert took %llu nsecs more\n",
+                                  mode->name, insert_time2 - (scale_factor * insert_time1));
+                       goto err;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+       }
+
+err:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       vfree(nodes);
+}
+
+static void igt_mm_align(struct kunit *test)
+{
+       const struct insert_mode *mode;
+       const unsigned int max_count = min(8192u, max_prime);
+       struct drm_mm mm;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int prime;
+
+       /* For each of the possible insertion modes, we pick a few
+        * arbitrary alignments and check that the inserted node
+        * meets our requirements.
+        */
+
+       nodes = vzalloc(array_size(max_count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       drm_mm_init(&mm, 1, U64_MAX - 2);
+
+       for (mode = insert_modes; mode->name; mode++) {
+               unsigned int i = 0;
+
+               for_each_prime_number_from(prime, 1, max_count) {
+                       u64 size = next_prime_number(prime);
+
+                       if (!expect_insert(test, &mm, &nodes[i], size, prime, i, mode)) {
+                               KUNIT_FAIL(test, "%s insert failed with alignment=%d",
+                                          mode->name, prime);
+                               goto out;
+                       }
+
+                       i++;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       vfree(nodes);
+}
+
+static void igt_align_pot(struct kunit *test, int max)
+{
+       struct drm_mm mm;
+       struct drm_mm_node *node, *next;
+       int bit;
+
+       /* Check that we can align to the full u64 address space */
+
+       drm_mm_init(&mm, 1, U64_MAX - 2);
+
+       for (bit = max - 1; bit; bit--) {
+               u64 align, size;
+
+               node = kzalloc(sizeof(*node), GFP_KERNEL);
+               if (!node) {
+                       KUNIT_FAIL(test, "failed to allocate node");
+                       goto out;
+               }
+
+               align = BIT_ULL(bit);
+               size = BIT_ULL(bit - 1) + 1;
+               if (!expect_insert(test, &mm, node, size, align, bit, &insert_modes[0])) {
+                       KUNIT_FAIL(test, "insert failed with alignment=%llx [%d]", align, bit);
+                       goto out;
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm) {
+               drm_mm_remove_node(node);
+               kfree(node);
+       }
+       drm_mm_takedown(&mm);
+}
+
+static void igt_mm_align32(struct kunit *test)
+{
+       igt_align_pot(test, 32);
+}
+
+static void igt_mm_align64(struct kunit *test)
+{
+       igt_align_pot(test, 64);
+}
+
+static void show_scan(struct kunit *test, const struct drm_mm_scan *scan)
+{
+       kunit_info(test, "scan: hit [%llx, %llx], size=%lld, align=%lld, color=%ld\n",
+                  scan->hit_start, scan->hit_end, scan->size, scan->alignment, scan->color);
+}
+
+static void show_holes(struct kunit *test, const struct drm_mm *mm, int count)
+{
+       u64 hole_start, hole_end;
+       struct drm_mm_node *hole;
+
+       drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
+               struct drm_mm_node *next = list_next_entry(hole, node_list);
+               const char *node1 = NULL, *node2 = NULL;
+
+               if (drm_mm_node_allocated(hole))
+                       node1 = kasprintf(GFP_KERNEL, "[%llx + %lld, color=%ld], ",
+                                         hole->start, hole->size, hole->color);
+
+               if (drm_mm_node_allocated(next))
+                       node2 = kasprintf(GFP_KERNEL, ", [%llx + %lld, color=%ld]",
+                                         next->start, next->size, next->color);
+
+               kunit_info(test, "%sHole [%llx - %llx, size %lld]%s\n", node1,
+                          hole_start, hole_end, hole_end - hole_start, node2);
+
+               kfree(node2);
+               kfree(node1);
+
+               if (!--count)
+                       break;
+       }
+}
+
+struct evict_node {
+       struct drm_mm_node node;
+       struct list_head link;
+};
+
+static bool evict_nodes(struct kunit *test, struct drm_mm_scan *scan,
+                       struct evict_node *nodes, unsigned int *order, unsigned int count,
+                       bool use_color, struct list_head *evict_list)
+{
+       struct evict_node *e, *en;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               e = &nodes[order ? order[i] : i];
+               list_add(&e->link, evict_list);
+               if (drm_mm_scan_add_block(scan, &e->node))
+                       break;
+       }
+       list_for_each_entry_safe(e, en, evict_list, link) {
+               if (!drm_mm_scan_remove_block(scan, &e->node))
+                       list_del(&e->link);
+       }
+       if (list_empty(evict_list)) {
+               KUNIT_FAIL(test,
+                          "Failed to find eviction: size=%lld [avail=%d], align=%lld (color=%lu)\n",
+                          scan->size, count, scan->alignment, scan->color);
+               return false;
+       }
+
+       list_for_each_entry(e, evict_list, link)
+               drm_mm_remove_node(&e->node);
+
+       if (use_color) {
+               struct drm_mm_node *node;
+
+               while ((node = drm_mm_scan_color_evict(scan))) {
+                       e = container_of(node, typeof(*e), node);
+                       drm_mm_remove_node(&e->node);
+                       list_add(&e->link, evict_list);
+               }
+       } else {
+               if (drm_mm_scan_color_evict(scan)) {
+                       KUNIT_FAIL(test,
+                                  "drm_mm_scan_color_evict unexpectedly reported overlapping nodes!\n");
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static bool evict_nothing(struct kunit *test, struct drm_mm *mm,
+                         unsigned int total_size, struct evict_node *nodes)
+{
+       struct drm_mm_scan scan;
+       LIST_HEAD(evict_list);
+       struct evict_node *e;
+       struct drm_mm_node *node;
+       unsigned int n;
+
+       drm_mm_scan_init(&scan, mm, 1, 0, 0, 0);
+       for (n = 0; n < total_size; n++) {
+               e = &nodes[n];
+               list_add(&e->link, &evict_list);
+               drm_mm_scan_add_block(&scan, &e->node);
+       }
+       list_for_each_entry(e, &evict_list, link)
+               drm_mm_scan_remove_block(&scan, &e->node);
+
+       for (n = 0; n < total_size; n++) {
+               e = &nodes[n];
+
+               if (!drm_mm_node_allocated(&e->node)) {
+                       KUNIT_FAIL(test, "node[%d] no longer allocated!\n", n);
+                       return false;
+               }
+
+               e->link.next = NULL;
+       }
+
+       drm_mm_for_each_node(node, mm) {
+               e = container_of(node, typeof(*e), node);
+               e->link.next = &e->link;
+       }
+
+       for (n = 0; n < total_size; n++) {
+               e = &nodes[n];
+
+               if (!e->link.next) {
+                       KUNIT_FAIL(test, "node[%d] no longer connected!\n", n);
+                       return false;
+               }
+       }
+
+       return assert_continuous(test, mm, nodes[0].node.size);
+}
+
+static bool evict_everything(struct kunit *test, struct drm_mm *mm,
+                            unsigned int total_size, struct evict_node *nodes)
+{
+       struct drm_mm_scan scan;
+       LIST_HEAD(evict_list);
+       struct evict_node *e;
+       unsigned int n;
+       int err;
+
+       drm_mm_scan_init(&scan, mm, total_size, 0, 0, 0);
+       for (n = 0; n < total_size; n++) {
+               e = &nodes[n];
+               list_add(&e->link, &evict_list);
+               if (drm_mm_scan_add_block(&scan, &e->node))
+                       break;
+       }
+
+       err = 0;
+       list_for_each_entry(e, &evict_list, link) {
+               if (!drm_mm_scan_remove_block(&scan, &e->node)) {
+                       if (!err) {
+                               KUNIT_FAIL(test, "Node %lld not marked for eviction!\n",
+                                          e->node.start);
+                               err = -EINVAL;
+                       }
+               }
+       }
+       if (err)
+               return false;
+
+       list_for_each_entry(e, &evict_list, link)
+               drm_mm_remove_node(&e->node);
+
+       if (!assert_one_hole(test, mm, 0, total_size))
+               return false;
+
+       list_for_each_entry(e, &evict_list, link) {
+               err = drm_mm_reserve_node(mm, &e->node);
+               if (err) {
+                       KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n",
+                                  e->node.start);
+                       return false;
+               }
+       }
+
+       return assert_continuous(test, mm, nodes[0].node.size);
+}
+
+static int evict_something(struct kunit *test, struct drm_mm *mm,
+                          u64 range_start, u64 range_end, struct evict_node *nodes,
+                          unsigned int *order, unsigned int count, unsigned int size,
+                          unsigned int alignment, const struct insert_mode *mode)
+{
+       struct drm_mm_scan scan;
+       LIST_HEAD(evict_list);
+       struct evict_node *e;
+       struct drm_mm_node tmp;
+       int err;
+
+       drm_mm_scan_init_with_range(&scan, mm, size, alignment, 0, range_start,
+                                   range_end, mode->mode);
+       if (!evict_nodes(test, &scan, nodes, order, count, false, &evict_list))
+               return -EINVAL;
+
+       memset(&tmp, 0, sizeof(tmp));
+       err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, 0,
+                                        DRM_MM_INSERT_EVICT);
+       if (err) {
+               KUNIT_FAIL(test, "Failed to insert into eviction hole: size=%d, align=%d\n",
+                          size, alignment);
+               show_scan(test, &scan);
+               show_holes(test, mm, 3);
+               return err;
+       }
+
+       if (tmp.start < range_start || tmp.start + tmp.size > range_end) {
+               KUNIT_FAIL(test,
+                          "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n",
+                          tmp.start, tmp.size, range_start, range_end);
+               err = -EINVAL;
+       }
+
+       if (!assert_node(test, &tmp, mm, size, alignment, 0) ||
+           drm_mm_hole_follows(&tmp)) {
+               KUNIT_FAIL(test,
+                          "Inserted did not fill the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx, hole-follows?=%d\n",
+                          tmp.size, size, alignment, misalignment(&tmp, alignment),
+                          tmp.start, drm_mm_hole_follows(&tmp));
+               err = -EINVAL;
+       }
+
+       drm_mm_remove_node(&tmp);
+       if (err)
+               return err;
+
+       list_for_each_entry(e, &evict_list, link) {
+               err = drm_mm_reserve_node(mm, &e->node);
+               if (err) {
+                       KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n",
+                                  e->node.start);
+                       return err;
+               }
+       }
+
+       if (!assert_continuous(test, mm, nodes[0].node.size)) {
+               KUNIT_FAIL(test, "range is no longer continuous\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void igt_mm_evict(struct kunit *test)
+{
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int size = 8192;
+       const struct insert_mode *mode;
+       struct drm_mm mm;
+       struct evict_node *nodes;
+       struct drm_mm_node *node, *next;
+       unsigned int *order, n;
+
+       /* Here we populate a full drm_mm and then try and insert a new node
+        * by evicting other nodes in a random order. The drm_mm_scan should
+        * pick the first matching hole it finds from the random list. We
+        * repeat that for different allocation strategies, alignments and
+        * sizes to try and stress the hole finder.
+        */
+
+       nodes = vzalloc(array_size(size, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       order = drm_random_order(size, &prng);
+       if (!order)
+               goto err_nodes;
+
+       drm_mm_init(&mm, 0, size);
+       for (n = 0; n < size; n++) {
+               if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) {
+                       KUNIT_FAIL(test, "insert failed, step %d\n", n);
+                       goto out;
+               }
+       }
+
+       /* First check that using the scanner doesn't break the mm */
+       if (!evict_nothing(test, &mm, size, nodes)) {
+               KUNIT_FAIL(test, "evict_nothing() failed\n");
+               goto out;
+       }
+       if (!evict_everything(test, &mm, size, nodes)) {
+               KUNIT_FAIL(test, "evict_everything() failed\n");
+               goto out;
+       }
+
+       for (mode = evict_modes; mode->name; mode++) {
+               for (n = 1; n <= size; n <<= 1) {
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size, n, 1,
+                                           mode)) {
+                               KUNIT_FAIL(test, "%s evict_something(size=%u) failed\n",
+                                          mode->name, n);
+                               goto out;
+                       }
+               }
+
+               for (n = 1; n < size; n <<= 1) {
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size,
+                                           size / 2, n, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_something(size=%u, alignment=%u) failed\n",
+                                          mode->name, size / 2, n);
+                               goto out;
+                       }
+               }
+
+               for_each_prime_number_from(n, 1, min(size, max_prime)) {
+                       unsigned int nsize = (size - n + 1) / 2;
+
+                       DRM_MM_BUG_ON(!nsize);
+
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, 0, U64_MAX, nodes, order, size,
+                                           nsize, n, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_something(size=%u, alignment=%u) failed\n",
+                                          mode->name, nsize, n);
+                               goto out;
+                       }
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_nodes:
+       vfree(nodes);
+}
+
+static void igt_mm_evict_range(struct kunit *test)
+{
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int size = 8192;
+       const unsigned int range_size = size / 2;
+       const unsigned int range_start = size / 4;
+       const unsigned int range_end = range_start + range_size;
+       const struct insert_mode *mode;
+       struct drm_mm mm;
+       struct evict_node *nodes;
+       struct drm_mm_node *node, *next;
+       unsigned int *order, n;
+
+       /* Like igt_evict() but now we are limiting the search to a
+        * small portion of the full drm_mm.
+        */
+
+       nodes = vzalloc(array_size(size, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       order = drm_random_order(size, &prng);
+       if (!order)
+               goto err_nodes;
+
+       drm_mm_init(&mm, 0, size);
+       for (n = 0; n < size; n++) {
+               if (drm_mm_insert_node(&mm, &nodes[n].node, 1)) {
+                       KUNIT_FAIL(test, "insert failed, step %d\n", n);
+                       goto out;
+               }
+       }
+
+       for (mode = evict_modes; mode->name; mode++) {
+               for (n = 1; n <= range_size; n <<= 1) {
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, range_start, range_end, nodes,
+                                           order, size, n, 1, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_something(size=%u) failed with range [%u, %u]\n",
+                                          mode->name, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               for (n = 1; n <= range_size; n <<= 1) {
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, range_start, range_end, nodes,
+                                           order, size, range_size / 2, n, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n",
+                                          mode->name, range_size / 2, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               for_each_prime_number_from(n, 1, min(range_size, max_prime)) {
+                       unsigned int nsize = (range_size - n + 1) / 2;
+
+                       DRM_MM_BUG_ON(!nsize);
+
+                       drm_random_reorder(order, size, &prng);
+                       if (evict_something(test, &mm, range_start, range_end, nodes,
+                                           order, size, nsize, n, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_something(size=%u, alignment=%u) failed with range [%u, %u]\n",
+                                          mode->name, nsize, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_nodes:
+       vfree(nodes);
+}
+
+static unsigned int node_index(const struct drm_mm_node *node)
+{
+       return div64_u64(node->start, node->size);
+}
+
+static void igt_mm_topdown(struct kunit *test)
+{
+       const struct insert_mode *topdown = &insert_modes[TOPDOWN];
+
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int count = 8192;
+       unsigned int size;
+       unsigned long *bitmap;
+       struct drm_mm mm;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int *order, n, m, o = 0;
+
+       /* When allocating top-down, we expect to be returned a node
+        * from a suitable hole at the top of the drm_mm. We check that
+        * the returned node does match the highest available slot.
+        */
+
+       nodes = vzalloc(array_size(count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       bitmap = bitmap_zalloc(count, GFP_KERNEL);
+       if (!bitmap)
+               goto err_nodes;
+
+       order = drm_random_order(count, &prng);
+       if (!order)
+               goto err_bitmap;
+
+       for (size = 1; size <= 64; size <<= 1) {
+               drm_mm_init(&mm, 0, size * count);
+               for (n = 0; n < count; n++) {
+                       if (!expect_insert(test, &mm, &nodes[n], size, 0, n, topdown)) {
+                               KUNIT_FAIL(test, "insert failed, size %u step %d\n", size, n);
+                               goto out;
+                       }
+
+                       if (drm_mm_hole_follows(&nodes[n])) {
+                               KUNIT_FAIL(test,
+                                          "hole after topdown insert %d, start=%llx\n, size=%u",
+                                          n, nodes[n].start, size);
+                               goto out;
+                       }
+
+                       if (!assert_one_hole(test, &mm, 0, size * (count - n - 1)))
+                               goto out;
+               }
+
+               if (!assert_continuous(test, &mm, size))
+                       goto out;
+
+               drm_random_reorder(order, count, &prng);
+               for_each_prime_number_from(n, 1, min(count, max_prime)) {
+                       for (m = 0; m < n; m++) {
+                               node = &nodes[order[(o + m) % count]];
+                               drm_mm_remove_node(node);
+                               __set_bit(node_index(node), bitmap);
+                       }
+
+                       for (m = 0; m < n; m++) {
+                               unsigned int last;
+
+                               node = &nodes[order[(o + m) % count]];
+                               if (!expect_insert(test, &mm, node, size, 0, 0, topdown)) {
+                                       KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n);
+                                       goto out;
+                               }
+
+                               if (drm_mm_hole_follows(node)) {
+                                       KUNIT_FAIL(test,
+                                                  "hole after topdown insert %d/%d, start=%llx\n",
+                                                  m, n, node->start);
+                                       goto out;
+                               }
+
+                               last = find_last_bit(bitmap, count);
+                               if (node_index(node) != last) {
+                                       KUNIT_FAIL(test,
+                                                  "node %d/%d, size %d, not inserted into upmost hole, expected %d, found %d\n",
+                                                  m, n, size, last, node_index(node));
+                                       goto out;
+                               }
+
+                               __clear_bit(last, bitmap);
+                       }
+
+                       DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count);
+
+                       o += n;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_bitmap:
+       bitmap_free(bitmap);
+err_nodes:
+       vfree(nodes);
+}
+
+static void igt_mm_bottomup(struct kunit *test)
+{
+       const struct insert_mode *bottomup = &insert_modes[BOTTOMUP];
+
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int count = 8192;
+       unsigned int size;
+       unsigned long *bitmap;
+       struct drm_mm mm;
+       struct drm_mm_node *nodes, *node, *next;
+       unsigned int *order, n, m, o = 0;
+
+       /* Like igt_topdown, but instead of searching for the last hole,
+        * we search for the first.
+        */
+
+       nodes = vzalloc(array_size(count, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       bitmap = bitmap_zalloc(count, GFP_KERNEL);
+       if (!bitmap)
+               goto err_nodes;
+
+       order = drm_random_order(count, &prng);
+       if (!order)
+               goto err_bitmap;
+
+       for (size = 1; size <= 64; size <<= 1) {
+               drm_mm_init(&mm, 0, size * count);
+               for (n = 0; n < count; n++) {
+                       if (!expect_insert(test, &mm, &nodes[n], size, 0, n, bottomup)) {
+                               KUNIT_FAIL(test,
+                                          "bottomup insert failed, size %u step %d\n", size, n);
+                               goto out;
+                       }
+
+                       if (!assert_one_hole(test, &mm, size * (n + 1), size * count))
+                               goto out;
+               }
+
+               if (!assert_continuous(test, &mm, size))
+                       goto out;
+
+               drm_random_reorder(order, count, &prng);
+               for_each_prime_number_from(n, 1, min(count, max_prime)) {
+                       for (m = 0; m < n; m++) {
+                               node = &nodes[order[(o + m) % count]];
+                               drm_mm_remove_node(node);
+                               __set_bit(node_index(node), bitmap);
+                       }
+
+                       for (m = 0; m < n; m++) {
+                               unsigned int first;
+
+                               node = &nodes[order[(o + m) % count]];
+                               if (!expect_insert(test, &mm, node, size, 0, 0, bottomup)) {
+                                       KUNIT_FAIL(test, "insert failed, step %d/%d\n", m, n);
+                                       goto out;
+                               }
+
+                               first = find_first_bit(bitmap, count);
+                               if (node_index(node) != first) {
+                                       KUNIT_FAIL(test,
+                                                  "node %d/%d not inserted into bottom hole, expected %d, found %d\n",
+                                                  m, n, first, node_index(node));
+                                       goto out;
+                               }
+                               __clear_bit(first, bitmap);
+                       }
+
+                       DRM_MM_BUG_ON(find_first_bit(bitmap, count) != count);
+
+                       o += n;
+               }
+
+               drm_mm_for_each_node_safe(node, next, &mm)
+                       drm_mm_remove_node(node);
+               DRM_MM_BUG_ON(!drm_mm_clean(&mm));
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_bitmap:
+       bitmap_free(bitmap);
+err_nodes:
+       vfree(nodes);
+}
+
+static void __igt_once(struct kunit *test, unsigned int mode)
+{
+       struct drm_mm mm;
+       struct drm_mm_node rsvd_lo, rsvd_hi, node;
+
+       drm_mm_init(&mm, 0, 7);
+
+       memset(&rsvd_lo, 0, sizeof(rsvd_lo));
+       rsvd_lo.start = 1;
+       rsvd_lo.size = 1;
+       if (drm_mm_reserve_node(&mm, &rsvd_lo)) {
+               KUNIT_FAIL(test, "Could not reserve low node\n");
+               goto err;
+       }
+
+       memset(&rsvd_hi, 0, sizeof(rsvd_hi));
+       rsvd_hi.start = 5;
+       rsvd_hi.size = 1;
+       if (drm_mm_reserve_node(&mm, &rsvd_hi)) {
+               KUNIT_FAIL(test, "Could not reserve low node\n");
+               goto err_lo;
+       }
+
+       if (!drm_mm_hole_follows(&rsvd_lo) || !drm_mm_hole_follows(&rsvd_hi)) {
+               KUNIT_FAIL(test, "Expected a hole after lo and high nodes!\n");
+               goto err_hi;
+       }
+
+       memset(&node, 0, sizeof(node));
+       if (drm_mm_insert_node_generic(&mm, &node, 2, 0, 0, mode)) {
+               KUNIT_FAIL(test, "Could not insert the node into the available hole!\n");
+               goto err_hi;
+       }
+
+       drm_mm_remove_node(&node);
+err_hi:
+       drm_mm_remove_node(&rsvd_hi);
+err_lo:
+       drm_mm_remove_node(&rsvd_lo);
+err:
+       drm_mm_takedown(&mm);
+}
+
+static void igt_mm_lowest(struct kunit *test)
+{
+       __igt_once(test, DRM_MM_INSERT_LOW);
+}
+
+static void igt_mm_highest(struct kunit *test)
+{
+       __igt_once(test, DRM_MM_INSERT_HIGH);
+}
+
+static void separate_adjacent_colors(const struct drm_mm_node *node,
+                                    unsigned long color, u64 *start, u64 *end)
+{
+       if (drm_mm_node_allocated(node) && node->color != color)
+               ++*start;
+
+       node = list_next_entry(node, node_list);
+       if (drm_mm_node_allocated(node) && node->color != color)
+               --*end;
+}
+
+static bool colors_abutt(struct kunit *test, const struct drm_mm_node *node)
+{
+       if (!drm_mm_hole_follows(node) &&
+           drm_mm_node_allocated(list_next_entry(node, node_list))) {
+               KUNIT_FAIL(test, "colors abutt; %ld [%llx + %llx] is next to %ld [%llx + %llx]!\n",
+                          node->color, node->start, node->size,
+                      list_next_entry(node, node_list)->color,
+                      list_next_entry(node, node_list)->start,
+                      list_next_entry(node, node_list)->size);
+               return true;
+       }
+
+       return false;
+}
+
+static void igt_mm_color(struct kunit *test)
+{
+       const unsigned int count = min(4096u, max_iterations);
+       const struct insert_mode *mode;
+       struct drm_mm mm;
+       struct drm_mm_node *node, *nn;
+       unsigned int n;
+
+       /* Color adjustment complicates everything. First we just check
+        * that when we insert a node we apply any color_adjustment callback.
+        * The callback we use should ensure that there is a gap between
+        * any two nodes, and so after each insertion we check that those
+        * holes are inserted and that they are preserved.
+        */
+
+       drm_mm_init(&mm, 0, U64_MAX);
+
+       for (n = 1; n <= count; n++) {
+               node = kzalloc(sizeof(*node), GFP_KERNEL);
+               if (!node)
+                       goto out;
+
+               if (!expect_insert(test, &mm, node, n, 0, n, &insert_modes[0])) {
+                       KUNIT_FAIL(test, "insert failed, step %d\n", n);
+                       kfree(node);
+                       goto out;
+               }
+       }
+
+       drm_mm_for_each_node_safe(node, nn, &mm) {
+               if (node->color != node->size) {
+                       KUNIT_FAIL(test, "invalid color stored: expected %lld, found %ld\n",
+                                  node->size, node->color);
+
+                       goto out;
+               }
+
+               drm_mm_remove_node(node);
+               kfree(node);
+       }
+
+       /* Now, let's start experimenting with applying a color callback */
+       mm.color_adjust = separate_adjacent_colors;
+       for (mode = insert_modes; mode->name; mode++) {
+               u64 last;
+
+               node = kzalloc(sizeof(*node), GFP_KERNEL);
+               if (!node)
+                       goto out;
+
+               node->size = 1 + 2 * count;
+               node->color = node->size;
+
+               if (drm_mm_reserve_node(&mm, node)) {
+                       KUNIT_FAIL(test, "initial reserve failed!\n");
+                       goto out;
+               }
+
+               last = node->start + node->size;
+
+               for (n = 1; n <= count; n++) {
+                       int rem;
+
+                       node = kzalloc(sizeof(*node), GFP_KERNEL);
+                       if (!node)
+                               goto out;
+
+                       node->start = last;
+                       node->size = n + count;
+                       node->color = node->size;
+
+                       if (drm_mm_reserve_node(&mm, node) != -ENOSPC) {
+                               KUNIT_FAIL(test, "reserve %d did not report color overlap!", n);
+                               goto out;
+                       }
+
+                       node->start += n + 1;
+                       rem = misalignment(node, n + count);
+                       node->start += n + count - rem;
+
+                       if (drm_mm_reserve_node(&mm, node)) {
+                               KUNIT_FAIL(test, "reserve %d failed", n);
+                               goto out;
+                       }
+
+                       last = node->start + node->size;
+               }
+
+               for (n = 1; n <= count; n++) {
+                       node = kzalloc(sizeof(*node), GFP_KERNEL);
+                       if (!node)
+                               goto out;
+
+                       if (!expect_insert(test, &mm, node, n, n, n, mode)) {
+                               KUNIT_FAIL(test, "%s insert failed, step %d\n", mode->name, n);
+                               kfree(node);
+                               goto out;
+                       }
+               }
+
+               drm_mm_for_each_node_safe(node, nn, &mm) {
+                       u64 rem;
+
+                       if (node->color != node->size) {
+                               KUNIT_FAIL(test,
+                                          "%s invalid color stored: expected %lld, found %ld\n",
+                                          mode->name, node->size, node->color);
+
+                               goto out;
+                       }
+
+                       if (colors_abutt(test, node))
+                               goto out;
+
+                       div64_u64_rem(node->start, node->size, &rem);
+                       if (rem) {
+                               KUNIT_FAIL(test,
+                                          "%s colored node misaligned, start=%llx expected alignment=%lld [rem=%lld]\n",
+                                          mode->name, node->start, node->size, rem);
+                               goto out;
+                       }
+
+                       drm_mm_remove_node(node);
+                       kfree(node);
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, nn, &mm) {
+               drm_mm_remove_node(node);
+               kfree(node);
+       }
+       drm_mm_takedown(&mm);
+}
+
+static int evict_color(struct kunit *test, struct drm_mm *mm, u64 range_start,
+                      u64 range_end, struct evict_node *nodes, unsigned int *order,
+               unsigned int count, unsigned int size, unsigned int alignment,
+               unsigned long color, const struct insert_mode *mode)
+{
+       struct drm_mm_scan scan;
+       LIST_HEAD(evict_list);
+       struct evict_node *e;
+       struct drm_mm_node tmp;
+       int err;
+
+       drm_mm_scan_init_with_range(&scan, mm, size, alignment, color, range_start,
+                                   range_end, mode->mode);
+       if (!evict_nodes(test, &scan, nodes, order, count, true, &evict_list))
+               return -EINVAL;
+
+       memset(&tmp, 0, sizeof(tmp));
+       err = drm_mm_insert_node_generic(mm, &tmp, size, alignment, color,
+                                        DRM_MM_INSERT_EVICT);
+       if (err) {
+               KUNIT_FAIL(test,
+                          "Failed to insert into eviction hole: size=%d, align=%d, color=%lu, err=%d\n",
+                          size, alignment, color, err);
+               show_scan(test, &scan);
+               show_holes(test, mm, 3);
+               return err;
+       }
+
+       if (tmp.start < range_start || tmp.start + tmp.size > range_end) {
+               KUNIT_FAIL(test,
+                          "Inserted [address=%llu + %llu] did not fit into the request range [%llu, %llu]\n",
+                          tmp.start, tmp.size, range_start, range_end);
+               err = -EINVAL;
+       }
+
+       if (colors_abutt(test, &tmp))
+               err = -EINVAL;
+
+       if (!assert_node(test, &tmp, mm, size, alignment, color)) {
+               KUNIT_FAIL(test,
+                          "Inserted did not fit the eviction hole: size=%lld [%d], align=%d [rem=%lld], start=%llx\n",
+                          tmp.size, size, alignment, misalignment(&tmp, alignment), tmp.start);
+               err = -EINVAL;
+       }
+
+       drm_mm_remove_node(&tmp);
+       if (err)
+               return err;
+
+       list_for_each_entry(e, &evict_list, link) {
+               err = drm_mm_reserve_node(mm, &e->node);
+               if (err) {
+                       KUNIT_FAIL(test, "Failed to reinsert node after eviction: start=%llx\n",
+                                  e->node.start);
+                       return err;
+               }
+       }
+
+       cond_resched();
+       return 0;
+}
+
+static void igt_mm_color_evict(struct kunit *test)
+{
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int total_size = min(8192u, max_iterations);
+       const struct insert_mode *mode;
+       unsigned long color = 0;
+       struct drm_mm mm;
+       struct evict_node *nodes;
+       struct drm_mm_node *node, *next;
+       unsigned int *order, n;
+
+       /* Check that the drm_mm_scan also honours color adjustment when
+        * choosing its victims to create a hole. Our color_adjust does not
+        * allow two nodes to be placed together without an intervening hole
+        * enlarging the set of victims that must be evicted.
+        */
+
+       nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       order = drm_random_order(total_size, &prng);
+       if (!order)
+               goto err_nodes;
+
+       drm_mm_init(&mm, 0, 2 * total_size - 1);
+       mm.color_adjust = separate_adjacent_colors;
+       for (n = 0; n < total_size; n++) {
+               if (!expect_insert(test, &mm, &nodes[n].node,
+                                  1, 0, color++,
+                                  &insert_modes[0])) {
+                       KUNIT_FAIL(test, "insert failed, step %d\n", n);
+                       goto out;
+               }
+       }
+
+       for (mode = evict_modes; mode->name; mode++) {
+               for (n = 1; n <= total_size; n <<= 1) {
+                       drm_random_reorder(order, total_size, &prng);
+                       if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size,
+                                       n, 1, color++, mode)) {
+                               KUNIT_FAIL(test, "%s evict_color(size=%u) failed\n", mode->name, n);
+                               goto out;
+                       }
+               }
+
+               for (n = 1; n < total_size; n <<= 1) {
+                       drm_random_reorder(order, total_size, &prng);
+                       if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size,
+                                       total_size / 2, n, color++, mode)) {
+                               KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n",
+                                          mode->name, total_size / 2, n);
+                               goto out;
+                       }
+               }
+
+               for_each_prime_number_from(n, 1, min(total_size, max_prime)) {
+                       unsigned int nsize = (total_size - n + 1) / 2;
+
+                       DRM_MM_BUG_ON(!nsize);
+
+                       drm_random_reorder(order, total_size, &prng);
+                       if (evict_color(test, &mm, 0, U64_MAX, nodes, order, total_size,
+                                       nsize, n, color++, mode)) {
+                               KUNIT_FAIL(test, "%s evict_color(size=%u, alignment=%u) failed\n",
+                                          mode->name, nsize, n);
+                               goto out;
+                       }
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_nodes:
+       vfree(nodes);
+}
+
+static void igt_mm_color_evict_range(struct kunit *test)
+{
+       DRM_RND_STATE(prng, random_seed);
+       const unsigned int total_size = 8192;
+       const unsigned int range_size = total_size / 2;
+       const unsigned int range_start = total_size / 4;
+       const unsigned int range_end = range_start + range_size;
+       const struct insert_mode *mode;
+       unsigned long color = 0;
+       struct drm_mm mm;
+       struct evict_node *nodes;
+       struct drm_mm_node *node, *next;
+       unsigned int *order, n;
+
+       /* Like igt_color_evict(), but limited to small portion of the full
+        * drm_mm range.
+        */
+
+       nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
+       KUNIT_ASSERT_TRUE(test, nodes);
+
+       order = drm_random_order(total_size, &prng);
+       if (!order)
+               goto err_nodes;
+
+       drm_mm_init(&mm, 0, 2 * total_size - 1);
+       mm.color_adjust = separate_adjacent_colors;
+       for (n = 0; n < total_size; n++) {
+               if (!expect_insert(test, &mm, &nodes[n].node,
+                                  1, 0, color++,
+                                  &insert_modes[0])) {
+                       KUNIT_FAIL(test, "insert failed, step %d\n", n);
+                       goto out;
+               }
+       }
+
+       for (mode = evict_modes; mode->name; mode++) {
+               for (n = 1; n <= range_size; n <<= 1) {
+                       drm_random_reorder(order, range_size, &prng);
+                       if (evict_color(test, &mm, range_start, range_end, nodes, order,
+                                       total_size, n, 1, color++, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_color(size=%u) failed for range [%x, %x]\n",
+                                               mode->name, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               for (n = 1; n < range_size; n <<= 1) {
+                       drm_random_reorder(order, total_size, &prng);
+                       if (evict_color(test, &mm, range_start, range_end, nodes, order,
+                                       total_size, range_size / 2, n, color++, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n",
+                                          mode->name, total_size / 2, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               for_each_prime_number_from(n, 1, min(range_size, max_prime)) {
+                       unsigned int nsize = (range_size - n + 1) / 2;
+
+                       DRM_MM_BUG_ON(!nsize);
+
+                       drm_random_reorder(order, total_size, &prng);
+                       if (evict_color(test, &mm, range_start, range_end, nodes, order,
+                                       total_size, nsize, n, color++, mode)) {
+                               KUNIT_FAIL(test,
+                                          "%s evict_color(size=%u, alignment=%u) failed for range [%x, %x]\n",
+                                          mode->name, nsize, n, range_start, range_end);
+                               goto out;
+                       }
+               }
+
+               cond_resched();
+       }
+
+out:
+       drm_mm_for_each_node_safe(node, next, &mm)
+               drm_mm_remove_node(node);
+       drm_mm_takedown(&mm);
+       kfree(order);
+err_nodes:
+       vfree(nodes);
+}
+
+static int drm_mm_init_test(struct kunit *test)
+{
+       while (!random_seed)
+               random_seed = get_random_int();
+
+       return 0;
+}
+
+module_param(random_seed, uint, 0400);
+module_param(max_iterations, uint, 0400);
+module_param(max_prime, uint, 0400);
+
+static struct kunit_case drm_mm_tests[] = {
+       KUNIT_CASE(igt_mm_init),
+       KUNIT_CASE(igt_mm_debug),
+       KUNIT_CASE(igt_mm_reserve),
+       KUNIT_CASE(igt_mm_insert),
+       KUNIT_CASE(igt_mm_replace),
+       KUNIT_CASE(igt_mm_insert_range),
+       KUNIT_CASE(igt_mm_frag),
+       KUNIT_CASE(igt_mm_align),
+       KUNIT_CASE(igt_mm_align32),
+       KUNIT_CASE(igt_mm_align64),
+       KUNIT_CASE(igt_mm_evict),
+       KUNIT_CASE(igt_mm_evict_range),
+       KUNIT_CASE(igt_mm_topdown),
+       KUNIT_CASE(igt_mm_bottomup),
+       KUNIT_CASE(igt_mm_lowest),
+       KUNIT_CASE(igt_mm_highest),
+       KUNIT_CASE(igt_mm_color),
+       KUNIT_CASE(igt_mm_color_evict),
+       KUNIT_CASE(igt_mm_color_evict_range),
+       {}
+};
+
+static struct kunit_suite drm_mm_test_suite = {
+       .name = "drm_mm",
+       .init = drm_mm_init_test,
+       .test_cases = drm_mm_tests,
+};
+
+kunit_test_suite(drm_mm_test_suite);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c
new file mode 100644 (file)
index 0000000..be6cff0
--- /dev/null
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for the drm_plane_helper functions
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modes.h>
+
+static void set_src(struct drm_plane_state *plane_state,
+                   unsigned int src_x, unsigned int src_y,
+                   unsigned int src_w, unsigned int src_h)
+{
+       plane_state->src_x = src_x;
+       plane_state->src_y = src_y;
+       plane_state->src_w = src_w;
+       plane_state->src_h = src_h;
+}
+
+static bool check_src_eq(struct drm_plane_state *plane_state,
+                        unsigned int src_x, unsigned int src_y,
+                        unsigned int src_w, unsigned int src_h)
+{
+       if (plane_state->src.x1 < 0) {
+               pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
+               drm_rect_debug_print("src: ", &plane_state->src, true);
+               return false;
+       }
+       if (plane_state->src.y1 < 0) {
+               pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
+               drm_rect_debug_print("src: ", &plane_state->src, true);
+               return false;
+       }
+
+       if (plane_state->src.x1 != src_x ||
+           plane_state->src.y1 != src_y ||
+           drm_rect_width(&plane_state->src) != src_w ||
+           drm_rect_height(&plane_state->src) != src_h) {
+               drm_rect_debug_print("src: ", &plane_state->src, true);
+               return false;
+       }
+
+       return true;
+}
+
+static void set_crtc(struct drm_plane_state *plane_state,
+                    int crtc_x, int crtc_y,
+                    unsigned int crtc_w, unsigned int crtc_h)
+{
+       plane_state->crtc_x = crtc_x;
+       plane_state->crtc_y = crtc_y;
+       plane_state->crtc_w = crtc_w;
+       plane_state->crtc_h = crtc_h;
+}
+
+static bool check_crtc_eq(struct drm_plane_state *plane_state,
+                         int crtc_x, int crtc_y,
+                         unsigned int crtc_w, unsigned int crtc_h)
+{
+       if (plane_state->dst.x1 != crtc_x ||
+           plane_state->dst.y1 != crtc_y ||
+           drm_rect_width(&plane_state->dst) != crtc_w ||
+           drm_rect_height(&plane_state->dst) != crtc_h) {
+               drm_rect_debug_print("dst: ", &plane_state->dst, false);
+
+               return false;
+       }
+
+       return true;
+}
+
+static void igt_check_plane_state(struct kunit *test)
+{
+       int ret;
+
+       static const struct drm_crtc_state crtc_state = {
+               .crtc = ZERO_SIZE_PTR,
+               .enable = true,
+               .active = true,
+               .mode = {
+                       DRM_MODE("1024x768", 0, 65000, 1024, 1048, 1184, 1344, 0, 768, 771,
+                                777, 806, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
+               },
+       };
+       static struct drm_plane plane = {
+               .dev = NULL
+       };
+       static struct drm_framebuffer fb = {
+               .width = 2048,
+               .height = 2048
+       };
+       static struct drm_plane_state plane_state = {
+               .plane = &plane,
+               .crtc = ZERO_SIZE_PTR,
+               .fb = &fb,
+               .rotation = DRM_MODE_ROTATE_0
+       };
+
+       /* Simple clipping, no scaling. */
+       set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
+       set_crtc(&plane_state, 0, 0, fb.width, fb.height);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple clipping check should pass\n");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+
+       /* Rotated clipping + reflection, no scaling. */
+       plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Rotated clipping check should pass\n");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+       plane_state.rotation = DRM_MODE_ROTATE_0;
+
+       /* Check whether positioning works correctly. */
+       set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
+       set_crtc(&plane_state, 0, 0, 1023, 767);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_TRUE_MSG(test, ret,
+                             "Should not be able to position on the crtc with can_position=false\n");
+
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 true, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple positioning should work\n");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1023, 767));
+
+       /* Simple scaling tests. */
+       set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
+       set_crtc(&plane_state, 0, 0, 1024, 768);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 0x8001,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_TRUE_MSG(test, ret, "Upscaling out of range should fail.\n");
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 0x8000,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Upscaling exactly 2x should work\n");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+
+       set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 0x1ffff, false, false);
+       KUNIT_EXPECT_TRUE_MSG(test, ret, "Downscaling out of range should fail.\n");
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 0x20000, false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed with exact scaling limit\n");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+
+       /* Testing rounding errors. */
+       set_src(&plane_state, 0, 0, 0x40001, 0x40001);
+       set_crtc(&plane_state, 1022, 766, 4, 4);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 0x10001,
+                                                 true, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2));
+
+       set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
+       set_crtc(&plane_state, -2, -2, 1028, 772);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 0x10001,
+                                                 false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x40002, 0x40002,
+                                            1024 << 16, 768 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+
+       set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
+       set_crtc(&plane_state, 1022, 766, 4, 4);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 0xffff,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 true, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       /* Should not be rounded to 0x20001, which would be upscaling. */
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2));
+
+       set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
+       set_crtc(&plane_state, -2, -2, 1028, 772);
+       ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
+                                                 0xffff,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
+       KUNIT_EXPECT_TRUE(test, plane_state.visible);
+       KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x3fffe, 0x3fffe,
+                                            1024 << 16, 768 << 16));
+       KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+}
+
+static struct kunit_case drm_plane_helper_test[] = {
+       KUNIT_CASE(igt_check_plane_state),
+       {}
+};
+
+static struct kunit_suite drm_plane_helper_test_suite = {
+       .name = "drm_plane_helper",
+       .test_cases = drm_plane_helper_test,
+};
+
+kunit_test_suite(drm_plane_helper_test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_rect_test.c b/drivers/gpu/drm/tests/drm_rect_test.c
new file mode 100644 (file)
index 0000000..c1dbefd
--- /dev/null
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Test cases for the drm_rect functions
+ *
+ * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_rect.h>
+
+static void igt_drm_rect_clip_scaled_div_by_zero(struct kunit *test)
+{
+       struct drm_rect src, dst, clip;
+       bool visible;
+
+       /*
+        * Make sure we don't divide by zero when dst
+        * width/height is zero and dst and clip do not intersect.
+        */
+       drm_rect_init(&src, 0, 0, 0, 0);
+       drm_rect_init(&dst, 0, 0, 0, 0);
+       drm_rect_init(&clip, 1, 1, 1, 1);
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
+       KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
+
+       drm_rect_init(&src, 0, 0, 0, 0);
+       drm_rect_init(&dst, 3, 3, 0, 0);
+       drm_rect_init(&clip, 1, 1, 1, 1);
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination not be visible\n");
+       KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
+}
+
+static void igt_drm_rect_clip_scaled_not_clipped(struct kunit *test)
+{
+       struct drm_rect src, dst, clip;
+       bool visible;
+
+       /* 1:1 scaling */
+       drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
+       drm_rect_init(&dst, 0, 0, 1, 1);
+       drm_rect_init(&clip, 0, 0, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
+                              src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
+                              dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 2:1 scaling */
+       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
+       drm_rect_init(&dst, 0, 0, 1, 1);
+       drm_rect_init(&clip, 0, 0, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
+                              src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
+                              dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 1:2 scaling */
+       drm_rect_init(&src, 0, 0, 1 << 16, 1 << 16);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 0, 0, 2, 2);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
+                              src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 ||
+                              dst.y1 != 0 || dst.y2 != 2, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+}
+
+static void igt_drm_rect_clip_scaled_clipped(struct kunit *test)
+{
+       struct drm_rect src, dst, clip;
+       bool visible;
+
+       /* 1:1 scaling top/left clip */
+       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 0, 0, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
+                              src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 ||
+                              dst.y1 != 0 || dst.y2 != 1, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 1:1 scaling bottom/right clip */
+       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 1, 1, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
+                              src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
+                              dst.y2 != 2, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 2:1 scaling top/left clip */
+       drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 0, 0, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 2 << 16 ||
+                              src.y1 != 0 || src.y2 != 2 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 1 || dst.y1 != 0 ||
+                              dst.y2 != 1, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 2:1 scaling bottom/right clip */
+       drm_rect_init(&src, 0, 0, 4 << 16, 4 << 16);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 1, 1, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 2 << 16 || src.x2 != 4 << 16 ||
+                              src.y1 != 2 << 16 || src.y2 != 4 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 1 || dst.x2 != 2 || dst.y1 != 1 ||
+                              dst.y2 != 2, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 1:2 scaling top/left clip */
+       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
+       drm_rect_init(&dst, 0, 0, 4, 4);
+       drm_rect_init(&clip, 0, 0, 2, 2);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 0 || src.x2 != 1 << 16 ||
+                              src.y1 != 0 || src.y2 != 1 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 0 || dst.x2 != 2 || dst.y1 != 0 ||
+                              dst.y2 != 2, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+
+       /* 1:2 scaling bottom/right clip */
+       drm_rect_init(&src, 0, 0, 2 << 16, 2 << 16);
+       drm_rect_init(&dst, 0, 0, 4, 4);
+       drm_rect_init(&clip, 2, 2, 2, 2);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, src.x1 != 1 << 16 || src.x2 != 2 << 16 ||
+                              src.y1 != 1 << 16 || src.y2 != 2 << 16, "Source badly clipped\n");
+       KUNIT_EXPECT_FALSE_MSG(test, dst.x1 != 2 || dst.x2 != 4 || dst.y1 != 2 ||
+                              dst.y2 != 4, "Destination badly clipped\n");
+       KUNIT_EXPECT_TRUE_MSG(test, visible, "Destination should be visible\n");
+       KUNIT_EXPECT_TRUE_MSG(test, drm_rect_visible(&src), "Source should be visible\n");
+}
+
+static void igt_drm_rect_clip_scaled_signed_vs_unsigned(struct kunit *test)
+{
+       struct drm_rect src, dst, clip;
+       bool visible;
+
+       /*
+        * 'clip.x2 - dst.x1 >= dst width' could result a negative
+        * src rectangle width which is no longer expected by the
+        * code as it's using unsigned types. This could lead to
+        * the clipped source rectangle appering visible when it
+        * should have been fully clipped. Make sure both rectangles
+        * end up invisible.
+        */
+       drm_rect_init(&src, 0, 0, INT_MAX, INT_MAX);
+       drm_rect_init(&dst, 0, 0, 2, 2);
+       drm_rect_init(&clip, 3, 3, 1, 1);
+
+       visible = drm_rect_clip_scaled(&src, &dst, &clip);
+
+       KUNIT_EXPECT_FALSE_MSG(test, visible, "Destination should not be visible\n");
+       KUNIT_EXPECT_FALSE_MSG(test, drm_rect_visible(&src), "Source should not be visible\n");
+}
+
+static struct kunit_case drm_rect_tests[] = {
+       KUNIT_CASE(igt_drm_rect_clip_scaled_div_by_zero),
+       KUNIT_CASE(igt_drm_rect_clip_scaled_not_clipped),
+       KUNIT_CASE(igt_drm_rect_clip_scaled_clipped),
+       KUNIT_CASE(igt_drm_rect_clip_scaled_signed_vs_unsigned),
+       { }
+};
+
+static struct kunit_suite drm_rect_test_suite = {
+       .name = "drm_rect",
+       .test_cases = drm_rect_tests,
+};
+
+kunit_test_suite(drm_rect_test_suite);
+
+MODULE_LICENSE("GPL");
index bc4fa59b6fa9a395dc659026c3caaef3c05cba88..37860080616760cf19be513840e2cfa66cd282b1 100644 (file)
@@ -3,7 +3,7 @@ config DRM_TIDSS
        depends on DRM && OF
        depends on ARM || ARM64 || COMPILE_TEST
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        help
          The TI Keystone family SoCs introduced a new generation of
          Display SubSystem. There is currently three Keystone family
index 2218da3b3ca3445d3f94f88bcfeb478d711529d6..cd3c43a6c806483f5dccea762eb9b5184db471d4 100644 (file)
@@ -8,9 +8,7 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "tidss_crtc.h"
index dd3c6a606ae22a95ff4ccd6103a9b0814bed547f..ad93acc9abd2a24a15dc0890ec16d9252b167563 100644 (file)
@@ -24,9 +24,9 @@
 
 #include <drm/drm_blend.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_panel.h>
 
 #include "tidss_crtc.h"
@@ -1954,16 +1954,16 @@ int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
 }
 
 static
-dma_addr_t dispc_plane_state_paddr(const struct drm_plane_state *state)
+dma_addr_t dispc_plane_state_dma_addr(const struct drm_plane_state *state)
 {
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        u32 x = state->src_x >> 16;
        u32 y = state->src_y >> 16;
 
-       gem = drm_fb_cma_get_gem_obj(state->fb, 0);
+       gem = drm_fb_dma_get_gem_obj(state->fb, 0);
 
-       return gem->paddr + fb->offsets[0] + x * fb->format->cpp[0] +
+       return gem->dma_addr + fb->offsets[0] + x * fb->format->cpp[0] +
                y * fb->pitches[0];
 }
 
@@ -1971,16 +1971,16 @@ static
 dma_addr_t dispc_plane_state_p_uv_addr(const struct drm_plane_state *state)
 {
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        u32 x = state->src_x >> 16;
        u32 y = state->src_y >> 16;
 
        if (WARN_ON(state->fb->format->num_planes != 2))
                return 0;
 
-       gem = drm_fb_cma_get_gem_obj(fb, 1);
+       gem = drm_fb_dma_get_gem_obj(fb, 1);
 
-       return gem->paddr + fb->offsets[1] +
+       return gem->dma_addr + fb->offsets[1] +
                (x * fb->format->cpp[1] / fb->format->hsub) +
                (y * fb->pitches[1] / fb->format->vsub);
 }
@@ -1993,17 +1993,17 @@ int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
        u32 fourcc = state->fb->format->format;
        u16 cpp = state->fb->format->cpp[0];
        u32 fb_width = state->fb->pitches[0] / cpp;
-       dma_addr_t paddr = dispc_plane_state_paddr(state);
+       dma_addr_t dma_addr = dispc_plane_state_dma_addr(state);
        struct dispc_scaling_params scale;
 
        dispc_vid_calc_scaling(dispc, state, &scale, lite);
 
        dispc_plane_set_pixel_format(dispc, hw_plane, fourcc);
 
-       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, paddr & 0xffffffff);
-       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)paddr >> 32);
-       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, paddr & 0xffffffff);
-       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)paddr >> 32);
+       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_0, dma_addr & 0xffffffff);
+       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_0, (u64)dma_addr >> 32);
+       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_1, dma_addr & 0xffffffff);
+       dispc_vid_write(dispc, hw_plane, DISPC_VID_BA_EXT_1, (u64)dma_addr >> 32);
 
        dispc_vid_write(dispc, hw_plane, DISPC_VID_PICTURE_SIZE,
                        (scale.in_w - 1) | ((scale.in_h - 1) << 16));
index 04cfff89ee516bce33abf3134050155e920c66d4..15cd9b91b7e2a46d1618645ff9acadfbee4329db 100644 (file)
@@ -15,7 +15,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_module.h>
 #include <drm/drm_probe_helper.h>
@@ -101,13 +101,13 @@ static void tidss_release(struct drm_device *ddev)
        drm_kms_helper_poll_fini(ddev);
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(tidss_fops);
+DEFINE_DRM_GEM_DMA_FOPS(tidss_fops);
 
 static const struct drm_driver tidss_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &tidss_fops,
        .release                = tidss_release,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .name                   = "tidss",
        .desc                   = "TI Keystone DSS",
        .date                   = "20180215",
index 666e527a0acf10c1e2589bcb6beb5f2421d394d3..b61db8f279e94bafa17a4c87f484980f7585be7b 100644 (file)
@@ -10,7 +10,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_of.h>
index 68a85a94ffcbf544c71a40b2e544739efdb437e0..42d50ec5526d72830fe328ba9a3a0c5145fcf514 100644 (file)
@@ -11,7 +11,6 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
 
 #include "tidss_crtc.h"
index e315591eb36b80c41e3041f8d6af566f643e0910..d3bd2d7a181e35b114ea9a056093013da0c47b4e 100644 (file)
@@ -3,7 +3,7 @@ config DRM_TILCDC
        tristate "DRM Support for TI LCDC Display Controller"
        depends on DRM && OF && ARM
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
        select VIDEOMODE_HELPERS
index 509fbae8c9a621d648c7877544ec0a5da80f3887..b5f60b2b2d0e72ae8ec0f3f4e5e85bc5004e6e5b 100644 (file)
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_modeset_helper_vtables.h>
 #include <drm/drm_print.h>
 #include <drm/drm_vblank.h>
@@ -64,13 +64,13 @@ static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
 {
        struct drm_device *dev = crtc->dev;
        struct tilcdc_drm_private *priv = dev->dev_private;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        dma_addr_t start, end;
        u64 dma_base_and_ceiling;
 
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
 
-       start = gem->paddr + fb->offsets[0] +
+       start = gem->dma_addr + fb->offsets[0] +
                crtc->y * fb->pitches[0] +
                crtc->x * fb->format->cpp[0];
 
index eee3c447fbac28ad7793e270a762a3214eb7ca8c..f72755b8ea14c9d3cead4c65b16bf7d5646ad8f7 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_probe_helper.h>
@@ -476,11 +476,11 @@ static void tilcdc_debugfs_init(struct drm_minor *minor)
 }
 #endif
 
-DEFINE_DRM_GEM_CMA_FOPS(fops);
+DEFINE_DRM_GEM_DMA_FOPS(fops);
 
 static const struct drm_driver tilcdc_driver = {
        .driver_features    = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init       = tilcdc_debugfs_init,
 #endif
index 96013651881405b0a90a8c30bdde582a283b17d4..0ccf791301cbdade6bf349cf0b9cfb5e79ff5504 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <drm/drm_atomic.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
index 027cd87c3d0d7acf057484749e7275114ea5421d..565957264875b9cb08e179f739ccd24e82bfeeae 100644 (file)
@@ -3,7 +3,7 @@
 config DRM_ARCPGU
        tristate "ARC PGU"
        depends on DRM && OF
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        help
          Choose this option if you have an ARC PGU controller.
@@ -55,7 +55,7 @@ config DRM_PANEL_MIPI_DBI
        tristate "DRM support for MIPI DBI compatible panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        select VIDEOMODE_HELPERS
@@ -87,7 +87,7 @@ config TINYDRM_HX8357D
        tristate "DRM support for HX8357D display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -100,7 +100,7 @@ config TINYDRM_ILI9163
        tristate "DRM support for ILI9163 display panels"
        depends on DRM && SPI
        select BACKLIGHT_CLASS_DEVICE
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select DRM_MIPI_DBI
        help
@@ -113,7 +113,7 @@ config TINYDRM_ILI9225
        tristate "DRM support for ILI9225 display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        help
          DRM driver for the following Ilitek ILI9225 panels:
@@ -125,7 +125,7 @@ config TINYDRM_ILI9341
        tristate "DRM support for ILI9341 display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -138,7 +138,7 @@ config TINYDRM_ILI9486
        tristate "DRM support for ILI9486 display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -152,7 +152,7 @@ config TINYDRM_MI0283QT
        tristate "DRM support for MI0283QT"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -163,7 +163,7 @@ config TINYDRM_REPAPER
        tristate "DRM support for Pervasive Displays RePaper panels (V231)"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        help
          DRM driver for the following Pervasive Displays panels:
          1.44" TFT EPD Panel (E1144CS021)
@@ -177,7 +177,7 @@ config TINYDRM_ST7586
        tristate "DRM support for Sitronix ST7586 display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        help
          DRM driver for the following Sitronix ST7586 panels:
@@ -189,7 +189,7 @@ config TINYDRM_ST7735R
        tristate "DRM support for Sitronix ST7715R/ST7735R display panels"
        depends on DRM && SPI
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_MIPI_DBI
        select BACKLIGHT_CLASS_DEVICE
        help
index 7461cb4014071cd04b151733ae1fe141d930040d..bb302a3fd6b5f87403c38de830960e5625c1c7be 100644 (file)
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_of.h>
@@ -220,14 +220,14 @@ static void arc_pgu_update(struct drm_simple_display_pipe *pipe,
                           struct drm_plane_state *state)
 {
        struct arcpgu_drm_private *arcpgu;
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
 
        if (!pipe->plane.state->fb)
                return;
 
        arcpgu = pipe_to_arcpgu_priv(pipe);
-       gem = drm_fb_cma_get_gem_obj(pipe->plane.state->fb, 0);
-       arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr);
+       gem = drm_fb_dma_get_gem_obj(pipe->plane.state->fb, 0);
+       arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->dma_addr);
 }
 
 static const struct drm_simple_display_pipe_funcs arc_pgu_pipe_funcs = {
@@ -243,7 +243,7 @@ static const struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(arcpgu_drm_ops);
+DEFINE_DRM_GEM_DMA_FOPS(arcpgu_drm_ops);
 
 static int arcpgu_load(struct arcpgu_drm_private *arcpgu)
 {
@@ -370,7 +370,7 @@ static const struct drm_driver arcpgu_drm_driver = {
        .minor = 0,
        .patchlevel = 0,
        .fops = &arcpgu_drm_ops,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 #ifdef CONFIG_DEBUG_FS
        .debugfs_init = arcpgu_debugfs_init,
 #endif
index 82364a0a7b180dd2bcb5998cbacd4283e013d38c..08de137748624658685ffe92e05537d0523af6c8 100644 (file)
@@ -583,13 +583,17 @@ static int bochs_load(struct drm_device *dev)
 
        ret = drmm_vram_helper_init(dev, bochs->fb_base, bochs->fb_size);
        if (ret)
-               return ret;
+               goto err_hw_fini;
 
        ret = bochs_kms_init(bochs);
        if (ret)
-               return ret;
+               goto err_hw_fini;
 
        return 0;
+
+err_hw_fini:
+       bochs_hw_fini(dev);
+       return ret;
 }
 
 DEFINE_DRM_GEM_FOPS(bochs_fops);
@@ -664,11 +668,13 @@ static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent
 
        ret = drm_dev_register(dev, 0);
        if (ret)
-               goto err_free_dev;
+               goto err_hw_fini;
 
        drm_fbdev_generic_setup(dev, 32);
        return ret;
 
+err_hw_fini:
+       bochs_hw_fini(dev);
 err_free_dev:
        drm_dev_put(dev);
        return ret;
index c4f5beea1f90a4a607ba8d4974c0a254df184e9b..354d5e854a6f0979cc9ebc5a208eeb9ef0d211cd 100644 (file)
@@ -316,28 +316,29 @@ static int cirrus_mode_set(struct cirrus_device *cirrus,
 }
 
 static int cirrus_fb_blit_rect(struct drm_framebuffer *fb,
-                              const struct iosys_map *map,
+                              const struct iosys_map *vmap,
                               struct drm_rect *rect)
 {
        struct cirrus_device *cirrus = to_cirrus(fb->dev);
-       void __iomem *dst = cirrus->vram;
-       void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
+       struct iosys_map dst;
        int idx;
 
        if (!drm_dev_enter(&cirrus->dev, &idx))
                return -ENODEV;
 
+       iosys_map_set_vaddr_iomem(&dst, cirrus->vram);
+
        if (cirrus->cpp == fb->format->cpp[0]) {
-               dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect);
-               drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect);
+               iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, rect));
+               drm_fb_memcpy(&dst, fb->pitches, vmap, fb, rect);
 
        } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 2) {
-               dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
-               drm_fb_xrgb8888_to_rgb565_toio(dst, cirrus->pitch, vmap, fb, rect, false);
+               iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect));
+               drm_fb_xrgb8888_to_rgb565(&dst, &cirrus->pitch, vmap, fb, rect, false);
 
        } else if (fb->format->cpp[0] == 4 && cirrus->cpp == 3) {
-               dst += drm_fb_clip_offset(cirrus->pitch, fb->format, rect);
-               drm_fb_xrgb8888_to_rgb888_toio(dst, cirrus->pitch, vmap, fb, rect);
+               iosys_map_incr(&dst, drm_fb_clip_offset(cirrus->pitch, fb->format, rect));
+               drm_fb_xrgb8888_to_rgb888(&dst, &cirrus->pitch, vmap, fb, rect);
 
        } else {
                WARN_ON_ONCE("cpp mismatch");
index ebb025543f8de65c40e1f9b118de2116dc4af6d8..57f229a785bf8abba4ec6eb277d6bfbc83c78856 100644 (file)
@@ -20,7 +20,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modeset_helper.h>
@@ -190,12 +190,12 @@ static const struct drm_display_mode yx350hv15_mode = {
        DRM_SIMPLE_MODE(320, 480, 60, 75),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops);
+DEFINE_DRM_GEM_DMA_FOPS(hx8357d_fops);
 
 static const struct drm_driver hx8357d_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &hx8357d_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "hx8357d",
        .desc                   = "HX8357D",
index fc8ed245b0bc989dc1a0b21e7d5a87862ada2b1f..86439e50e304f7ffde79a9763cdd2db8ee3e1b04 100644 (file)
@@ -11,7 +11,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modeset_helper.h>
 
@@ -110,12 +110,12 @@ static const struct drm_display_mode yx240qv29_mode = {
        DRM_SIMPLE_MODE(128, 160, 28, 35),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9163_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ili9163_fops);
 
 static struct drm_driver ili9163_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &ili9163_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "ili9163",
        .desc                   = "Ilitek ILI9163",
index 8d686eecd5f499ed49a44ed44ba8de8ba06a45be..a79da2b4af647159f5db4a2fdfcb415235a2a1c4 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_rect.h>
@@ -78,7 +78,7 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data)
 
 static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
 {
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
        struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev);
        unsigned int height = rect->y2 - rect->y1;
        unsigned int width = rect->x2 - rect->x1;
@@ -104,7 +104,7 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
                if (ret)
                        goto err_msg;
        } else {
-               tr = cma_obj->vaddr;
+               tr = dma_obj->vaddr;
        }
 
        switch (dbidev->rotation) {
@@ -335,12 +335,12 @@ static const struct drm_display_mode ili9225_mode = {
        DRM_SIMPLE_MODE(176, 220, 35, 44),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ili9225_fops);
 
 static const struct drm_driver ili9225_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &ili9225_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .name                   = "ili9225",
        .desc                   = "Ilitek ILI9225",
        .date                   = "20171106",
index 5b8cc770ee7b92519718041ba2441928b2f7417e..b8826a0b086bfee98f19fbd73b94540b44de5b31 100644 (file)
@@ -19,7 +19,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modeset_helper.h>
@@ -146,12 +146,12 @@ static const struct drm_display_mode yx240qv29_mode = {
        DRM_SIMPLE_MODE(240, 320, 37, 49),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ili9341_fops);
 
 static const struct drm_driver ili9341_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &ili9341_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "ili9341",
        .desc                   = "Ilitek ILI9341",
index 6d655e18e0aa2062c59d7d7be0469eccf27a6b87..a5b433a8e0d8abec911e3294bc090f7404d099d2 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modeset_helper.h>
@@ -159,12 +159,12 @@ static const struct drm_display_mode waveshare_mode = {
        DRM_SIMPLE_MODE(480, 320, 73, 49),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(ili9486_fops);
+DEFINE_DRM_GEM_DMA_FOPS(ili9486_fops);
 
 static const struct drm_driver ili9486_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &ili9486_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "ili9486",
        .desc                   = "Ilitek ILI9486",
index 5e060f6910bb45f557aa61f1540bb1139bb77b1d..27f1bd4da2f4e800673a156f2827bb90fe193cde 100644 (file)
@@ -17,7 +17,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modeset_helper.h>
@@ -150,12 +150,12 @@ static const struct drm_display_mode mi0283qt_mode = {
        DRM_SIMPLE_MODE(320, 240, 58, 43),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
+DEFINE_DRM_GEM_DMA_FOPS(mi0283qt_fops);
 
 static const struct drm_driver mi0283qt_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &mi0283qt_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "mi0283qt",
        .desc                   = "Multi-Inno MI0283QT",
index c759ff9c2c875396a5356c07763cd615c2544ee3..a76fefa8adbc8701a2344bdd69eab26f39c8cdbd 100644 (file)
@@ -18,7 +18,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 #include <drm/drm_modes.h>
@@ -217,12 +217,12 @@ static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = {
        .update = mipi_dbi_pipe_update,
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(panel_mipi_dbi_fops);
+DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops);
 
 static const struct drm_driver panel_mipi_dbi_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &panel_mipi_dbi_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "panel-mipi-dbi",
        .desc                   = "MIPI DBI compatible display panel",
index 013790c45d0a22f66a5aeef7c544f29f1f87af3c..c4c1be3ac0b86a8401c860fe891f8ff87c7fedd0 100644 (file)
 #include <drm/drm_connector.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_modes.h>
@@ -511,8 +511,10 @@ static void repaper_get_temperature(struct repaper_epd *epd)
 
 static int repaper_fb_dirty(struct drm_framebuffer *fb)
 {
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
        struct repaper_epd *epd = drm_to_epd(fb->dev);
+       unsigned int dst_pitch = 0;
+       struct iosys_map dst, vmap;
        struct drm_rect clip;
        int idx, ret = 0;
        u8 *buf = NULL;
@@ -541,7 +543,9 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb)
        if (ret)
                goto out_free;
 
-       drm_fb_xrgb8888_to_mono(buf, 0, cma_obj->vaddr, fb, &clip);
+       iosys_map_set_vaddr(&dst, buf);
+       iosys_map_set_vaddr(&vmap, dma_obj->vaddr);
+       drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, &vmap, fb, &clip);
 
        drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
 
@@ -903,12 +907,12 @@ static const struct drm_display_mode repaper_e2271cs021_mode = {
 static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f,
                                            0xff, 0xfe, 0x00, 0x00 };
 
-DEFINE_DRM_GEM_CMA_FOPS(repaper_fops);
+DEFINE_DRM_GEM_DMA_FOPS(repaper_fops);
 
 static const struct drm_driver repaper_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &repaper_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .name                   = "repaper",
        .desc                   = "Pervasive Displays RePaper e-ink panels",
        .date                   = "20170405",
index 5422363690e71d6f9a99903290ac218ed5381d8a..a81f91814595ba145522f0669c2a701fa4671a41 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/regulator/consumer.h>
 
 #include <drm/drm_aperture.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_damage_helper.h>
@@ -20,8 +21,8 @@
 #include <drm/drm_gem_shmem_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
 
 #define DRIVER_NAME    "simpledrm"
 #define DRIVER_DESC    "DRM driver for simple-framebuffer platform devices"
@@ -198,7 +199,6 @@ simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node)
 
 struct simpledrm_device {
        struct drm_device dev;
-       struct platform_device *pdev;
 
        /* clocks */
 #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
@@ -217,14 +217,15 @@ struct simpledrm_device {
        unsigned int pitch;
 
        /* memory management */
-       struct resource *mem;
        void __iomem *screen_base;
 
        /* modesetting */
        uint32_t formats[8];
        size_t nformats;
+       struct drm_plane primary_plane;
+       struct drm_crtc crtc;
+       struct drm_encoder encoder;
        struct drm_connector connector;
-       struct drm_simple_display_pipe pipe;
 };
 
 static struct simpledrm_device *simpledrm_device_of_dev(struct drm_device *dev)
@@ -272,7 +273,7 @@ static void simpledrm_device_release_clocks(void *res)
 static int simpledrm_device_init_clocks(struct simpledrm_device *sdev)
 {
        struct drm_device *dev = &sdev->dev;
-       struct platform_device *pdev = sdev->pdev;
+       struct platform_device *pdev = to_platform_device(dev->dev);
        struct device_node *of_node = pdev->dev.of_node;
        struct clk *clock;
        unsigned int i;
@@ -370,7 +371,7 @@ static void simpledrm_device_release_regulators(void *res)
 static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
 {
        struct drm_device *dev = &sdev->dev;
-       struct platform_device *pdev = sdev->pdev;
+       struct platform_device *pdev = to_platform_device(dev->dev);
        struct device_node *of_node = pdev->dev.of_node;
        struct property *prop;
        struct regulator *regulator;
@@ -450,120 +451,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)
 }
 #endif
 
-/*
- *  Simplefb settings
- */
-
-static struct drm_display_mode simpledrm_mode(unsigned int width,
-                                             unsigned int height)
-{
-       struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) };
-
-       mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */;
-       drm_mode_set_name(&mode);
-
-       return mode;
-}
-
-static int simpledrm_device_init_fb(struct simpledrm_device *sdev)
-{
-       int width, height, stride;
-       const struct drm_format_info *format;
-       struct drm_device *dev = &sdev->dev;
-       struct platform_device *pdev = sdev->pdev;
-       const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
-       struct device_node *of_node = pdev->dev.of_node;
-
-       if (pd) {
-               width = simplefb_get_width_pd(dev, pd);
-               if (width < 0)
-                       return width;
-               height = simplefb_get_height_pd(dev, pd);
-               if (height < 0)
-                       return height;
-               stride = simplefb_get_stride_pd(dev, pd);
-               if (stride < 0)
-                       return stride;
-               format = simplefb_get_format_pd(dev, pd);
-               if (IS_ERR(format))
-                       return PTR_ERR(format);
-       } else if (of_node) {
-               width = simplefb_get_width_of(dev, of_node);
-               if (width < 0)
-                       return width;
-               height = simplefb_get_height_of(dev, of_node);
-               if (height < 0)
-                       return height;
-               stride = simplefb_get_stride_of(dev, of_node);
-               if (stride < 0)
-                       return stride;
-               format = simplefb_get_format_of(dev, of_node);
-               if (IS_ERR(format))
-                       return PTR_ERR(format);
-       } else {
-               drm_err(dev, "no simplefb configuration found\n");
-               return -ENODEV;
-       }
-
-       sdev->mode = simpledrm_mode(width, height);
-       sdev->format = format;
-       sdev->pitch = stride;
-
-       drm_dbg_kms(dev, "display mode={" DRM_MODE_FMT "}\n",
-                   DRM_MODE_ARG(&sdev->mode));
-       drm_dbg_kms(dev,
-                   "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
-                   &format->format, width, height, stride);
-
-       return 0;
-}
-
-/*
- * Memory management
- */
-
-static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
-{
-       struct drm_device *dev = &sdev->dev;
-       struct platform_device *pdev = sdev->pdev;
-       struct resource *res, *mem;
-       void __iomem *screen_base;
-       int ret;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EINVAL;
-
-       ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
-       if (ret) {
-               drm_err(dev, "could not acquire memory range %pr: error %d\n",
-                       res, ret);
-               return ret;
-       }
-
-       mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
-                                     sdev->dev.driver->name);
-       if (!mem) {
-               /*
-                * We cannot make this fatal. Sometimes this comes from magic
-                * spaces our resource handlers simply don't know about. Use
-                * the I/O-memory resource as-is and try to map that instead.
-                */
-               drm_warn(dev, "could not acquire memory region %pr\n", res);
-               mem = res;
-       }
-
-       screen_base = devm_ioremap_wc(&pdev->dev, mem->start,
-                                     resource_size(mem));
-       if (!screen_base)
-               return -ENOMEM;
-
-       sdev->mem = mem;
-       sdev->screen_base = screen_base;
-
-       return 0;
-}
-
 /*
  * Modesetting
  */
@@ -576,7 +463,7 @@ static int simpledrm_device_init_mm(struct simpledrm_device *sdev)
  * TODO: Add blit helpers for remaining formats and uncomment
  *       constants.
  */
-static const uint32_t simpledrm_default_formats[] = {
+static const uint32_t simpledrm_primary_plane_formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
        DRM_FORMAT_RGB565,
@@ -587,81 +474,52 @@ static const uint32_t simpledrm_default_formats[] = {
        DRM_FORMAT_ARGB2101010,
 };
 
-static const uint64_t simpledrm_format_modifiers[] = {
+static const uint64_t simpledrm_primary_plane_format_modifiers[] = {
        DRM_FORMAT_MOD_LINEAR,
        DRM_FORMAT_MOD_INVALID
 };
 
-static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
+static int simpledrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
+                                                      struct drm_atomic_state *new_state)
 {
-       struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev);
-       struct drm_display_mode *mode;
-
-       mode = drm_mode_duplicate(connector->dev, &sdev->mode);
-       if (!mode)
-               return 0;
-
-       if (mode->name[0] == '\0')
-               drm_mode_set_name(mode);
-
-       mode->type |= DRM_MODE_TYPE_PREFERRED;
-       drm_mode_probed_add(connector, mode);
-
-       if (mode->width_mm)
-               connector->display_info.width_mm = mode->width_mm;
-       if (mode->height_mm)
-               connector->display_info.height_mm = mode->height_mm;
-
-       return 1;
-}
-
-static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = {
-       .get_modes = simpledrm_connector_helper_get_modes,
-};
-
-static const struct drm_connector_funcs simpledrm_connector_funcs = {
-       .reset = drm_atomic_helper_connector_reset,
-       .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = drm_connector_cleanup,
-       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
+       struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
+       struct drm_crtc *new_crtc = new_plane_state->crtc;
+       struct drm_crtc_state *new_crtc_state = NULL;
+       int ret;
 
-static enum drm_mode_status
-simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
-                                   const struct drm_display_mode *mode)
-{
-       struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
+       if (new_crtc)
+               new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_crtc);
 
-       if (mode->hdisplay != sdev->mode.hdisplay &&
-           mode->vdisplay != sdev->mode.vdisplay)
-               return MODE_ONE_SIZE;
-       else if (mode->hdisplay != sdev->mode.hdisplay)
-               return MODE_ONE_WIDTH;
-       else if (mode->vdisplay != sdev->mode.vdisplay)
-               return MODE_ONE_HEIGHT;
+       ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 false, false);
+       if (ret)
+               return ret;
+       else if (!new_plane_state->visible)
+               return 0;
 
-       return MODE_OK;
+       return 0;
 }
 
-static void
-simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
-                                    struct drm_crtc_state *crtc_state,
-                                    struct drm_plane_state *plane_state)
+static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
+                                                        struct drm_atomic_state *old_state)
 {
-       struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
+       struct drm_plane_state *plane_state = plane->state;
+       struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
        struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
        struct drm_framebuffer *fb = plane_state->fb;
-       void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
-       struct drm_device *dev = &sdev->dev;
-       void __iomem *dst = sdev->screen_base;
+       struct drm_device *dev = plane->dev;
+       struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
+       struct iosys_map dst = IOSYS_MAP_INIT_VADDR(sdev->screen_base);
        struct drm_rect src_clip, dst_clip;
        int idx;
 
        if (!fb)
                return;
 
-       drm_rect_fp_to_int(&src_clip, &plane_state->src);
+       if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
+               return;
 
        dst_clip = plane_state->dst;
        if (!drm_rect_intersect(&dst_clip, &src_clip))
@@ -670,17 +528,18 @@ simpledrm_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
        if (!drm_dev_enter(dev, &idx))
                return;
 
-       dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip);
-       drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip);
+       iosys_map_incr(&dst, drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip));
+       drm_fb_blit(&dst, &sdev->pitch, sdev->format->format, shadow_plane_state->data, fb,
+                   &src_clip);
 
        drm_dev_exit(idx);
 }
 
-static void
-simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+                                                         struct drm_atomic_state *old_state)
 {
-       struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
-       struct drm_device *dev = &sdev->dev;
+       struct drm_device *dev = plane->dev;
+       struct simpledrm_device *sdev = simpledrm_device_of_dev(dev);
        int idx;
 
        if (!drm_dev_enter(dev, &idx))
@@ -692,46 +551,105 @@ simpledrm_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
        drm_dev_exit(idx);
 }
 
-static void
-simpledrm_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
-                                    struct drm_plane_state *old_plane_state)
+static const struct drm_plane_helper_funcs simpledrm_primary_plane_helper_funcs = {
+       DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+       .atomic_check = simpledrm_primary_plane_helper_atomic_check,
+       .atomic_update = simpledrm_primary_plane_helper_atomic_update,
+       .atomic_disable = simpledrm_primary_plane_helper_atomic_disable,
+};
+
+static const struct drm_plane_funcs simpledrm_primary_plane_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = drm_plane_cleanup,
+       DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *crtc,
+                                                            const struct drm_display_mode *mode)
 {
-       struct simpledrm_device *sdev = simpledrm_device_of_dev(pipe->crtc.dev);
-       struct drm_plane_state *plane_state = pipe->plane.state;
-       struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
-       void *vmap = shadow_plane_state->data[0].vaddr; /* TODO: Use mapping abstraction */
-       struct drm_framebuffer *fb = plane_state->fb;
-       struct drm_device *dev = &sdev->dev;
-       void __iomem *dst = sdev->screen_base;
-       struct drm_rect src_clip, dst_clip;
-       int idx;
+       struct simpledrm_device *sdev = simpledrm_device_of_dev(crtc->dev);
 
-       if (!fb)
-               return;
+       if (mode->hdisplay != sdev->mode.hdisplay &&
+           mode->vdisplay != sdev->mode.vdisplay)
+               return MODE_ONE_SIZE;
+       else if (mode->hdisplay != sdev->mode.hdisplay)
+               return MODE_ONE_WIDTH;
+       else if (mode->vdisplay != sdev->mode.vdisplay)
+               return MODE_ONE_HEIGHT;
 
-       if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
-               return;
+       return MODE_OK;
+}
 
-       dst_clip = plane_state->dst;
-       if (!drm_rect_intersect(&dst_clip, &src_clip))
-               return;
+static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
+                                             struct drm_atomic_state *new_state)
+{
+       struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+       int ret;
 
-       if (!drm_dev_enter(dev, &idx))
-               return;
+       ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
+       if (ret)
+               return ret;
 
-       dst += drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip);
-       drm_fb_blit_toio(dst, sdev->pitch, sdev->format->format, vmap, fb, &src_clip);
+       return drm_atomic_add_affected_planes(new_state, crtc);
+}
 
-       drm_dev_exit(idx);
+/*
+ * The CRTC is always enabled. Screen updates are performed by
+ * the primary plane's atomic_update function. Disabling clears
+ * the screen in the primary plane's atomic_disable function.
+ */
+static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = {
+       .mode_valid = simpledrm_crtc_helper_mode_valid,
+       .atomic_check = simpledrm_crtc_helper_atomic_check,
+};
+
+static const struct drm_crtc_funcs simpledrm_crtc_funcs = {
+       .reset = drm_atomic_helper_crtc_reset,
+       .destroy = drm_crtc_cleanup,
+       .set_config = drm_atomic_helper_set_config,
+       .page_flip = drm_atomic_helper_page_flip,
+       .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_encoder_funcs simpledrm_encoder_funcs = {
+       .destroy = drm_encoder_cleanup,
+};
+
+static int simpledrm_connector_helper_get_modes(struct drm_connector *connector)
+{
+       struct simpledrm_device *sdev = simpledrm_device_of_dev(connector->dev);
+       struct drm_display_mode *mode;
+
+       mode = drm_mode_duplicate(connector->dev, &sdev->mode);
+       if (!mode)
+               return 0;
+
+       if (mode->name[0] == '\0')
+               drm_mode_set_name(mode);
+
+       mode->type |= DRM_MODE_TYPE_PREFERRED;
+       drm_mode_probed_add(connector, mode);
+
+       if (mode->width_mm)
+               connector->display_info.width_mm = mode->width_mm;
+       if (mode->height_mm)
+               connector->display_info.height_mm = mode->height_mm;
+
+       return 1;
 }
 
-static const struct drm_simple_display_pipe_funcs
-simpledrm_simple_display_pipe_funcs = {
-       .mode_valid = simpledrm_simple_display_pipe_mode_valid,
-       .enable = simpledrm_simple_display_pipe_enable,
-       .disable = simpledrm_simple_display_pipe_disable,
-       .update = simpledrm_simple_display_pipe_update,
-       DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+static const struct drm_connector_helper_funcs simpledrm_connector_helper_funcs = {
+       .get_modes = simpledrm_connector_helper_get_modes,
+};
+
+static const struct drm_connector_funcs simpledrm_connector_funcs = {
+       .reset = drm_atomic_helper_connector_reset,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = drm_connector_cleanup,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+       .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 };
 
 static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
@@ -740,6 +658,21 @@ static const struct drm_mode_config_funcs simpledrm_mode_config_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
+/*
+ * Init / Cleanup
+ */
+
+static struct drm_display_mode simpledrm_mode(unsigned int width,
+                                             unsigned int height)
+{
+       struct drm_display_mode mode = { SIMPLEDRM_MODE(width, height) };
+
+       mode.clock = mode.hdisplay * mode.vdisplay * 60 / 1000 /* kHz */;
+       drm_mode_set_name(&mode);
+
+       return mode;
+}
+
 static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev,
                                                size_t *nformats_out)
 {
@@ -754,10 +687,10 @@ static const uint32_t *simpledrm_device_formats(struct simpledrm_device *sdev,
        sdev->nformats = 1;
 
        /* default formats go second */
-       for (i = 0; i < ARRAY_SIZE(simpledrm_default_formats); ++i) {
-               if (simpledrm_default_formats[i] == sdev->format->format)
+       for (i = 0; i < ARRAY_SIZE(simpledrm_primary_plane_formats); ++i) {
+               if (simpledrm_primary_plane_formats[i] == sdev->format->format)
                        continue; /* native format already went first */
-               sdev->formats[sdev->nformats] = simpledrm_default_formats[i];
+               sdev->formats[sdev->nformats] = simpledrm_primary_plane_formats[i];
                sdev->nformats++;
        }
 
@@ -779,88 +712,182 @@ out:
        return sdev->formats;
 }
 
-static int simpledrm_device_init_modeset(struct simpledrm_device *sdev)
+static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,
+                                                       struct platform_device *pdev)
 {
-       struct drm_device *dev = &sdev->dev;
-       struct drm_display_mode *mode = &sdev->mode;
-       struct drm_connector *connector = &sdev->connector;
-       struct drm_simple_display_pipe *pipe = &sdev->pipe;
+       const struct simplefb_platform_data *pd = dev_get_platdata(&pdev->dev);
+       struct device_node *of_node = pdev->dev.of_node;
+       struct simpledrm_device *sdev;
+       struct drm_device *dev;
+       int width, height, stride;
+       const struct drm_format_info *format;
+       struct resource *res, *mem;
+       void __iomem *screen_base;
+       struct drm_plane *primary_plane;
+       struct drm_crtc *crtc;
+       struct drm_encoder *encoder;
+       struct drm_connector *connector;
        unsigned long max_width, max_height;
        const uint32_t *formats;
        size_t nformats;
        int ret;
 
-       ret = drmm_mode_config_init(dev);
+       sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device, dev);
+       if (IS_ERR(sdev))
+               return ERR_CAST(sdev);
+       dev = &sdev->dev;
+       platform_set_drvdata(pdev, sdev);
+
+       /*
+        * Hardware settings
+        */
+
+       ret = simpledrm_device_init_clocks(sdev);
        if (ret)
-               return ret;
+               return ERR_PTR(ret);
+       ret = simpledrm_device_init_regulators(sdev);
+       if (ret)
+               return ERR_PTR(ret);
 
-       max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
-       max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
+       if (pd) {
+               width = simplefb_get_width_pd(dev, pd);
+               if (width < 0)
+                       return ERR_PTR(width);
+               height = simplefb_get_height_pd(dev, pd);
+               if (height < 0)
+                       return ERR_PTR(height);
+               stride = simplefb_get_stride_pd(dev, pd);
+               if (stride < 0)
+                       return ERR_PTR(stride);
+               format = simplefb_get_format_pd(dev, pd);
+               if (IS_ERR(format))
+                       return ERR_CAST(format);
+       } else if (of_node) {
+               width = simplefb_get_width_of(dev, of_node);
+               if (width < 0)
+                       return ERR_PTR(width);
+               height = simplefb_get_height_of(dev, of_node);
+               if (height < 0)
+                       return ERR_PTR(height);
+               stride = simplefb_get_stride_of(dev, of_node);
+               if (stride < 0)
+                       return ERR_PTR(stride);
+               format = simplefb_get_format_of(dev, of_node);
+               if (IS_ERR(format))
+                       return ERR_CAST(format);
+       } else {
+               drm_err(dev, "no simplefb configuration found\n");
+               return ERR_PTR(-ENODEV);
+       }
+       if (!stride)
+               stride = DIV_ROUND_UP(drm_format_info_bpp(format, 0) * width, 8);
 
-       dev->mode_config.min_width = mode->hdisplay;
-       dev->mode_config.max_width = max_width;
-       dev->mode_config.min_height = mode->vdisplay;
-       dev->mode_config.max_height = max_height;
-       dev->mode_config.preferred_depth = sdev->format->cpp[0] * 8;
-       dev->mode_config.funcs = &simpledrm_mode_config_funcs;
+       sdev->mode = simpledrm_mode(width, height);
+       sdev->format = format;
+       sdev->pitch = stride;
 
-       ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
-                                DRM_MODE_CONNECTOR_Unknown);
-       if (ret)
-               return ret;
-       drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
-       drm_connector_set_panel_orientation_with_quirk(connector,
-                                                      DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
-                                                      mode->hdisplay, mode->vdisplay);
+       drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&sdev->mode));
+       drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d byte\n",
+               &format->format, width, height, stride);
 
-       formats = simpledrm_device_formats(sdev, &nformats);
+       /*
+        * Memory management
+        */
 
-       ret = drm_simple_display_pipe_init(dev, pipe, &simpledrm_simple_display_pipe_funcs,
-                                          formats, nformats, simpledrm_format_modifiers,
-                                          connector);
-       if (ret)
-               return ret;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return ERR_PTR(-EINVAL);
 
-       drm_plane_enable_fb_damage_clips(&pipe->plane);
+       ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res));
+       if (ret) {
+               drm_err(dev, "could not acquire memory range %pr: error %d\n", res, ret);
+               return ERR_PTR(ret);
+       }
 
-       drm_mode_config_reset(dev);
+       mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), drv->name);
+       if (!mem) {
+               /*
+                * We cannot make this fatal. Sometimes this comes from magic
+                * spaces our resource handlers simply don't know about. Use
+                * the I/O-memory resource as-is and try to map that instead.
+                */
+               drm_warn(dev, "could not acquire memory region %pr\n", res);
+               mem = res;
+       }
 
-       return 0;
-}
+       screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem));
+       if (!screen_base)
+               return ERR_PTR(-ENOMEM);
+       sdev->screen_base = screen_base;
 
-/*
- * Init / Cleanup
- */
+       /*
+        * Modesetting
       */
 
-static struct simpledrm_device *
-simpledrm_device_create(struct drm_driver *drv, struct platform_device *pdev)
-{
-       struct simpledrm_device *sdev;
-       int ret;
+       ret = drmm_mode_config_init(dev);
+       if (ret)
+               return ERR_PTR(ret);
 
-       sdev = devm_drm_dev_alloc(&pdev->dev, drv, struct simpledrm_device,
-                                 dev);
-       if (IS_ERR(sdev))
-               return ERR_CAST(sdev);
-       sdev->pdev = pdev;
-       platform_set_drvdata(pdev, sdev);
+       max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH);
+       max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT);
 
-       ret = simpledrm_device_init_clocks(sdev);
+       dev->mode_config.min_width = width;
+       dev->mode_config.max_width = max_width;
+       dev->mode_config.min_height = height;
+       dev->mode_config.max_height = max_height;
+       dev->mode_config.preferred_depth = format->cpp[0] * 8;
+       dev->mode_config.funcs = &simpledrm_mode_config_funcs;
+
+       /* Primary plane */
+
+       formats = simpledrm_device_formats(sdev, &nformats);
+
+       primary_plane = &sdev->primary_plane;
+       ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs,
+                                      formats, nformats,
+                                      simpledrm_primary_plane_format_modifiers,
+                                      DRM_PLANE_TYPE_PRIMARY, NULL);
        if (ret)
                return ERR_PTR(ret);
-       ret = simpledrm_device_init_regulators(sdev);
+       drm_plane_helper_add(primary_plane, &simpledrm_primary_plane_helper_funcs);
+       drm_plane_enable_fb_damage_clips(primary_plane);
+
+       /* CRTC */
+
+       crtc = &sdev->crtc;
+       ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+                                       &simpledrm_crtc_funcs, NULL);
        if (ret)
                return ERR_PTR(ret);
-       ret = simpledrm_device_init_fb(sdev);
+       drm_crtc_helper_add(crtc, &simpledrm_crtc_helper_funcs);
+
+       /* Encoder */
+
+       encoder = &sdev->encoder;
+       ret = drm_encoder_init(dev, encoder, &simpledrm_encoder_funcs,
+                              DRM_MODE_ENCODER_NONE, NULL);
        if (ret)
                return ERR_PTR(ret);
-       ret = simpledrm_device_init_mm(sdev);
+       encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+       /* Connector */
+
+       connector = &sdev->connector;
+       ret = drm_connector_init(dev, connector, &simpledrm_connector_funcs,
+                                DRM_MODE_CONNECTOR_Unknown);
        if (ret)
                return ERR_PTR(ret);
-       ret = simpledrm_device_init_modeset(sdev);
+       drm_connector_helper_add(connector, &simpledrm_connector_helper_funcs);
+       drm_connector_set_panel_orientation_with_quirk(connector,
+                                                      DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
+                                                      width, height);
+
+       ret = drm_connector_attach_encoder(connector, encoder);
        if (ret)
                return ERR_PTR(ret);
 
+       drm_mode_config_reset(dev);
+
        return sdev;
 }
 
index 8eddb020c43e1e907495bf3d9c39ae5a8d05283d..b6f620b902e6dabb2337a08a9e25e0bab291d725 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_format_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
@@ -69,12 +69,15 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
        size_t len = (clip->x2 - clip->x1) * (clip->y2 - clip->y1);
        unsigned int x, y;
        u8 *src, *buf, val;
+       struct iosys_map dst_map, vmap;
 
        buf = kmalloc(len, GFP_KERNEL);
        if (!buf)
                return;
 
-       drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, clip);
+       iosys_map_set_vaddr(&dst_map, buf);
+       iosys_map_set_vaddr(&vmap, vaddr);
+       drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, clip);
        src = buf;
 
        for (y = clip->y1; y < clip->y2; y++) {
@@ -92,8 +95,8 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr,
 static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
                           struct drm_rect *clip)
 {
-       struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
-       void *src = cma_obj->vaddr;
+       struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
+       void *src = dma_obj->vaddr;
        int ret = 0;
 
        ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
@@ -269,12 +272,12 @@ static const struct drm_display_mode st7586_mode = {
        DRM_SIMPLE_MODE(178, 128, 37, 27),
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(st7586_fops);
+DEFINE_DRM_GEM_DMA_FOPS(st7586_fops);
 
 static const struct drm_driver st7586_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &st7586_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "st7586",
        .desc                   = "Sitronix ST7586",
index e0f02d367d880ae4fceb2f2d3d0a8a15485b4332..d2042a0f02dd358b357fb63ba26d39f7289de5b7 100644 (file)
@@ -20,7 +20,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mipi_dbi.h>
 
@@ -151,12 +151,12 @@ static const struct st7735r_cfg rh128128t_cfg = {
        .rgb            = true,
 };
 
-DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops);
+DEFINE_DRM_GEM_DMA_FOPS(st7735r_fops);
 
 static const struct drm_driver st7735r_driver = {
        .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
        .fops                   = &st7735r_fops,
-       DRM_GEM_CMA_DRIVER_OPS_VMAP,
+       DRM_GEM_DMA_DRIVER_OPS_VMAP,
        .debugfs_init           = mipi_dbi_debugfs_init,
        .name                   = "st7735r",
        .desc                   = "Sitronix ST7735R",
index 97184c33352662662bbd27de462eacb111045435..590110fdf59cde5c0b138ea13fe8e29b1a8a09f5 100644 (file)
@@ -117,12 +117,13 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
                                  struct ttm_operation_ctx *ctx,
                                  struct ttm_place *hop)
 {
-       struct ttm_resource_manager *old_man, *new_man;
        struct ttm_device *bdev = bo->bdev;
+       bool old_use_tt, new_use_tt;
        int ret;
 
-       old_man = ttm_manager_type(bdev, bo->resource->mem_type);
-       new_man = ttm_manager_type(bdev, mem->mem_type);
+       old_use_tt = bo->resource &&
+               ttm_manager_type(bdev, bo->resource->mem_type)->use_tt;
+       new_use_tt = ttm_manager_type(bdev, mem->mem_type)->use_tt;
 
        ttm_bo_unmap_virtual(bo);
 
@@ -130,11 +131,11 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
         * Create and bind a ttm if required.
         */
 
-       if (new_man->use_tt) {
+       if (new_use_tt) {
                /* Zero init the new TTM structure if the old location should
                 * have used one as well.
                 */
-               ret = ttm_tt_create(bo, old_man->use_tt);
+               ret = ttm_tt_create(bo, old_use_tt);
                if (ret)
                        goto out_err;
 
@@ -160,8 +161,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
        return 0;
 
 out_err:
-       new_man = ttm_manager_type(bdev, bo->resource->mem_type);
-       if (!new_man->use_tt)
+       if (!old_use_tt)
                ttm_bo_tt_destroy(bo);
 
        return ret;
@@ -904,7 +904,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
        /*
         * Check whether we need to move buffer.
         */
-       if (!ttm_resource_compat(bo->resource, placement)) {
+       if (!bo->resource || !ttm_resource_compat(bo->resource, placement)) {
                ret = ttm_bo_move_buffer(bo, placement, ctx);
                if (ret)
                        return ret;
@@ -921,36 +921,61 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
 }
 EXPORT_SYMBOL(ttm_bo_validate);
 
-int ttm_bo_init_reserved(struct ttm_device *bdev,
-                        struct ttm_buffer_object *bo,
-                        size_t size,
-                        enum ttm_bo_type type,
-                        struct ttm_placement *placement,
-                        uint32_t page_alignment,
-                        struct ttm_operation_ctx *ctx,
-                        struct sg_table *sg,
-                        struct dma_resv *resv,
+/**
+ * ttm_bo_init_reserved
+ *
+ * @bdev: Pointer to a ttm_device struct.
+ * @bo: Pointer to a ttm_buffer_object to be initialized.
+ * @type: Requested type of buffer object.
+ * @placement: Initial placement for buffer object.
+ * @alignment: Data alignment in pages.
+ * @ctx: TTM operation context for memory allocation.
+ * @sg: Scatter-gather table.
+ * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
+ * @destroy: Destroy function. Use NULL for kfree().
+ *
+ * This function initializes a pre-allocated struct ttm_buffer_object.
+ * As this object may be part of a larger structure, this function,
+ * together with the @destroy function, enables driver-specific objects
+ * derived from a ttm_buffer_object.
+ *
+ * On successful return, the caller owns an object kref to @bo. The kref and
+ * list_kref are usually set to 1, but note that in some situations, other
+ * tasks may already be holding references to @bo as well.
+ * Furthermore, if resv == NULL, the buffer's reservation lock will be held,
+ * and it is the caller's responsibility to call ttm_bo_unreserve.
+ *
+ * If a failure occurs, the function will call the @destroy function. Thus,
+ * after a failure, dereferencing @bo is illegal and will likely cause memory
+ * corruption.
+ *
+ * Returns
+ * -ENOMEM: Out of memory.
+ * -EINVAL: Invalid placement flags.
+ * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources.
+ */
+int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo,
+                        enum ttm_bo_type type, struct ttm_placement *placement,
+                        uint32_t alignment, struct ttm_operation_ctx *ctx,
+                        struct sg_table *sg, struct dma_resv *resv,
                         void (*destroy) (struct ttm_buffer_object *))
 {
        static const struct ttm_place sys_mem = { .mem_type = TTM_PL_SYSTEM };
-       bool locked;
        int ret;
 
-       bo->destroy = destroy;
        kref_init(&bo->kref);
        INIT_LIST_HEAD(&bo->ddestroy);
        bo->bdev = bdev;
        bo->type = type;
-       bo->page_alignment = page_alignment;
+       bo->page_alignment = alignment;
+       bo->destroy = destroy;
        bo->pin_count = 0;
        bo->sg = sg;
        bo->bulk_move = NULL;
-       if (resv) {
+       if (resv)
                bo->base.resv = resv;
-               dma_resv_assert_held(bo->base.resv);
-       } else {
+       else
                bo->base.resv = &bo->base._resv;
-       }
        atomic_inc(&ttm_glob.bo_count);
 
        ret = ttm_resource_alloc(bo, &sys_mem, &bo->resource);
@@ -963,50 +988,84 @@ int ttm_bo_init_reserved(struct ttm_device *bdev,
         * For ttm_bo_type_device buffers, allocate
         * address space from the device.
         */
-       if (bo->type == ttm_bo_type_device ||
-           bo->type == ttm_bo_type_sg)
+       if (bo->type == ttm_bo_type_device || bo->type == ttm_bo_type_sg) {
                ret = drm_vma_offset_add(bdev->vma_manager, &bo->base.vma_node,
-                                        bo->resource->num_pages);
+                                        PFN_UP(bo->base.size));
+               if (ret)
+                       goto err_put;
+       }
 
        /* passed reservation objects should already be locked,
         * since otherwise lockdep will be angered in radeon.
         */
-       if (!resv) {
-               locked = dma_resv_trylock(bo->base.resv);
-               WARN_ON(!locked);
-       }
+       if (!resv)
+               WARN_ON(!dma_resv_trylock(bo->base.resv));
+       else
+               dma_resv_assert_held(resv);
 
-       if (likely(!ret))
-               ret = ttm_bo_validate(bo, placement, ctx);
+       ret = ttm_bo_validate(bo, placement, ctx);
+       if (unlikely(ret))
+               goto err_unlock;
 
-       if (unlikely(ret)) {
-               if (!resv)
-                       ttm_bo_unreserve(bo);
+       return 0;
 
-               ttm_bo_put(bo);
-               return ret;
-       }
+err_unlock:
+       if (!resv)
+               dma_resv_unlock(bo->base.resv);
 
+err_put:
+       ttm_bo_put(bo);
        return ret;
 }
 EXPORT_SYMBOL(ttm_bo_init_reserved);
 
-int ttm_bo_init(struct ttm_device *bdev,
-               struct ttm_buffer_object *bo,
-               size_t size,
-               enum ttm_bo_type type,
-               struct ttm_placement *placement,
-               uint32_t page_alignment,
-               bool interruptible,
-               struct sg_table *sg,
-               struct dma_resv *resv,
-               void (*destroy) (struct ttm_buffer_object *))
+/**
+ * ttm_bo_init_validate
+ *
+ * @bdev: Pointer to a ttm_device struct.
+ * @bo: Pointer to a ttm_buffer_object to be initialized.
+ * @type: Requested type of buffer object.
+ * @placement: Initial placement for buffer object.
+ * @alignment: Data alignment in pages.
+ * @interruptible: If needing to sleep to wait for GPU resources,
+ * sleep interruptible.
+ * pinned in physical memory. If this behaviour is not desired, this member
+ * holds a pointer to a persistent shmem object. Typically, this would
+ * point to the shmem object backing a GEM object if TTM is used to back a
+ * GEM user interface.
+ * @sg: Scatter-gather table.
+ * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
+ * @destroy: Destroy function. Use NULL for kfree().
+ *
+ * This function initializes a pre-allocated struct ttm_buffer_object.
+ * As this object may be part of a larger structure, this function,
+ * together with the @destroy function,
+ * enables driver-specific objects derived from a ttm_buffer_object.
+ *
+ * On successful return, the caller owns an object kref to @bo. The kref and
+ * list_kref are usually set to 1, but note that in some situations, other
+ * tasks may already be holding references to @bo as well.
+ *
+ * If a failure occurs, the function will call the @destroy function, Thus,
+ * after a failure, dereferencing @bo is illegal and will likely cause memory
+ * corruption.
+ *
+ * Returns
+ * -ENOMEM: Out of memory.
+ * -EINVAL: Invalid placement flags.
+ * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources.
+ */
+int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo,
+                        enum ttm_bo_type type, struct ttm_placement *placement,
+                        uint32_t alignment, bool interruptible,
+                        struct sg_table *sg, struct dma_resv *resv,
+                        void (*destroy) (struct ttm_buffer_object *))
 {
        struct ttm_operation_ctx ctx = { interruptible, false };
        int ret;
 
-       ret = ttm_bo_init_reserved(bdev, bo, size, type, placement,
-                                  page_alignment, &ctx, sg, resv, destroy);
+       ret = ttm_bo_init_reserved(bdev, bo, type, placement, alignment, &ctx,
+                                  sg, resv, destroy);
        if (ret)
                return ret;
 
@@ -1015,7 +1074,7 @@ int ttm_bo_init(struct ttm_device *bdev,
 
        return 0;
 }
-EXPORT_SYMBOL(ttm_bo_init);
+EXPORT_SYMBOL(ttm_bo_init_validate);
 
 /*
  * buffer object vm functions.
index 1cbfb00c1d6586313711aa837d636c1eeee6ff4b..1530982338e9faef3e1fd516787fbd08f36ad0a5 100644 (file)
@@ -137,8 +137,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
                ttm_manager_type(bo->bdev, dst_mem->mem_type);
        struct ttm_tt *ttm = bo->ttm;
        struct ttm_resource *src_mem = bo->resource;
-       struct ttm_resource_manager *src_man =
-               ttm_manager_type(bdev, src_mem->mem_type);
+       struct ttm_resource_manager *src_man;
        union {
                struct ttm_kmap_iter_tt tt;
                struct ttm_kmap_iter_linear_io io;
@@ -147,6 +146,10 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
        bool clear;
        int ret = 0;
 
+       if (!src_mem)
+               return 0;
+
+       src_man = ttm_manager_type(bdev, src_mem->mem_type);
        if (ttm && ((ttm->page_flags & TTM_TT_FLAG_SWAPPED) ||
                    dst_man->use_tt)) {
                ret = ttm_tt_populate(bdev, ttm, ctx);
index 47a7dbe6c11480ad8ce4d6fee8289d6abb6ba487..11e865be81c6d0416c3622060c52bcff06ca50e0 100644 (file)
@@ -8,7 +8,7 @@ config DRM_TVE200
        select DRM_BRIDGE
        select DRM_PANEL_BRIDGE
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE
        help
          Choose this option for DRM support for the Faraday TV Encoder
index 771bad881714da385b66894c4bd9d0a5c3afb58c..37bdd976ae591ac4fbd6c9823cb019d9ea2bc860 100644 (file)
 #include <linux/of_graph.h>
 #include <linux/delay.h>
 
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_vblank.h>
 
@@ -90,7 +90,7 @@ static int tve200_display_check(struct drm_simple_display_pipe *pipe,
        }
 
        if (fb) {
-               u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
+               u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0);
 
                /* FB base address must be dword aligned. */
                if (offset & 3) {
@@ -267,14 +267,14 @@ static void tve200_display_update(struct drm_simple_display_pipe *pipe,
 
        if (fb) {
                /* For RGB, the Y component is used as base address */
-               writel(drm_fb_cma_get_gem_addr(fb, pstate, 0),
+               writel(drm_fb_dma_get_gem_addr(fb, pstate, 0),
                       priv->regs + TVE200_Y_FRAME_BASE_ADDR);
 
                /* For three plane YUV we need two more addresses */
                if (fb->format->format == DRM_FORMAT_YUV420) {
-                       writel(drm_fb_cma_get_gem_addr(fb, pstate, 1),
+                       writel(drm_fb_dma_get_gem_addr(fb, pstate, 1),
                               priv->regs + TVE200_U_FRAME_BASE_ADDR);
-                       writel(drm_fb_cma_get_gem_addr(fb, pstate, 2),
+                       writel(drm_fb_dma_get_gem_addr(fb, pstate, 2),
                               priv->regs + TVE200_V_FRAME_BASE_ADDR);
                }
        }
index 6d9d2921abf49df4e4dbe34f4c680e33df733079..79d790ae1670e9500554de54827662677f1f13bc 100644 (file)
@@ -39,9 +39,8 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_module.h>
 #include <drm/drm_of.h>
@@ -135,7 +134,7 @@ finish:
        return ret;
 }
 
-DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(drm_fops);
 
 static const struct drm_driver tve200_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
@@ -147,7 +146,7 @@ static const struct drm_driver tve200_drm_driver = {
        .major = 1,
        .minor = 0,
        .patchlevel = 0,
-       DRM_GEM_CMA_DRIVER_OPS,
+       DRM_GEM_DMA_DRIVER_OPS,
 };
 
 static int tve200_probe(struct platform_device *pdev)
index cc16a13316e4e1f565331449b6ee17b6cee3b543..28aaf75d71cf09ffadbcace9acc7506cff3b0793 100644 (file)
@@ -34,14 +34,14 @@ struct udl_device;
 struct urb_node {
        struct list_head entry;
        struct udl_device *dev;
-       struct delayed_work release_urb_work;
        struct urb *urb;
 };
 
 struct urb_list {
        struct list_head list;
+       struct list_head in_flight;
        spinlock_t lock;
-       struct semaphore limit_sem;
+       wait_queue_head_t sleep;
        int available;
        int count;
        size_t size;
@@ -75,9 +75,17 @@ static inline struct usb_device *udl_to_usb_device(struct udl_device *udl)
 int udl_modeset_init(struct drm_device *dev);
 struct drm_connector *udl_connector_init(struct drm_device *dev);
 
-struct urb *udl_get_urb(struct drm_device *dev);
+struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout);
+
+#define GET_URB_TIMEOUT        HZ
+static inline struct urb *udl_get_urb(struct drm_device *dev)
+{
+       return udl_get_urb_timeout(dev, GET_URB_TIMEOUT);
+}
 
 int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len);
+int udl_sync_pending_urbs(struct drm_device *dev);
+void udl_kill_pending_urbs(struct drm_device *dev);
 void udl_urb_completion(struct urb *urb);
 
 int udl_init(struct udl_device *udl);
index 853f147036f6b5c5ecda9598c0bbd8d0f010a8d0..fdafbf8f3c3cb083b1cd03029d1089ce21bc267c 100644 (file)
@@ -23,9 +23,6 @@
 #define WRITES_IN_FLIGHT (4)
 #define MAX_VENDOR_DESCRIPTOR_SIZE 256
 
-#define GET_URB_TIMEOUT        HZ
-#define FREE_URB_TIMEOUT (HZ*2)
-
 static int udl_parse_vendor_descriptor(struct udl_device *udl)
 {
        struct usb_device *udev = udl_to_usb_device(udl);
@@ -119,14 +116,6 @@ static int udl_select_std_channel(struct udl_device *udl)
        return ret < 0 ? ret : 0;
 }
 
-static void udl_release_urb_work(struct work_struct *work)
-{
-       struct urb_node *unode = container_of(work, struct urb_node,
-                                             release_urb_work.work);
-
-       up(&unode->dev->urbs.limit_sem);
-}
-
 void udl_urb_completion(struct urb *urb)
 {
        struct urb_node *unode = urb->context;
@@ -146,27 +135,17 @@ void udl_urb_completion(struct urb *urb)
        urb->transfer_buffer_length = udl->urbs.size; /* reset to actual */
 
        spin_lock_irqsave(&udl->urbs.lock, flags);
-       list_add_tail(&unode->entry, &udl->urbs.list);
+       list_move(&unode->entry, &udl->urbs.list);
        udl->urbs.available++;
        spin_unlock_irqrestore(&udl->urbs.lock, flags);
 
-#if 0
-       /*
-        * When using fb_defio, we deadlock if up() is called
-        * while another is waiting. So queue to another process.
-        */
-       if (fb_defio)
-               schedule_delayed_work(&unode->release_urb_work, 0);
-       else
-#endif
-               up(&udl->urbs.limit_sem);
+       wake_up(&udl->urbs.sleep);
 }
 
 static void udl_free_urb_list(struct drm_device *dev)
 {
        struct udl_device *udl = to_udl(dev);
        int count = udl->urbs.count;
-       struct list_head *node;
        struct urb_node *unode;
        struct urb *urb;
 
@@ -174,23 +153,15 @@ static void udl_free_urb_list(struct drm_device *dev)
 
        /* keep waiting and freeing, until we've got 'em all */
        while (count--) {
-               down(&udl->urbs.limit_sem);
-
-               spin_lock_irq(&udl->urbs.lock);
-
-               node = udl->urbs.list.next; /* have reserved one with sem */
-               list_del_init(node);
-
-               spin_unlock_irq(&udl->urbs.lock);
-
-               unode = list_entry(node, struct urb_node, entry);
-               urb = unode->urb;
-
+               urb = udl_get_urb_timeout(dev, MAX_SCHEDULE_TIMEOUT);
+               if (WARN_ON(!urb))
+                       break;
+               unode = urb->context;
                /* Free each separately allocated piece */
                usb_free_coherent(urb->dev, udl->urbs.size,
                                  urb->transfer_buffer, urb->transfer_dma);
                usb_free_urb(urb);
-               kfree(node);
+               kfree(unode);
        }
        udl->urbs.count = 0;
 }
@@ -209,8 +180,9 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size)
 retry:
        udl->urbs.size = size;
        INIT_LIST_HEAD(&udl->urbs.list);
+       INIT_LIST_HEAD(&udl->urbs.in_flight);
 
-       sema_init(&udl->urbs.limit_sem, 0);
+       init_waitqueue_head(&udl->urbs.sleep);
        udl->urbs.count = 0;
        udl->urbs.available = 0;
 
@@ -220,9 +192,6 @@ retry:
                        break;
                unode->dev = udl;
 
-               INIT_DELAYED_WORK(&unode->release_urb_work,
-                         udl_release_urb_work);
-
                urb = usb_alloc_urb(0, GFP_KERNEL);
                if (!urb) {
                        kfree(unode);
@@ -250,7 +219,6 @@ retry:
 
                list_add_tail(&unode->entry, &udl->urbs.list);
 
-               up(&udl->urbs.limit_sem);
                udl->urbs.count++;
                udl->urbs.available++;
        }
@@ -260,36 +228,31 @@ retry:
        return udl->urbs.count;
 }
 
-struct urb *udl_get_urb(struct drm_device *dev)
+struct urb *udl_get_urb_timeout(struct drm_device *dev, long timeout)
 {
        struct udl_device *udl = to_udl(dev);
-       int ret = 0;
-       struct list_head *entry;
-       struct urb_node *unode;
-       struct urb *urb = NULL;
+       struct urb_node *unode = NULL;
 
-       /* Wait for an in-flight buffer to complete and get re-queued */
-       ret = down_timeout(&udl->urbs.limit_sem, GET_URB_TIMEOUT);
-       if (ret) {
-               DRM_INFO("wait for urb interrupted: %x available: %d\n",
-                      ret, udl->urbs.available);
-               goto error;
-       }
+       if (!udl->urbs.count)
+               return NULL;
 
+       /* Wait for an in-flight buffer to complete and get re-queued */
        spin_lock_irq(&udl->urbs.lock);
+       if (!wait_event_lock_irq_timeout(udl->urbs.sleep,
+                                        !list_empty(&udl->urbs.list),
+                                        udl->urbs.lock, timeout)) {
+               DRM_INFO("wait for urb interrupted: available: %d\n",
+                        udl->urbs.available);
+               goto unlock;
+       }
 
-       BUG_ON(list_empty(&udl->urbs.list)); /* reserved one with limit_sem */
-       entry = udl->urbs.list.next;
-       list_del_init(entry);
+       unode = list_first_entry(&udl->urbs.list, struct urb_node, entry);
+       list_move(&unode->entry, &udl->urbs.in_flight);
        udl->urbs.available--;
 
+unlock:
        spin_unlock_irq(&udl->urbs.lock);
-
-       unode = list_entry(entry, struct urb_node, entry);
-       urb = unode->urb;
-
-error:
-       return urb;
+       return unode ? unode->urb : NULL;
 }
 
 int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len)
@@ -297,7 +260,8 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len)
        struct udl_device *udl = to_udl(dev);
        int ret;
 
-       BUG_ON(len > udl->urbs.size);
+       if (WARN_ON(len > udl->urbs.size))
+               return -EINVAL;
 
        urb->transfer_buffer_length = len; /* set to actual payload len */
        ret = usb_submit_urb(urb, GFP_ATOMIC);
@@ -308,6 +272,40 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len)
        return ret;
 }
 
+/* wait until all pending URBs have been processed */
+int udl_sync_pending_urbs(struct drm_device *dev)
+{
+       struct udl_device *udl = to_udl(dev);
+       int ret = 0;
+
+       spin_lock_irq(&udl->urbs.lock);
+       /* 2 seconds as a sane timeout */
+       if (!wait_event_lock_irq_timeout(udl->urbs.sleep,
+                                        list_empty(&udl->urbs.in_flight),
+                                        udl->urbs.lock,
+                                        msecs_to_jiffies(2000)))
+               ret = -ETIMEDOUT;
+       spin_unlock_irq(&udl->urbs.lock);
+       return ret;
+}
+
+/* kill pending URBs */
+void udl_kill_pending_urbs(struct drm_device *dev)
+{
+       struct udl_device *udl = to_udl(dev);
+       struct urb_node *unode;
+
+       spin_lock_irq(&udl->urbs.lock);
+       while (!list_empty(&udl->urbs.in_flight)) {
+               unode = list_first_entry(&udl->urbs.in_flight,
+                                        struct urb_node, entry);
+               spin_unlock_irq(&udl->urbs.lock);
+               usb_kill_urb(unode->urb);
+               spin_lock_irq(&udl->urbs.lock);
+       }
+       spin_unlock_irq(&udl->urbs.lock);
+}
+
 int udl_init(struct udl_device *udl)
 {
        struct drm_device *dev = &udl->drm;
@@ -356,6 +354,7 @@ int udl_drop_usb(struct drm_device *dev)
 {
        struct udl_device *udl = to_udl(dev);
 
+       udl_kill_pending_urbs(dev);
        udl_free_urb_list(dev);
        put_device(udl->dmadev);
        udl->dmadev = NULL;
index e67c40a48fb46cd2ed6d71625667861ecd03cfd5..169110d8fc2e193b235d8b4cc2ee5c4849d49ca0 100644 (file)
@@ -397,6 +397,8 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
        struct urb *urb;
        char *buf;
 
+       udl_kill_pending_urbs(dev);
+
        urb = udl_get_urb(dev);
        if (!urb)
                return;
@@ -408,6 +410,8 @@ udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
        buf = udl_dummy_render(buf);
 
        udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);
+
+       udl_sync_pending_urbs(dev);
 }
 
 static void
index 971927669d6b80eaf1d1815ff8ab85b675596828..176ef2a6a73138b793add72ed3490500f73a437c 100644 (file)
@@ -220,7 +220,8 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr,
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
 
-       BUG_ON(!(log_bpp == 1 || log_bpp == 2));
+       if (WARN_ON(!(log_bpp == 1 || log_bpp == 2)))
+               return -EINVAL;
 
        line_start = (u8 *) (front + byte_offset);
        next_pixel = line_start;
index 8c7f910daa28c1cb486b848cd734baa78c2e17db..e8c975b8158592233e7e4972fac71eac728a9d6d 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/reset.h>
 
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_managed.h>
 #include <uapi/drm/v3d_drm.h>
index 725a252e837bf566a7121ba1ca437397ad82c12d..b8980440d137f26e34a5513c2c62f9fa7b2e3ccf 100644 (file)
@@ -313,7 +313,7 @@ v3d_lookup_bos(struct drm_device *dev,
        }
 
        job->bo = kvmalloc_array(job->bo_count,
-                                sizeof(struct drm_gem_cma_object *),
+                                sizeof(struct drm_gem_dma_object *),
                                 GFP_KERNEL | __GFP_ZERO);
        if (!job->bo) {
                DRM_DEBUG("Failed to allocate validated BO pointers\n");
@@ -1092,7 +1092,7 @@ v3d_gem_init(struct drm_device *dev)
        if (!v3d->pt) {
                drm_mm_takedown(&v3d->mm);
                dev_err(v3d->drm.dev,
-                       "Failed to allocate page tables. Please ensure you have CMA enabled.\n");
+                       "Failed to allocate page tables. Please ensure you have DMA enabled.\n");
                return -ENOMEM;
        }
 
index f6a88abccc7d904eda3bc21106c9f5f6bc301ac6..48aaaa972c490294a8c4e835aebf27afd93de8d2 100644 (file)
@@ -95,7 +95,7 @@ struct v3d_perfmon *v3d_perfmon_find(struct v3d_file_priv *v3d_priv, int id)
 void v3d_perfmon_open_file(struct v3d_file_priv *v3d_priv)
 {
        mutex_init(&v3d_priv->perfmon.lock);
-       idr_init(&v3d_priv->perfmon.idr);
+       idr_init_base(&v3d_priv->perfmon.idr, 1);
 }
 
 static int v3d_perfmon_idr_del(int id, void *elem, void *data)
index fa0d73ce07bc5d19f78d948ba23d933007f08bf7..341edd982cb3be10054266989d3728d897e3e3a3 100644 (file)
@@ -269,8 +269,8 @@ static int vbox_primary_atomic_check(struct drm_plane *plane,
        }
 
        return drm_atomic_helper_check_plane_state(new_state, crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   false, true);
 }
 
@@ -351,8 +351,8 @@ static int vbox_cursor_atomic_check(struct drm_plane *plane,
        }
 
        ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        if (ret)
                return ret;
@@ -477,7 +477,7 @@ static const struct drm_plane_helper_funcs vbox_cursor_helper_funcs = {
 static const struct drm_plane_funcs vbox_cursor_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        DRM_GEM_SHADOW_PLANE_FUNCS,
 };
 
@@ -496,7 +496,7 @@ static const struct drm_plane_helper_funcs vbox_primary_helper_funcs = {
 static const struct drm_plane_funcs vbox_primary_plane_funcs = {
        .update_plane   = drm_atomic_helper_update_plane,
        .disable_plane  = drm_atomic_helper_disable_plane,
-       .destroy        = drm_primary_helper_destroy,
+       .destroy        = drm_plane_helper_destroy,
        .reset          = drm_atomic_helper_plane_reset,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
index 061be9a6619df4de18bfc257d31640be1bb48a36..246305d17a52a3c756f3c3d6212bccae20f4e6cb 100644 (file)
@@ -8,10 +8,11 @@ config DRM_VC4
        depends on DRM
        depends on SND && SND_SOC
        depends on COMMON_CLK
+       depends on PM
        select DRM_DISPLAY_HDMI_HELPER
        select DRM_DISPLAY_HELPER
        select DRM_KMS_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_PANEL_BRIDGE
        select SND_PCM
        select SND_PCM_ELD
index 0846d56f74f2d4ecc05444e5fe615919ab3f5b14..231add8b8e127c59dd1a4c39302022bf85927e31 100644 (file)
@@ -8,10 +8,10 @@
  *
  * The VC4 GPU architecture (both scanout and rendering) has direct
  * access to system memory with no MMU in between.  To support it, we
- * use the GEM CMA helper functions to allocate contiguous ranges of
+ * use the GEM DMA helper functions to allocate contiguous ranges of
  * physical memory for our BOs.
  *
- * Since the CMA allocator is very slow, we keep a cache of recently
+ * Since the DMA allocator is very slow, we keep a cache of recently
  * freed BOs around so that the kernel's allocation of objects for 3D
  * rendering can return quickly.
  */
@@ -179,7 +179,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
                bo->validated_shader = NULL;
        }
 
-       drm_gem_cma_free(&bo->base);
+       drm_gem_dma_free(&bo->base);
 }
 
 static void vc4_bo_remove_from_cache(struct vc4_bo *bo)
@@ -303,7 +303,7 @@ static void vc4_bo_purge(struct drm_gem_object *obj)
 
        drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping);
 
-       dma_free_wc(dev->dev, obj->size, bo->base.vaddr, bo->base.paddr);
+       dma_free_wc(dev->dev, obj->size, bo->base.vaddr, bo->base.dma_addr);
        bo->base.vaddr = NULL;
        bo->madv = __VC4_MADV_PURGED;
 }
@@ -387,13 +387,14 @@ out:
  * @dev: DRM device
  * @size: Size in bytes of the memory the object will reference
  *
- * This lets the CMA helpers allocate object structs for us, and keep
+ * This lets the DMA helpers allocate object structs for us, and keep
  * our BO stats correct.
  */
 struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct vc4_bo *bo;
+       int ret;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
                return ERR_PTR(-ENODEV);
@@ -404,7 +405,11 @@ struct drm_gem_object *vc4_create_object(struct drm_device *dev, size_t size)
 
        bo->madv = VC4_MADV_WILLNEED;
        refcount_set(&bo->usecnt, 0);
-       mutex_init(&bo->madv_lock);
+
+       ret = drmm_mutex_init(dev, &bo->madv_lock);
+       if (ret)
+               return ERR_PTR(ret);
+
        mutex_lock(&vc4->bo_lock);
        bo->label = VC4_BO_TYPE_KERNEL;
        vc4->bo_labels[VC4_BO_TYPE_KERNEL].num_allocated++;
@@ -421,7 +426,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
 {
        size_t size = roundup(unaligned_size, PAGE_SIZE);
        struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct drm_gem_cma_object *cma_obj;
+       struct drm_gem_dma_object *dma_obj;
        struct vc4_bo *bo;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
@@ -438,39 +443,39 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
                return bo;
        }
 
-       cma_obj = drm_gem_cma_create(dev, size);
-       if (IS_ERR(cma_obj)) {
+       dma_obj = drm_gem_dma_create(dev, size);
+       if (IS_ERR(dma_obj)) {
                /*
-                * If we've run out of CMA memory, kill the cache of
-                * CMA allocations we've got laying around and try again.
+                * If we've run out of DMA memory, kill the cache of
+                * DMA allocations we've got laying around and try again.
                 */
                vc4_bo_cache_purge(dev);
-               cma_obj = drm_gem_cma_create(dev, size);
+               dma_obj = drm_gem_dma_create(dev, size);
        }
 
-       if (IS_ERR(cma_obj)) {
+       if (IS_ERR(dma_obj)) {
                /*
-                * Still not enough CMA memory, purge the userspace BO
+                * Still not enough DMA memory, purge the userspace BO
                 * cache and retry.
                 * This is sub-optimal since we purge the whole userspace
                 * BO cache which forces user that want to re-use the BO to
                 * restore its initial content.
                 * Ideally, we should purge entries one by one and retry
-                * after each to see if CMA allocation succeeds. Or even
+                * after each to see if DMA allocation succeeds. Or even
                 * better, try to find an entry with at least the same
                 * size.
                 */
                vc4_bo_userspace_cache_purge(dev);
-               cma_obj = drm_gem_cma_create(dev, size);
+               dma_obj = drm_gem_dma_create(dev, size);
        }
 
-       if (IS_ERR(cma_obj)) {
+       if (IS_ERR(dma_obj)) {
                struct drm_printer p = drm_info_printer(vc4->base.dev);
-               DRM_ERROR("Failed to allocate from CMA:\n");
+               DRM_ERROR("Failed to allocate from GEM DMA helper:\n");
                vc4_bo_stats_print(&p, vc4);
                return ERR_PTR(-ENOMEM);
        }
-       bo = to_vc4_bo(&cma_obj->base);
+       bo = to_vc4_bo(&dma_obj->base);
 
        /* By default, BOs do not support the MADV ioctl. This will be enabled
         * only on BOs that are exposed to userspace (V3D, V3D_SHADER and DUMB
@@ -479,7 +484,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t unaligned_size,
        bo->madv = __VC4_MADV_NOTSUPP;
 
        mutex_lock(&vc4->bo_lock);
-       vc4_bo_set_label(&cma_obj->base, type);
+       vc4_bo_set_label(&dma_obj->base, type);
        mutex_unlock(&vc4->bo_lock);
 
        return bo;
@@ -564,7 +569,7 @@ static void vc4_free_object(struct drm_gem_object *gem_bo)
                goto out;
        }
 
-       /* If this object was partially constructed but CMA allocation
+       /* If this object was partially constructed but DMA allocation
         * had failed, just free it. Can also happen when the BO has been
         * purged.
         */
@@ -742,7 +747,7 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
                return -EINVAL;
        }
 
-       return drm_gem_cma_mmap(&bo->base, vma);
+       return drm_gem_dma_mmap(&bo->base, vma);
 }
 
 static const struct vm_operations_struct vc4_vm_ops = {
@@ -754,8 +759,8 @@ static const struct vm_operations_struct vc4_vm_ops = {
 static const struct drm_gem_object_funcs vc4_gem_object_funcs = {
        .free = vc4_free_object,
        .export = vc4_prime_export,
-       .get_sg_table = drm_gem_cma_object_get_sg_table,
-       .vmap = drm_gem_cma_object_vmap,
+       .get_sg_table = drm_gem_dma_object_get_sg_table,
+       .vmap = drm_gem_dma_object_vmap,
        .mmap = vc4_gem_object_mmap,
        .vm_ops = &vc4_vm_ops,
 };
@@ -984,10 +989,28 @@ int vc4_get_tiling_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+int vc4_bo_debugfs_init(struct drm_minor *minor)
+{
+       struct drm_device *drm = minor->dev;
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
+       int ret;
+
+       if (!vc4->v3d)
+               return -ENODEV;
+
+       ret = vc4_debugfs_add_file(minor, "bo_stats",
+                                  vc4_bo_stats_debugfs, NULL);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static void vc4_bo_cache_destroy(struct drm_device *dev, void *unused);
 int vc4_bo_cache_init(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
+       int ret;
        int i;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
@@ -1007,9 +1030,11 @@ int vc4_bo_cache_init(struct drm_device *dev)
        for (i = 0; i < VC4_BO_TYPE_COUNT; i++)
                vc4->bo_labels[i].name = bo_type_names[i];
 
-       mutex_init(&vc4->bo_lock);
-
-       vc4_debugfs_add_file(dev, "bo_stats", vc4_bo_stats_debugfs, NULL);
+       ret = drmm_mutex_init(dev, &vc4->bo_lock);
+       if (ret) {
+               kfree(vc4->bo_labels);
+               return ret;
+       }
 
        INIT_LIST_HEAD(&vc4->bo_cache.time_list);
 
index 029be98660b3043d794d582202f9711bb62b1b13..2def6e2ad6f075940f7850cf103a501a72d9054b 100644 (file)
@@ -37,7 +37,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_print.h>
 #include <drm/drm_probe_helper.h>
@@ -206,11 +206,6 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
        return ret;
 }
 
-void vc4_crtc_destroy(struct drm_crtc *crtc)
-{
-       drm_crtc_cleanup(crtc);
-}
-
 static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
 {
        const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
@@ -544,6 +539,20 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc)
        return 0;
 }
 
+void vc4_crtc_send_vblank(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       unsigned long flags;
+
+       if (!crtc->state || !crtc->state->event)
+               return;
+
+       spin_lock_irqsave(&dev->event_lock, flags);
+       drm_crtc_send_vblank_event(crtc, crtc->state->event);
+       crtc->state->event = NULL;
+       spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
 static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
                                    struct drm_atomic_state *state)
 {
@@ -567,14 +576,7 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc,
         * Make sure we issue a vblank event after disabling the CRTC if
         * someone was waiting it.
         */
-       if (crtc->state->event) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&dev->event_lock, flags);
-               drm_crtc_send_vblank_event(crtc, crtc->state->event);
-               crtc->state->event = NULL;
-               spin_unlock_irqrestore(&dev->event_lock, flags);
-       }
+       vc4_crtc_send_vblank(crtc);
 }
 
 static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -821,9 +823,9 @@ static void vc4_async_page_flip_seqno_complete(struct vc4_seqno_cb *cb)
        struct vc4_bo *bo = NULL;
 
        if (flip_state->old_fb) {
-               struct drm_gem_cma_object *cma_bo =
-                       drm_fb_cma_get_gem_obj(flip_state->old_fb, 0);
-               bo = to_vc4_bo(&cma_bo->base);
+               struct drm_gem_dma_object *dma_bo =
+                       drm_fb_dma_get_gem_obj(flip_state->old_fb, 0);
+               bo = to_vc4_bo(&dma_bo->base);
        }
 
        vc4_async_page_flip_complete(flip_state);
@@ -855,19 +857,19 @@ static int vc4_async_set_fence_cb(struct drm_device *dev,
                                  struct vc4_async_flip_state *flip_state)
 {
        struct drm_framebuffer *fb = flip_state->fb;
-       struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0);
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct dma_fence *fence;
        int ret;
 
        if (!vc4->is_vc5) {
-               struct vc4_bo *bo = to_vc4_bo(&cma_bo->base);
+               struct vc4_bo *bo = to_vc4_bo(&dma_bo->base);
 
                return vc4_queue_seqno_cb(dev, &flip_state->cb.seqno, bo->seqno,
                                          vc4_async_page_flip_seqno_complete);
        }
 
-       ret = dma_resv_get_singleton(cma_bo->base.resv, DMA_RESV_USAGE_READ, &fence);
+       ret = dma_resv_get_singleton(dma_bo->base.resv, DMA_RESV_USAGE_READ, &fence);
        if (ret)
                return ret;
 
@@ -943,8 +945,8 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct drm_gem_cma_object *cma_bo = drm_fb_cma_get_gem_obj(fb, 0);
-       struct vc4_bo *bo = to_vc4_bo(&cma_bo->base);
+       struct drm_gem_dma_object *dma_bo = drm_fb_dma_get_gem_obj(fb, 0);
+       struct vc4_bo *bo = to_vc4_bo(&dma_bo->base);
        int ret;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
@@ -1050,9 +1052,23 @@ void vc4_crtc_reset(struct drm_crtc *crtc)
        __drm_atomic_helper_crtc_reset(crtc, &vc4_crtc_state->base);
 }
 
+int vc4_crtc_late_register(struct drm_crtc *crtc)
+{
+       struct drm_device *drm = crtc->dev;
+       struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+       const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc);
+       int ret;
+
+       ret = vc4_debugfs_add_regset32(drm->primary, crtc_data->debugfs_name,
+                                      &vc4_crtc->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static const struct drm_crtc_funcs vc4_crtc_funcs = {
        .set_config = drm_atomic_helper_set_config,
-       .destroy = vc4_crtc_destroy,
        .page_flip = vc4_page_flip,
        .set_property = NULL,
        .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
@@ -1063,6 +1079,7 @@ static const struct drm_crtc_funcs vc4_crtc_funcs = {
        .enable_vblank = vc4_enable_vblank,
        .disable_vblank = vc4_disable_vblank,
        .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp,
+       .late_register = vc4_crtc_late_register,
 };
 
 static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
@@ -1077,10 +1094,10 @@ static const struct drm_crtc_helper_funcs vc4_crtc_helper_funcs = {
 
 static const struct vc4_pv_data bcm2835_pv0_data = {
        .base = {
+               .debugfs_name = "crtc0_regs",
                .hvs_available_channels = BIT(0),
                .hvs_output = 0,
        },
-       .debugfs_name = "crtc0_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1091,10 +1108,10 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
 
 static const struct vc4_pv_data bcm2835_pv1_data = {
        .base = {
+               .debugfs_name = "crtc1_regs",
                .hvs_available_channels = BIT(2),
                .hvs_output = 2,
        },
-       .debugfs_name = "crtc1_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1105,10 +1122,10 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
 
 static const struct vc4_pv_data bcm2835_pv2_data = {
        .base = {
+               .debugfs_name = "crtc2_regs",
                .hvs_available_channels = BIT(1),
                .hvs_output = 1,
        },
-       .debugfs_name = "crtc2_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1119,10 +1136,10 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
 
 static const struct vc4_pv_data bcm2711_pv0_data = {
        .base = {
+               .debugfs_name = "crtc0_regs",
                .hvs_available_channels = BIT(0),
                .hvs_output = 0,
        },
-       .debugfs_name = "crtc0_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1133,10 +1150,10 @@ static const struct vc4_pv_data bcm2711_pv0_data = {
 
 static const struct vc4_pv_data bcm2711_pv1_data = {
        .base = {
+               .debugfs_name = "crtc1_regs",
                .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
                .hvs_output = 3,
        },
-       .debugfs_name = "crtc1_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1147,10 +1164,10 @@ static const struct vc4_pv_data bcm2711_pv1_data = {
 
 static const struct vc4_pv_data bcm2711_pv2_data = {
        .base = {
+               .debugfs_name = "crtc2_regs",
                .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
                .hvs_output = 4,
        },
-       .debugfs_name = "crtc2_regs",
        .fifo_depth = 256,
        .pixels_per_clock = 2,
        .encoder_types = {
@@ -1160,10 +1177,10 @@ static const struct vc4_pv_data bcm2711_pv2_data = {
 
 static const struct vc4_pv_data bcm2711_pv3_data = {
        .base = {
+               .debugfs_name = "crtc3_regs",
                .hvs_available_channels = BIT(1),
                .hvs_output = 1,
        },
-       .debugfs_name = "crtc3_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 1,
        .encoder_types = {
@@ -1173,10 +1190,10 @@ static const struct vc4_pv_data bcm2711_pv3_data = {
 
 static const struct vc4_pv_data bcm2711_pv4_data = {
        .base = {
+               .debugfs_name = "crtc4_regs",
                .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
                .hvs_output = 5,
        },
-       .debugfs_name = "crtc4_regs",
        .fifo_depth = 64,
        .pixels_per_clock = 2,
        .encoder_types = {
@@ -1230,6 +1247,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
        struct drm_crtc *crtc = &vc4_crtc->base;
        struct drm_plane *primary_plane;
        unsigned int i;
+       int ret;
 
        /* For now, we create just the primary and the legacy cursor
         * planes.  We should be able to stack more planes on easily,
@@ -1237,15 +1255,18 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
         * requirement of the plane configuration, and reject ones
         * that will take too much.
         */
-       primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
+       primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
        if (IS_ERR(primary_plane)) {
                dev_err(drm->dev, "failed to construct primary plane\n");
                return PTR_ERR(primary_plane);
        }
 
        spin_lock_init(&vc4_crtc->irq_lock);
-       drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
-                                 crtc_funcs, NULL);
+       ret = drmm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
+                                        crtc_funcs, NULL);
+       if (ret)
+               return ret;
+
        drm_crtc_helper_add(crtc, crtc_helper_funcs);
 
        if (!vc4->is_vc5) {
@@ -1275,10 +1296,9 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
        const struct vc4_pv_data *pv_data;
        struct vc4_crtc *vc4_crtc;
        struct drm_crtc *crtc;
-       struct drm_plane *destroy_plane, *temp;
        int ret;
 
-       vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
+       vc4_crtc = drmm_kzalloc(drm, sizeof(*vc4_crtc), GFP_KERNEL);
        if (!vc4_crtc)
                return -ENOMEM;
        crtc = &vc4_crtc->base;
@@ -1310,23 +1330,11 @@ static int vc4_crtc_bind(struct device *dev, struct device *master, void *data)
                               IRQF_SHARED,
                               "vc4 crtc", vc4_crtc);
        if (ret)
-               goto err_destroy_planes;
+               return ret;
 
        platform_set_drvdata(pdev, vc4_crtc);
 
-       vc4_debugfs_add_regset32(drm, pv_data->debugfs_name,
-                                &vc4_crtc->regset);
-
        return 0;
-
-err_destroy_planes:
-       list_for_each_entry_safe(destroy_plane, temp,
-                                &drm->mode_config.plane_list, head) {
-               if (destroy_plane->possible_crtcs == drm_crtc_mask(crtc))
-                   destroy_plane->funcs->destroy(destroy_plane);
-       }
-
-       return ret;
 }
 
 static void vc4_crtc_unbind(struct device *dev, struct device *master,
@@ -1335,8 +1343,6 @@ static void vc4_crtc_unbind(struct device *dev, struct device *master,
        struct platform_device *pdev = to_platform_device(dev);
        struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
 
-       vc4_crtc_destroy(&vc4_crtc->base);
-
        CRTC_WRITE(PV_INTEN, 0);
 
        platform_set_drvdata(pdev, NULL);
index ba2d8ea562af9031a7bdcc285dbb1e779992036e..19cda4f91a822b3cf9394fdc0ac30573b4e69f1c 100644 (file)
@@ -3,6 +3,8 @@
  *  Copyright Â© 2014 Broadcom
  */
 
+#include <drm/drm_drv.h>
+
 #include <linux/seq_file.h>
 #include <linux/circ_buf.h>
 #include <linux/ctype.h>
 #include "vc4_drv.h"
 #include "vc4_regs.h"
 
-struct vc4_debugfs_info_entry {
-       struct list_head link;
-       struct drm_info_list info;
-};
-
 /*
  * Called at drm_dev_register() time on each of the minors registered
  * by the DRM device, to attach the debugfs files.
@@ -25,62 +22,59 @@ void
 vc4_debugfs_init(struct drm_minor *minor)
 {
        struct vc4_dev *vc4 = to_vc4_dev(minor->dev);
-       struct vc4_debugfs_info_entry *entry;
+       struct drm_device *drm = &vc4->base;
 
-       if (!of_device_is_compatible(vc4->hvs->pdev->dev.of_node,
-                                    "brcm,bcm2711-vc5"))
-               debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR,
-                                   minor->debugfs_root, &vc4->load_tracker_enabled);
+       drm_WARN_ON(drm, vc4_hvs_debugfs_init(minor));
 
-       list_for_each_entry(entry, &vc4->debugfs_list, link) {
-               drm_debugfs_create_files(&entry->info, 1,
-                                        minor->debugfs_root, minor);
+       if (vc4->v3d) {
+               drm_WARN_ON(drm, vc4_bo_debugfs_init(minor));
+               drm_WARN_ON(drm, vc4_v3d_debugfs_init(minor));
        }
 }
 
 static int vc4_debugfs_regset32(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *)m->private;
+       struct drm_device *drm = node->minor->dev;
        struct debugfs_regset32 *regset = node->info_ent->data;
        struct drm_printer p = drm_seq_file_printer(m);
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return -ENODEV;
 
        drm_print_regset32(&p, regset);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
-/*
- * Registers a debugfs file with a callback function for a vc4 component.
- *
- * This is like drm_debugfs_create_files(), but that can only be
- * called a given DRM minor, while the various VC4 components want to
- * register their debugfs files during the component bind process.  We
- * track the request and delay it to be called on each minor during
- * vc4_debugfs_init().
- */
-void vc4_debugfs_add_file(struct drm_device *dev,
-                         const char *name,
-                         int (*show)(struct seq_file*, void*),
-                         void *data)
+int vc4_debugfs_add_file(struct drm_minor *minor,
+                        const char *name,
+                        int (*show)(struct seq_file*, void*),
+                        void *data)
 {
-       struct vc4_dev *vc4 = to_vc4_dev(dev);
+       struct drm_device *dev = minor->dev;
+       struct dentry *root = minor->debugfs_root;
+       struct drm_info_list *file;
 
-       struct vc4_debugfs_info_entry *entry =
-               devm_kzalloc(dev->dev, sizeof(*entry), GFP_KERNEL);
+       file = drmm_kzalloc(dev, sizeof(*file), GFP_KERNEL);
+       if (!file)
+               return -ENOMEM;
 
-       if (!entry)
-               return;
+       file->name = name;
+       file->show = show;
+       file->data = data;
 
-       entry->info.name = name;
-       entry->info.show = show;
-       entry->info.data = data;
+       drm_debugfs_create_files(file, 1, root, minor);
 
-       list_add(&entry->link, &vc4->debugfs_list);
+       return 0;
 }
 
-void vc4_debugfs_add_regset32(struct drm_device *drm,
-                             const char *name,
-                             struct debugfs_regset32 *regset)
+int vc4_debugfs_add_regset32(struct drm_minor *minor,
+                            const char *name,
+                            struct debugfs_regset32 *regset)
 {
-       vc4_debugfs_add_file(drm, name, vc4_debugfs_regset32, regset);
+       return vc4_debugfs_add_file(minor, name, vc4_debugfs_regset32, regset);
 }
index ef5e3921062c5953924f9bd5b3a1230539797832..1f8f44b7b5a5f161703bb6e3f03aed775069a19a 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
@@ -84,9 +85,9 @@
 
 /* General DPI hardware state. */
 struct vc4_dpi {
-       struct platform_device *pdev;
+       struct vc4_encoder encoder;
 
-       struct drm_encoder *encoder;
+       struct platform_device *pdev;
 
        void __iomem *regs;
 
@@ -96,21 +97,15 @@ struct vc4_dpi {
        struct debugfs_regset32 regset;
 };
 
-#define DPI_READ(offset) readl(dpi->regs + (offset))
-#define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset))
-
-/* VC4 DPI encoder KMS struct */
-struct vc4_dpi_encoder {
-       struct vc4_encoder base;
-       struct vc4_dpi *dpi;
-};
-
-static inline struct vc4_dpi_encoder *
-to_vc4_dpi_encoder(struct drm_encoder *encoder)
+static inline struct vc4_dpi *
+to_vc4_dpi(struct drm_encoder *encoder)
 {
-       return container_of(encoder, struct vc4_dpi_encoder, base.base);
+       return container_of(encoder, struct vc4_dpi, encoder.base);
 }
 
+#define DPI_READ(offset) readl(dpi->regs + (offset))
+#define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset))
+
 static const struct debugfs_reg32 dpi_regs[] = {
        VC4_REG32(DPI_C),
        VC4_REG32(DPI_ID),
@@ -118,21 +113,27 @@ static const struct debugfs_reg32 dpi_regs[] = {
 
 static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
 {
-       struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
-       struct vc4_dpi *dpi = vc4_encoder->dpi;
+       struct drm_device *dev = encoder->dev;
+       struct vc4_dpi *dpi = to_vc4_dpi(encoder);
+       int idx;
+
+       if (!drm_dev_enter(dev, &idx))
+               return;
 
        clk_disable_unprepare(dpi->pixel_clock);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
 {
        struct drm_device *dev = encoder->dev;
        struct drm_display_mode *mode = &encoder->crtc->mode;
-       struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
-       struct vc4_dpi *dpi = vc4_encoder->dpi;
+       struct vc4_dpi *dpi = to_vc4_dpi(encoder);
        struct drm_connector_list_iter conn_iter;
        struct drm_connector *connector = NULL, *connector_scan;
        u32 dpi_c = DPI_ENABLE;
+       int idx;
        int ret;
 
        /* Look up the connector attached to DPI so we can get the
@@ -212,6 +213,9 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
                        dpi_c |= DPI_VSYNC_DISABLE;
        }
 
+       if (!drm_dev_enter(dev, &idx))
+               return;
+
        DPI_WRITE(DPI_C, dpi_c);
 
        ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000);
@@ -221,6 +225,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
        ret = clk_prepare_enable(dpi->pixel_clock);
        if (ret)
                DRM_ERROR("Failed to set clock rate: %d\n", ret);
+
+       drm_dev_exit(idx);
 }
 
 static enum drm_mode_status vc4_dpi_encoder_mode_valid(struct drm_encoder *encoder,
@@ -238,6 +244,23 @@ static const struct drm_encoder_helper_funcs vc4_dpi_encoder_helper_funcs = {
        .mode_valid = vc4_dpi_encoder_mode_valid,
 };
 
+static int vc4_dpi_late_register(struct drm_encoder *encoder)
+{
+       struct drm_device *drm = encoder->dev;
+       struct vc4_dpi *dpi = to_vc4_dpi(encoder);
+       int ret;
+
+       ret = vc4_debugfs_add_regset32(drm->primary, "dpi_regs", &dpi->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct drm_encoder_funcs vc4_dpi_encoder_funcs = {
+       .late_register = vc4_dpi_late_register,
+};
+
 static const struct of_device_id vc4_dpi_dt_match[] = {
        { .compatible = "brcm,bcm2835-dpi", .data = NULL },
        {}
@@ -248,10 +271,11 @@ static const struct of_device_id vc4_dpi_dt_match[] = {
  */
 static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
 {
+       struct drm_device *drm = dpi->encoder.base.dev;
        struct device *dev = &dpi->pdev->dev;
        struct drm_bridge *bridge;
 
-       bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+       bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
        if (IS_ERR(bridge)) {
                /* If nothing was connected in the DT, that's not an
                 * error.
@@ -262,30 +286,28 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
                        return PTR_ERR(bridge);
        }
 
-       return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
+       return drm_bridge_attach(&dpi->encoder.base, bridge, NULL, 0);
+}
+
+static void vc4_dpi_disable_clock(void *ptr)
+{
+       struct vc4_dpi *dpi = ptr;
+
+       clk_disable_unprepare(dpi->core_clock);
 }
 
 static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_dpi *dpi;
-       struct vc4_dpi_encoder *vc4_dpi_encoder;
        int ret;
 
-       dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
+       dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL);
        if (!dpi)
                return -ENOMEM;
 
-       vc4_dpi_encoder = devm_kzalloc(dev, sizeof(*vc4_dpi_encoder),
-                                      GFP_KERNEL);
-       if (!vc4_dpi_encoder)
-               return -ENOMEM;
-       vc4_dpi_encoder->base.type = VC4_ENCODER_TYPE_DPI;
-       vc4_dpi_encoder->dpi = dpi;
-       dpi->encoder = &vc4_dpi_encoder->base.base;
-
+       dpi->encoder.type = VC4_ENCODER_TYPE_DPI;
        dpi->pdev = pdev;
        dpi->regs = vc4_ioremap_regs(pdev, 0);
        if (IS_ERR(dpi->regs))
@@ -307,6 +329,7 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
                        DRM_ERROR("Failed to get core clock: %d\n", ret);
                return ret;
        }
+
        dpi->pixel_clock = devm_clk_get(dev, "pixel");
        if (IS_ERR(dpi->pixel_clock)) {
                ret = PTR_ERR(dpi->pixel_clock);
@@ -316,49 +339,35 @@ static int vc4_dpi_bind(struct device *dev, struct device *master, void *data)
        }
 
        ret = clk_prepare_enable(dpi->core_clock);
-       if (ret)
+       if (ret) {
                DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+               return ret;
+       }
 
-       drm_simple_encoder_init(drm, dpi->encoder, DRM_MODE_ENCODER_DPI);
-       drm_encoder_helper_add(dpi->encoder, &vc4_dpi_encoder_helper_funcs);
+       ret = devm_add_action_or_reset(dev, vc4_dpi_disable_clock, dpi);
+       if (ret)
+               return ret;
 
-       ret = vc4_dpi_init_bridge(dpi);
+       ret = drmm_encoder_init(drm, &dpi->encoder.base,
+                               &vc4_dpi_encoder_funcs,
+                               DRM_MODE_ENCODER_DPI,
+                               NULL);
        if (ret)
-               goto err_destroy_encoder;
+               return ret;
 
-       dev_set_drvdata(dev, dpi);
+       drm_encoder_helper_add(&dpi->encoder.base, &vc4_dpi_encoder_helper_funcs);
 
-       vc4->dpi = dpi;
+       ret = vc4_dpi_init_bridge(dpi);
+       if (ret)
+               return ret;
 
-       vc4_debugfs_add_regset32(drm, "dpi_regs", &dpi->regset);
+       dev_set_drvdata(dev, dpi);
 
        return 0;
-
-err_destroy_encoder:
-       drm_encoder_cleanup(dpi->encoder);
-       clk_disable_unprepare(dpi->core_clock);
-       return ret;
-}
-
-static void vc4_dpi_unbind(struct device *dev, struct device *master,
-                          void *data)
-{
-       struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
-       struct vc4_dpi *dpi = dev_get_drvdata(dev);
-
-       drm_of_panel_bridge_remove(dev->of_node, 0, 0);
-
-       drm_encoder_cleanup(dpi->encoder);
-
-       clk_disable_unprepare(dpi->core_clock);
-
-       vc4->dpi = NULL;
 }
 
 static const struct component_ops vc4_dpi_ops = {
        .bind   = vc4_dpi_bind,
-       .unbind = vc4_dpi_unbind,
 };
 
 static int vc4_dpi_dev_probe(struct platform_device *pdev)
index 292d1b6a01b6fcb54f453ca18c0efbb2f3773ec7..ffbbb454c9e878e71be0df45dac2b4c928c89059 100644 (file)
@@ -33,7 +33,6 @@
 #include <drm/drm_aperture.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_drv.h>
-#include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_vblank.h>
 
@@ -86,7 +85,7 @@ static int vc5_dumb_create(struct drm_file *file_priv,
        if (ret)
                return ret;
 
-       return drm_gem_cma_dumb_create_internal(file_priv, dev, args);
+       return drm_gem_dma_dumb_create_internal(file_priv, dev, args);
 }
 
 static int vc4_get_param_ioctl(struct drm_device *dev, void *data,
@@ -212,7 +211,7 @@ static const struct drm_driver vc4_drm_driver = {
 
        .gem_create_object = vc4_create_object,
 
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc4_bo_dumb_create),
 
        .ioctls = vc4_drm_ioctls,
        .num_ioctls = ARRAY_SIZE(vc4_drm_ioctls),
@@ -235,7 +234,7 @@ static const struct drm_driver vc5_drm_driver = {
        .debugfs_init = vc4_debugfs_init,
 #endif
 
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(vc5_dumb_create),
 
        .fops = &vc4_drm_fops,
 
@@ -267,6 +266,13 @@ static void vc4_match_add_drivers(struct device *dev,
        }
 }
 
+static void vc4_component_unbind_all(void *ptr)
+{
+       struct vc4_dev *vc4 = ptr;
+
+       component_unbind_all(vc4->dev, &vc4->base);
+}
+
 static const struct of_device_id vc4_dma_range_matches[] = {
        { .compatible = "brcm,bcm2711-hvs" },
        { .compatible = "brcm,bcm2835-hvs" },
@@ -310,13 +316,16 @@ static int vc4_drm_bind(struct device *dev)
        if (IS_ERR(vc4))
                return PTR_ERR(vc4);
        vc4->is_vc5 = is_vc5;
+       vc4->dev = dev;
 
        drm = &vc4->base;
        platform_set_drvdata(pdev, drm);
        INIT_LIST_HEAD(&vc4->debugfs_list);
 
        if (!is_vc5) {
-               mutex_init(&vc4->bin_bo_lock);
+               ret = drmm_mutex_init(drm, &vc4->bin_bo_lock);
+               if (ret)
+                       return ret;
 
                ret = vc4_bo_cache_init(drm);
                if (ret)
@@ -360,6 +369,10 @@ static int vc4_drm_bind(struct device *dev)
        if (ret)
                return ret;
 
+       ret = devm_add_action_or_reset(dev, vc4_component_unbind_all, vc4);
+       if (ret)
+               return ret;
+
        ret = vc4_plane_create_additional_planes(drm);
        if (ret)
                goto unbind_all;
@@ -380,8 +393,6 @@ static int vc4_drm_bind(struct device *dev)
        return 0;
 
 unbind_all:
-       component_unbind_all(dev, drm);
-
        return ret;
 }
 
@@ -389,8 +400,7 @@ static void vc4_drm_unbind(struct device *dev)
 {
        struct drm_device *drm = dev_get_drvdata(dev);
 
-       drm_dev_unregister(drm);
-
+       drm_dev_unplug(drm);
        drm_atomic_helper_shutdown(drm);
 }
 
index 1beb96b77b8c68e64fbbb7e219a16666747b7cea..418a8242691f26b2cf6952b56eec23c65e849ef5 100644 (file)
@@ -14,7 +14,7 @@
 #include <drm/drm_debugfs.h>
 #include <drm/drm_device.h>
 #include <drm/drm_encoder.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_modeset_lock.h>
@@ -76,6 +76,7 @@ struct vc4_perfmon {
 
 struct vc4_dev {
        struct drm_device base;
+       struct device *dev;
 
        bool is_vc5;
 
@@ -83,9 +84,6 @@ struct vc4_dev {
 
        struct vc4_hvs *hvs;
        struct vc4_v3d *v3d;
-       struct vc4_dpi *dpi;
-       struct vc4_vec *vec;
-       struct vc4_txp *txp;
 
        struct vc4_hang_state *hang_state;
 
@@ -241,7 +239,7 @@ to_vc4_dev(struct drm_device *dev)
 }
 
 struct vc4_bo {
-       struct drm_gem_cma_object base;
+       struct drm_gem_dma_object base;
 
        /* seqno of the last job to render using this BO. */
        uint64_t seqno;
@@ -290,7 +288,7 @@ struct vc4_bo {
 static inline struct vc4_bo *
 to_vc4_bo(struct drm_gem_object *bo)
 {
-       return container_of(to_drm_gem_cma_obj(bo), struct vc4_bo, base);
+       return container_of(to_drm_gem_dma_obj(bo), struct vc4_bo, base);
 }
 
 struct vc4_fence {
@@ -458,6 +456,8 @@ to_vc4_encoder(struct drm_encoder *encoder)
 }
 
 struct vc4_crtc_data {
+       const char *debugfs_name;
+
        /* Bitmask of channels (FIFOs) of the HVS that the output can source from */
        unsigned int hvs_available_channels;
 
@@ -475,8 +475,6 @@ struct vc4_pv_data {
        u8 pixels_per_clock;
 
        enum vc4_encoder_type encoder_types[4];
-       const char *debugfs_name;
-
 };
 
 struct vc4_crtc {
@@ -604,14 +602,14 @@ struct vc4_exec_info {
        /* This is the array of BOs that were looked up at the start of exec.
         * Command validation will use indices into this array.
         */
-       struct drm_gem_cma_object **bo;
+       struct drm_gem_dma_object **bo;
        uint32_t bo_count;
 
        /* List of BOs that are being written by the RCL.  Other than
         * the binner temporary storage, this is all the BOs written
         * by the job.
         */
-       struct drm_gem_cma_object *rcl_write_bo[4];
+       struct drm_gem_dma_object *rcl_write_bo[4];
        uint32_t rcl_write_bo_count;
 
        /* Pointers for our position in vc4->job_list */
@@ -630,7 +628,7 @@ struct vc4_exec_info {
        /* This is the BO where we store the validated command lists, shader
         * records, and uniforms.
         */
-       struct drm_gem_cma_object *exec_bo;
+       struct drm_gem_dma_object *exec_bo;
 
        /**
         * This tracks the per-shader-record state (packet 64) that
@@ -843,6 +841,7 @@ int vc4_bo_inc_usecnt(struct vc4_bo *bo);
 void vc4_bo_dec_usecnt(struct vc4_bo *bo);
 void vc4_bo_add_to_purgeable_pool(struct vc4_bo *bo);
 void vc4_bo_remove_from_purgeable_pool(struct vc4_bo *bo);
+int vc4_bo_debugfs_init(struct drm_minor *minor);
 
 /* vc4_crtc.c */
 extern struct platform_driver vc4_crtc_driver;
@@ -850,7 +849,6 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc);
 int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
                  const struct drm_crtc_funcs *crtc_funcs,
                  const struct drm_crtc_helper_funcs *crtc_helper_funcs);
-void vc4_crtc_destroy(struct drm_crtc *crtc);
 int vc4_page_flip(struct drm_crtc *crtc,
                  struct drm_framebuffer *fb,
                  struct drm_pending_vblank_event *event,
@@ -861,6 +859,8 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc,
                            struct drm_crtc_state *state);
 void vc4_crtc_reset(struct drm_crtc *crtc);
 void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
+void vc4_crtc_send_vblank(struct drm_crtc *crtc);
+int vc4_crtc_late_register(struct drm_crtc *crtc);
 void vc4_crtc_get_margins(struct drm_crtc_state *state,
                          unsigned int *left, unsigned int *right,
                          unsigned int *top, unsigned int *bottom);
@@ -868,25 +868,27 @@ void vc4_crtc_get_margins(struct drm_crtc_state *state,
 /* vc4_debugfs.c */
 void vc4_debugfs_init(struct drm_minor *minor);
 #ifdef CONFIG_DEBUG_FS
-void vc4_debugfs_add_file(struct drm_device *drm,
-                         const char *filename,
-                         int (*show)(struct seq_file*, void*),
-                         void *data);
-void vc4_debugfs_add_regset32(struct drm_device *drm,
-                             const char *filename,
-                             struct debugfs_regset32 *regset);
+int vc4_debugfs_add_file(struct drm_minor *minor,
+                        const char *filename,
+                        int (*show)(struct seq_file*, void*),
+                        void *data);
+int vc4_debugfs_add_regset32(struct drm_minor *minor,
+                            const char *filename,
+                            struct debugfs_regset32 *regset);
 #else
-static inline void vc4_debugfs_add_file(struct drm_device *drm,
-                                       const char *filename,
-                                       int (*show)(struct seq_file*, void*),
-                                       void *data)
+static inline int vc4_debugfs_add_file(struct drm_minor *minor,
+                                      const char *filename,
+                                      int (*show)(struct seq_file*, void*),
+                                      void *data)
 {
+       return 0;
 }
 
-static inline void vc4_debugfs_add_regset32(struct drm_device *drm,
-                                           const char *filename,
-                                           struct debugfs_regset32 *regset)
+static inline int vc4_debugfs_add_regset32(struct drm_minor *minor,
+                                          const char *filename,
+                                          struct debugfs_regset32 *regset)
 {
+       return 0;
 }
 #endif
 
@@ -952,13 +954,15 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
 void vc4_hvs_dump_state(struct vc4_hvs *hvs);
 void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel);
 void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel);
+int vc4_hvs_debugfs_init(struct drm_minor *minor);
 
 /* vc4_kms.c */
 int vc4_kms_load(struct drm_device *dev);
 
 /* vc4_plane.c */
 struct drm_plane *vc4_plane_init(struct drm_device *dev,
-                                enum drm_plane_type type);
+                                enum drm_plane_type type,
+                                uint32_t possible_crtcs);
 int vc4_plane_create_additional_planes(struct drm_device *dev);
 u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
 u32 vc4_plane_dlist_size(const struct drm_plane_state *state);
@@ -973,6 +977,7 @@ int vc4_v3d_bin_bo_get(struct vc4_dev *vc4, bool *used);
 void vc4_v3d_bin_bo_put(struct vc4_dev *vc4);
 int vc4_v3d_pm_get(struct vc4_dev *vc4);
 void vc4_v3d_pm_put(struct vc4_dev *vc4);
+int vc4_v3d_debugfs_init(struct drm_minor *minor);
 
 /* vc4_validate.c */
 int
@@ -984,19 +989,19 @@ vc4_validate_bin_cl(struct drm_device *dev,
 int
 vc4_validate_shader_recs(struct drm_device *dev, struct vc4_exec_info *exec);
 
-struct drm_gem_cma_object *vc4_use_bo(struct vc4_exec_info *exec,
+struct drm_gem_dma_object *vc4_use_bo(struct vc4_exec_info *exec,
                                      uint32_t hindex);
 
 int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec);
 
 bool vc4_check_tex_size(struct vc4_exec_info *exec,
-                       struct drm_gem_cma_object *fbo,
+                       struct drm_gem_dma_object *fbo,
                        uint32_t offset, uint8_t tiling_format,
                        uint32_t width, uint32_t height, uint8_t cpp);
 
 /* vc4_validate_shader.c */
 struct vc4_validated_shader_info *
-vc4_validate_shader(struct drm_gem_cma_object *shader_obj);
+vc4_validate_shader(struct drm_gem_dma_object *shader_obj);
 
 /* vc4_perfmon.c */
 void vc4_perfmon_get(struct vc4_perfmon *perfmon);
index b7b2c76770dc6fe5a4eb4fae84453ba891fd4050..878e05d79e81ca86a4a2a83dbcd36d5d054f6bf4 100644 (file)
@@ -549,10 +549,13 @@ struct vc4_dsi_variant {
 
 /* General DSI hardware state. */
 struct vc4_dsi {
+       struct vc4_encoder encoder;
+       struct mipi_dsi_host dsi_host;
+
+       struct kref kref;
+
        struct platform_device *pdev;
 
-       struct mipi_dsi_host dsi_host;
-       struct drm_encoder *encoder;
        struct drm_bridge *bridge;
        struct list_head bridge_chain;
 
@@ -600,6 +603,12 @@ struct vc4_dsi {
 
 #define host_to_dsi(host) container_of(host, struct vc4_dsi, dsi_host)
 
+static inline struct vc4_dsi *
+to_vc4_dsi(struct drm_encoder *encoder)
+{
+       return container_of(encoder, struct vc4_dsi, encoder.base);
+}
+
 static inline void
 dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
 {
@@ -644,18 +653,6 @@ dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
        DSI_WRITE(dsi->variant->port ? DSI1_##offset : DSI0_##offset, val)
 #define DSI_PORT_BIT(bit) (dsi->variant->port ? DSI1_##bit : DSI0_##bit)
 
-/* VC4 DSI encoder KMS struct */
-struct vc4_dsi_encoder {
-       struct vc4_encoder base;
-       struct vc4_dsi *dsi;
-};
-
-static inline struct vc4_dsi_encoder *
-to_vc4_dsi_encoder(struct drm_encoder *encoder)
-{
-       return container_of(encoder, struct vc4_dsi_encoder, base.base);
-}
-
 static const struct debugfs_reg32 dsi0_regs[] = {
        VC4_REG32(DSI0_CTRL),
        VC4_REG32(DSI0_STAT),
@@ -795,8 +792,7 @@ dsi_esc_timing(u32 ns)
 
 static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
 {
-       struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
-       struct vc4_dsi *dsi = vc4_encoder->dsi;
+       struct vc4_dsi *dsi = to_vc4_dsi(encoder);
        struct device *dev = &dsi->pdev->dev;
        struct drm_bridge *iter;
 
@@ -839,8 +835,7 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
                                       const struct drm_display_mode *mode,
                                       struct drm_display_mode *adjusted_mode)
 {
-       struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
-       struct vc4_dsi *dsi = vc4_encoder->dsi;
+       struct vc4_dsi *dsi = to_vc4_dsi(encoder);
        struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
        unsigned long parent_rate = clk_get_rate(phy_parent);
        unsigned long pixel_clock_hz = mode->clock * 1000;
@@ -875,8 +870,7 @@ static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
 static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
 {
        struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
-       struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
-       struct vc4_dsi *dsi = vc4_encoder->dsi;
+       struct vc4_dsi *dsi = to_vc4_dsi(encoder);
        struct device *dev = &dsi->pdev->dev;
        bool debug_dump_regs = false;
        struct drm_bridge *iter;
@@ -1378,6 +1372,24 @@ static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
        .mode_fixup = vc4_dsi_encoder_mode_fixup,
 };
 
+static int vc4_dsi_late_register(struct drm_encoder *encoder)
+{
+       struct drm_device *drm = encoder->dev;
+       struct vc4_dsi *dsi = to_vc4_dsi(encoder);
+       int ret;
+
+       ret = vc4_debugfs_add_regset32(drm->primary, dsi->variant->debugfs_name,
+                                      &dsi->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct drm_encoder_funcs vc4_dsi_encoder_funcs = {
+       .late_register = vc4_dsi_late_register,
+};
+
 static const struct vc4_dsi_variant bcm2711_dsi1_variant = {
        .port                   = 1,
        .debugfs_name           = "dsi1_regs",
@@ -1564,26 +1576,50 @@ static void vc4_dsi_dma_chan_release(void *ptr)
        dsi->reg_dma_chan = NULL;
 }
 
+static void vc4_dsi_release(struct kref *kref)
+{
+       struct vc4_dsi *dsi =
+               container_of(kref, struct vc4_dsi, kref);
+
+       kfree(dsi);
+}
+
+static void vc4_dsi_get(struct vc4_dsi *dsi)
+{
+       kref_get(&dsi->kref);
+}
+
+static void vc4_dsi_put(struct vc4_dsi *dsi)
+{
+       kref_put(&dsi->kref, &vc4_dsi_release);
+}
+
+static void vc4_dsi_release_action(struct drm_device *drm, void *ptr)
+{
+       struct vc4_dsi *dsi = ptr;
+
+       vc4_dsi_put(dsi);
+}
+
 static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
        struct vc4_dsi *dsi = dev_get_drvdata(dev);
-       struct vc4_dsi_encoder *vc4_dsi_encoder;
+       struct drm_encoder *encoder = &dsi->encoder.base;
        int ret;
 
-       dsi->variant = of_device_get_match_data(dev);
+       vc4_dsi_get(dsi);
 
-       vc4_dsi_encoder = devm_kzalloc(dev, sizeof(*vc4_dsi_encoder),
-                                      GFP_KERNEL);
-       if (!vc4_dsi_encoder)
-               return -ENOMEM;
+       ret = drmm_add_action_or_reset(drm, vc4_dsi_release_action, dsi);
+       if (ret)
+               return ret;
+
+       dsi->variant = of_device_get_match_data(dev);
 
        INIT_LIST_HEAD(&dsi->bridge_chain);
-       vc4_dsi_encoder->base.type = dsi->variant->port ?
-                       VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0;
-       vc4_dsi_encoder->dsi = dsi;
-       dsi->encoder = &vc4_dsi_encoder->base.base;
+       dsi->encoder.type = dsi->variant->port ?
+               VC4_ENCODER_TYPE_DSI1 : VC4_ENCODER_TYPE_DSI0;
 
        dsi->regs = vc4_ioremap_regs(pdev, 0);
        if (IS_ERR(dsi->regs))
@@ -1687,7 +1723,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
+       dsi->bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
        if (IS_ERR(dsi->bridge))
                return PTR_ERR(dsi->bridge);
 
@@ -1702,10 +1738,20 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
        if (ret)
                return ret;
 
-       drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
-       drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
+       ret = drmm_encoder_init(drm, encoder,
+                               &vc4_dsi_encoder_funcs,
+                               DRM_MODE_ENCODER_DSI,
+                               NULL);
+       if (ret)
+               return ret;
+
+       drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs);
 
-       ret = drm_bridge_attach(dsi->encoder, dsi->bridge, NULL, 0);
+       ret = devm_pm_runtime_enable(dev);
+       if (ret)
+               return ret;
+
+       ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0);
        if (ret)
                return ret;
        /* Disable the atomic helper calls into the bridge.  We
@@ -1713,11 +1759,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
         * from our driver, since we need to sequence them within the
         * encoder's enable/disable paths.
         */
-       list_splice_init(&dsi->encoder->bridge_chain, &dsi->bridge_chain);
-
-       vc4_debugfs_add_regset32(drm, dsi->variant->debugfs_name, &dsi->regset);
-
-       pm_runtime_enable(dev);
+       list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
 
        return 0;
 }
@@ -1726,15 +1768,13 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
                           void *data)
 {
        struct vc4_dsi *dsi = dev_get_drvdata(dev);
-
-       pm_runtime_disable(dev);
+       struct drm_encoder *encoder = &dsi->encoder.base;
 
        /*
         * Restore the bridge_chain so the bridge detach procedure can happen
         * normally.
         */
-       list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
-       drm_encoder_cleanup(dsi->encoder);
+       list_splice_init(&dsi->bridge_chain, &encoder->bridge_chain);
 }
 
 static const struct component_ops vc4_dsi_ops = {
@@ -1747,11 +1787,12 @@ static int vc4_dsi_dev_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct vc4_dsi *dsi;
 
-       dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+       dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
        if (!dsi)
                return -ENOMEM;
        dev_set_drvdata(dev, dsi);
 
+       kref_init(&dsi->kref);
        dsi->pdev = pdev;
        dsi->dsi_host.ops = &vc4_dsi_host_ops;
        dsi->dsi_host.dev = dev;
@@ -1766,6 +1807,8 @@ static int vc4_dsi_dev_remove(struct platform_device *pdev)
        struct vc4_dsi *dsi = dev_get_drvdata(dev);
 
        mipi_dsi_host_unregister(&dsi->dsi_host);
+       vc4_dsi_put(dsi);
+
        return 0;
 }
 
index fe10d9c3fff8a27bf11a62e3e59bf18ab63db0bb..628d40ff3aa1c08936deb9deae13ecef49ab8506 100644 (file)
@@ -126,7 +126,7 @@ vc4_get_hang_state_ioctl(struct drm_device *dev, void *data,
                        goto err_delete_handle;
                }
                bo_state[i].handle = handle;
-               bo_state[i].paddr = vc4_bo->base.paddr;
+               bo_state[i].paddr = vc4_bo->base.dma_addr;
                bo_state[i].size = vc4_bo->base.base.size;
        }
 
@@ -764,7 +764,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
        }
 
        exec->bo = kvmalloc_array(exec->bo_count,
-                                   sizeof(struct drm_gem_cma_object *),
+                                   sizeof(struct drm_gem_dma_object *),
                                    GFP_KERNEL | __GFP_ZERO);
        if (!exec->bo) {
                DRM_ERROR("Failed to allocate validated BO pointers\n");
@@ -797,7 +797,7 @@ vc4_cl_lookup_bos(struct drm_device *dev,
                }
 
                drm_gem_object_get(bo);
-               exec->bo[i] = (struct drm_gem_cma_object *)bo;
+               exec->bo[i] = (struct drm_gem_dma_object *)bo;
        }
        spin_unlock(&file_priv->table_lock);
 
@@ -917,16 +917,16 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec)
        list_add_tail(&to_vc4_bo(&exec->exec_bo->base)->unref_head,
                      &exec->unref_list);
 
-       exec->ct0ca = exec->exec_bo->paddr + bin_offset;
+       exec->ct0ca = exec->exec_bo->dma_addr + bin_offset;
 
        exec->bin_u = bin;
 
        exec->shader_rec_v = exec->exec_bo->vaddr + shader_rec_offset;
-       exec->shader_rec_p = exec->exec_bo->paddr + shader_rec_offset;
+       exec->shader_rec_p = exec->exec_bo->dma_addr + shader_rec_offset;
        exec->shader_rec_size = args->shader_rec_size;
 
        exec->uniforms_v = exec->exec_bo->vaddr + uniforms_offset;
-       exec->uniforms_p = exec->exec_bo->paddr + uniforms_offset;
+       exec->uniforms_p = exec->exec_bo->dma_addr + uniforms_offset;
        exec->uniforms_size = args->uniforms_size;
 
        ret = vc4_validate_bin_cl(dev,
@@ -1308,6 +1308,7 @@ static void vc4_gem_destroy(struct drm_device *dev, void *unused);
 int vc4_gem_init(struct drm_device *dev)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
+       int ret;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
                return -ENODEV;
@@ -1325,10 +1326,15 @@ int vc4_gem_init(struct drm_device *dev)
 
        INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
 
-       mutex_init(&vc4->power_lock);
+       ret = drmm_mutex_init(dev, &vc4->power_lock);
+       if (ret)
+               return ret;
 
        INIT_LIST_HEAD(&vc4->purgeable.list);
-       mutex_init(&vc4->purgeable.lock);
+
+       ret = drmm_mutex_init(dev, &vc4->purgeable.lock);
+       if (ret)
+               return ret;
 
        return drmm_add_action_or_reset(dev, vc4_gem_destroy, NULL);
 }
index 592c3b5d03e6e1f296dace9bf27b0a39c8a42dd9..fda450185c366e85efa06267d42a7693171ce5ab 100644 (file)
@@ -34,6 +34,7 @@
 #include <drm/display/drm_hdmi_helper.h>
 #include <drm/display/drm_scdc_helper.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_simple_kms_helper.h>
 #include <linux/clk.h>
@@ -41,7 +42,6 @@
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/of_address.h>
-#include <linux/of_gpio.h>
 #include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/rational.h>
@@ -146,7 +146,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
 {
        struct drm_info_node *node = (struct drm_info_node *)m->private;
        struct vc4_hdmi *vc4_hdmi = node->info_ent->data;
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_printer p = drm_seq_file_printer(m);
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return -ENODEV;
 
        drm_print_regset32(&p, &vc4_hdmi->hdmi_regset);
        drm_print_regset32(&p, &vc4_hdmi->hd_regset);
@@ -157,12 +162,23 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused)
        drm_print_regset32(&p, &vc4_hdmi->ram_regset);
        drm_print_regset32(&p, &vc4_hdmi->rm_regset);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
 static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
+
+       /*
+        * We can be called by our bind callback, when the
+        * connector->dev pointer might not be initialised yet.
+        */
+       if (drm && !drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -179,11 +195,23 @@ static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
        HDMI_WRITE(HDMI_SW_RESET_CONTROL, 0);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       if (drm)
+               drm_dev_exit(idx);
 }
 
 static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
+
+       /*
+        * We can be called by our bind callback, when the
+        * connector->dev pointer might not be initialised yet.
+        */
+       if (drm && !drm_dev_enter(drm, &idx))
+               return;
 
        reset_control_reset(vc4_hdmi->reset);
 
@@ -195,15 +223,31 @@ static void vc5_hdmi_reset(struct vc4_hdmi *vc4_hdmi)
                   HDMI_READ(HDMI_CLOCK_STOP) | VC4_DVP_HT_CLOCK_STOP_PIXEL);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       if (drm)
+               drm_dev_exit(idx);
 }
 
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
 {
-       unsigned long cec_rate = clk_get_rate(vc4_hdmi->cec_clock);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
+       unsigned long cec_rate;
        unsigned long flags;
        u16 clk_cnt;
        u32 value;
+       int idx;
+
+       /*
+        * This function is called by our runtime_resume implementation
+        * and thus at bind time, when we haven't registered our
+        * connector yet and thus don't have a pointer to the DRM
+        * device.
+        */
+       if (drm && !drm_dev_enter(drm, &idx))
+               return;
+
+       cec_rate = clk_get_rate(vc4_hdmi->cec_clock);
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -219,6 +263,9 @@ static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi)
        HDMI_WRITE(HDMI_CEC_CNTRL_1, value);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       if (drm)
+               drm_dev_exit(idx);
 }
 #else
 static void vc4_hdmi_cec_update_clk_div(struct vc4_hdmi *vc4_hdmi) {}
@@ -267,12 +314,6 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force)
        return connector_status_disconnected;
 }
 
-static void vc4_hdmi_connector_destroy(struct drm_connector *connector)
-{
-       drm_connector_unregister(connector);
-       drm_connector_cleanup(connector);
-}
-
 static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
 {
        struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
@@ -380,7 +421,6 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector)
 static const struct drm_connector_funcs vc4_hdmi_connector_funcs = {
        .detect = vc4_hdmi_connector_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_hdmi_connector_destroy,
        .reset = vc4_hdmi_connector_reset,
        .atomic_duplicate_state = vc4_hdmi_connector_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -398,10 +438,13 @@ static int vc4_hdmi_connector_init(struct drm_device *dev,
        struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
        int ret;
 
-       drm_connector_init_with_ddc(dev, connector,
-                                   &vc4_hdmi_connector_funcs,
-                                   DRM_MODE_CONNECTOR_HDMIA,
-                                   vc4_hdmi->ddc);
+       ret = drmm_connector_init(dev, connector,
+                                 &vc4_hdmi_connector_funcs,
+                                 DRM_MODE_CONNECTOR_HDMIA,
+                                 vc4_hdmi->ddc);
+       if (ret)
+               return ret;
+
        drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
 
        /*
@@ -444,25 +487,34 @@ static int vc4_hdmi_stop_packet(struct drm_encoder *encoder,
                                bool poll)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        u32 packet_id = type - 0x80;
        unsigned long flags;
+       int ret = 0;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return -ENODEV;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
        HDMI_WRITE(HDMI_RAM_PACKET_CONFIG,
                   HDMI_READ(HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id));
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
-       if (!poll)
-               return 0;
+       if (poll) {
+               ret = wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
+                                BIT(packet_id)), 100);
+       }
 
-       return wait_for(!(HDMI_READ(HDMI_RAM_PACKET_STATUS) &
-                         BIT(packet_id)), 100);
+       drm_dev_exit(idx);
+       return ret;
 }
 
 static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
                                     union hdmi_infoframe *frame)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        u32 packet_id = frame->any.type - 0x80;
        const struct vc4_hdmi_register *ram_packet_start =
                &vc4_hdmi->variant->registers[HDMI_RAM_PACKET_START];
@@ -475,6 +527,10 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
        unsigned long flags;
        ssize_t len, i;
        int ret;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        WARN_ONCE(!(HDMI_READ(HDMI_RAM_PACKET_CONFIG) &
                    VC4_HDMI_RAM_PACKET_ENABLE),
@@ -482,12 +538,12 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
 
        len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer));
        if (len < 0)
-               return;
+               goto out;
 
        ret = vc4_hdmi_stop_packet(encoder, frame->any.type, true);
        if (ret) {
                DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret);
-               return;
+               goto out;
        }
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
@@ -523,6 +579,9 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder,
                        BIT(packet_id)), 100);
        if (ret)
                DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret);
+
+out:
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
@@ -672,8 +731,10 @@ static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder,
 static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
        unsigned long flags;
+       int idx;
 
        lockdep_assert_held(&vc4_hdmi->mutex);
 
@@ -685,6 +746,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
                                            vc4_hdmi->output_format))
                return;
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true);
        drm_scdc_set_scrambling(vc4_hdmi->ddc, true);
 
@@ -693,6 +757,8 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
                   VC5_HDMI_SCRAMBLER_CTL_ENABLE);
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        vc4_hdmi->scdc_enabled = true;
 
        queue_delayed_work(system_wq, &vc4_hdmi->scrambling_work,
@@ -702,7 +768,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
 static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
 
        lockdep_assert_held(&vc4_hdmi->mutex);
 
@@ -714,6 +782,9 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
        if (delayed_work_pending(&vc4_hdmi->scrambling_work))
                cancel_delayed_work_sync(&vc4_hdmi->scrambling_work);
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
        HDMI_WRITE(HDMI_SCRAMBLER_CTL, HDMI_READ(HDMI_SCRAMBLER_CTL) &
                   ~VC5_HDMI_SCRAMBLER_CTL_ENABLE);
@@ -721,6 +792,8 @@ static void vc4_hdmi_disable_scrambling(struct drm_encoder *encoder)
 
        drm_scdc_set_scrambling(vc4_hdmi->ddc, false);
        drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, false);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_scrambling_wq(struct work_struct *work)
@@ -743,12 +816,17 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
                                               struct drm_atomic_state *state)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
        vc4_hdmi->packet_ram_enabled = false;
 
+       if (!drm_dev_enter(drm, &idx))
+               goto out;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
        HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0);
@@ -766,6 +844,9 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder,
 
        vc4_hdmi_disable_scrambling(encoder);
 
+       drm_dev_exit(idx);
+
+out:
        mutex_unlock(&vc4_hdmi->mutex);
 }
 
@@ -773,11 +854,16 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
                                                 struct drm_atomic_state *state)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
        int ret;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx))
+               goto out;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
        HDMI_WRITE(HDMI_VID_CTL,
                   HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX);
@@ -793,6 +879,9 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder,
        if (ret < 0)
                DRM_ERROR("Failed to release power domain: %d\n", ret);
 
+       drm_dev_exit(idx);
+
+out:
        mutex_unlock(&vc4_hdmi->mutex);
 }
 
@@ -800,8 +889,13 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
                               struct drm_connector_state *state,
                               const struct drm_display_mode *mode)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
        u32 csc_ctl;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -836,6 +930,8 @@ static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
        HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       drm_dev_exit(idx);
 }
 
 /*
@@ -920,6 +1016,7 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
                               struct drm_connector_state *state,
                               const struct drm_display_mode *mode)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct vc4_hdmi_connector_state *vc4_state =
                conn_state_to_vc4_hdmi_conn_state(state);
        unsigned long flags;
@@ -928,6 +1025,10 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
        u32 csc_chan_ctl = 0;
        u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM,
                                                               VC5_MT_CP_CSC_CTL_MODE);
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -970,12 +1071,15 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi,
        HDMI_WRITE(HDMI_CSC_CTL, csc_ctl);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
                                 struct drm_connector_state *state,
                                 struct drm_display_mode *mode)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
        bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
        bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
@@ -995,6 +1099,10 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
                                        VC4_HDMI_VERTB_VBP));
        unsigned long flags;
        u32 reg;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -1027,12 +1135,15 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
        HDMI_WRITE(HDMI_MISC_CONTROL, reg);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       drm_dev_exit(idx);
 }
 
 static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
                                 struct drm_connector_state *state,
                                 struct drm_display_mode *mode)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        const struct vc4_hdmi_connector_state *vc4_state =
                conn_state_to_vc4_hdmi_conn_state(state);
        bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
@@ -1056,6 +1167,10 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
        unsigned char gcp;
        bool gcp_en;
        u32 reg;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -1132,13 +1247,20 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi,
        HDMI_WRITE(HDMI_CLOCK_STOP, 0);
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
        u32 drift;
        int ret;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -1167,12 +1289,15 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi)
                       VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1);
        WARN_ONCE(ret, "Timeout waiting for "
                  "VC4_HDMI_FIFO_CTL_RECENTER_DONE");
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
                                                struct drm_atomic_state *state)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_connector *connector = &vc4_hdmi->connector;
        struct drm_connector_state *conn_state =
                drm_atomic_get_new_connector_state(state, connector);
@@ -1183,9 +1308,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
        unsigned long bvb_rate, hsm_rate;
        unsigned long flags;
        int ret;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx))
+               goto out;
+
        /*
         * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
         * be faster than pixel clock, infinitesimally faster, tested in
@@ -1206,13 +1335,13 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
        ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate);
        if (ret) {
                DRM_ERROR("Failed to set HSM clock rate: %d\n", ret);
-               goto out;
+               goto err_dev_exit;
        }
 
        ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
        if (ret < 0) {
                DRM_ERROR("Failed to retain power domain: %d\n", ret);
-               goto out;
+               goto err_dev_exit;
        }
 
        ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate);
@@ -1264,6 +1393,8 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder,
        if (vc4_hdmi->variant->set_timings)
                vc4_hdmi->variant->set_timings(vc4_hdmi, conn_state, mode);
 
+       drm_dev_exit(idx);
+
        mutex_unlock(&vc4_hdmi->mutex);
 
        return;
@@ -1272,6 +1403,8 @@ err_disable_pixel_clock:
        clk_disable_unprepare(vc4_hdmi->pixel_clock);
 err_put_runtime_pm:
        pm_runtime_put(&vc4_hdmi->pdev->dev);
+err_dev_exit:
+       drm_dev_exit(idx);
 out:
        mutex_unlock(&vc4_hdmi->mutex);
        return;
@@ -1281,14 +1414,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
                                             struct drm_atomic_state *state)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_connector *connector = &vc4_hdmi->connector;
        struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
        struct drm_connector_state *conn_state =
                drm_atomic_get_new_connector_state(state, connector);
        unsigned long flags;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        if (vc4_hdmi->variant->csc_setup)
                vc4_hdmi->variant->csc_setup(vc4_hdmi, conn_state, mode);
 
@@ -1296,6 +1434,8 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder,
        HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N);
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        mutex_unlock(&vc4_hdmi->mutex);
 }
 
@@ -1303,15 +1443,20 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
                                              struct drm_atomic_state *state)
 {
        struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode;
        struct drm_display_info *display = &vc4_hdmi->connector.display_info;
        bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC;
        bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC;
        unsigned long flags;
        int ret;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
        HDMI_WRITE(HDMI_VID_CTL,
@@ -1370,6 +1515,7 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder,
        vc4_hdmi_recenter_fifo(vc4_hdmi);
        vc4_hdmi_enable_scrambling(encoder);
 
+       drm_dev_exit(idx);
        mutex_unlock(&vc4_hdmi->mutex);
 }
 
@@ -1692,6 +1838,26 @@ static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
        .mode_valid = vc4_hdmi_encoder_mode_valid,
 };
 
+static int vc4_hdmi_late_register(struct drm_encoder *encoder)
+{
+       struct drm_device *drm = encoder->dev;
+       struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
+       const struct vc4_hdmi_variant *variant = vc4_hdmi->variant;
+       int ret;
+
+       ret = vc4_debugfs_add_file(drm->primary, variant->debugfs_name,
+                                  vc4_hdmi_debugfs_regs,
+                                  vc4_hdmi);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = {
+       .late_register = vc4_hdmi_late_register,
+};
+
 static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 {
        int i;
@@ -1718,13 +1884,20 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
 
 static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi)
 {
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
        u32 hotplug;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return false;
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
        hotplug = HDMI_READ(HDMI_HOTPLUG);
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        return !!(hotplug & VC4_HDMI_HOTPLUG_CONNECTED);
 }
 
@@ -1732,10 +1905,16 @@ static bool vc5_hdmi_hp_detect(struct vc4_hdmi *vc4_hdmi)
 static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,
                                         unsigned int samplerate)
 {
-       u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
+       u32 hsm_clock;
        unsigned long flags;
        unsigned long n, m;
+       int idx;
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
        rational_best_approximation(hsm_clock, samplerate,
                                    VC4_HD_MAI_SMP_N_MASK >>
                                    VC4_HD_MAI_SMP_N_SHIFT,
@@ -1748,6 +1927,8 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,
                   VC4_SET_FIELD(n, VC4_HD_MAI_SMP_N) |
                   VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)
@@ -1803,13 +1984,21 @@ static bool vc4_hdmi_audio_can_stream(struct vc4_hdmi *vc4_hdmi)
 static int vc4_hdmi_audio_startup(struct device *dev, void *data)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int ret = 0;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx)) {
+               ret = -ENODEV;
+               goto out;
+       }
+
        if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) {
-               mutex_unlock(&vc4_hdmi->mutex);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_dev_exit;
        }
 
        vc4_hdmi->audio.streaming = true;
@@ -1826,9 +2015,12 @@ static int vc4_hdmi_audio_startup(struct device *dev, void *data)
        if (vc4_hdmi->variant->phy_rng_enable)
                vc4_hdmi->variant->phy_rng_enable(vc4_hdmi);
 
+out_dev_exit:
+       drm_dev_exit(idx);
+out:
        mutex_unlock(&vc4_hdmi->mutex);
 
-       return 0;
+       return ret;
 }
 
 static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
@@ -1857,10 +2049,15 @@ static void vc4_hdmi_audio_reset(struct vc4_hdmi *vc4_hdmi)
 static void vc4_hdmi_audio_shutdown(struct device *dev, void *data)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx))
+               goto out;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
        HDMI_WRITE(HDMI_MAI_CTL,
@@ -1876,6 +2073,9 @@ static void vc4_hdmi_audio_shutdown(struct device *dev, void *data)
        vc4_hdmi->audio.streaming = false;
        vc4_hdmi_audio_reset(vc4_hdmi);
 
+       drm_dev_exit(idx);
+
+out:
        mutex_unlock(&vc4_hdmi->mutex);
 }
 
@@ -1923,6 +2123,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
                                  struct hdmi_codec_params *params)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
        unsigned int sample_rate = params->sample_rate;
        unsigned int channels = params->channels;
@@ -1931,15 +2132,22 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
        u32 channel_map;
        u32 mai_audio_format;
        u32 mai_sample_rate;
+       int ret = 0;
+       int idx;
 
        dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
                sample_rate, params->sample_width, channels);
 
        mutex_lock(&vc4_hdmi->mutex);
 
+       if (!drm_dev_enter(drm, &idx)) {
+               ret = -ENODEV;
+               goto out;
+       }
+
        if (!vc4_hdmi_audio_can_stream(vc4_hdmi)) {
-               mutex_unlock(&vc4_hdmi->mutex);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out_dev_exit;
        }
 
        vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
@@ -1996,9 +2204,12 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
        memcpy(&vc4_hdmi->audio.infoframe, &params->cea, sizeof(params->cea));
        vc4_hdmi_set_audio_infoframe(encoder);
 
+out_dev_exit:
+       drm_dev_exit(idx);
+out:
        mutex_unlock(&vc4_hdmi->mutex);
 
-       return 0;
+       return ret;
 }
 
 static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
@@ -2061,6 +2272,14 @@ static struct hdmi_codec_pdata vc4_hdmi_codec_pdata = {
        .i2s = 1,
 };
 
+static void vc4_hdmi_audio_codec_release(void *ptr)
+{
+       struct vc4_hdmi *vc4_hdmi = ptr;
+
+       platform_device_unregister(vc4_hdmi->audio.codec_pdev);
+       vc4_hdmi->audio.codec_pdev = NULL;
+}
+
 static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 {
        const struct vc4_hdmi_register *mai_data =
@@ -2073,6 +2292,26 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
        int index, len;
        int ret;
 
+       /*
+        * ASoC makes it a bit hard to retrieve a pointer to the
+        * vc4_hdmi structure. Registering the card will overwrite our
+        * device drvdata with a pointer to the snd_soc_card structure,
+        * which can then be used to retrieve whatever drvdata we want
+        * to associate.
+        *
+        * However, that doesn't fly in the case where we wouldn't
+        * register an ASoC card (because of an old DT that is missing
+        * the dmas properties for example), then the card isn't
+        * registered and the device drvdata wouldn't be set.
+        *
+        * We can deal with both cases by making sure a snd_soc_card
+        * pointer and a vc4_hdmi structure are pointing to the same
+        * memory address, so we can treat them indistinctly without any
+        * issue.
+        */
+       BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
+       BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
+
        if (!of_find_property(dev->of_node, "dmas", &len) || !len) {
                dev_warn(dev,
                         "'dmas' DT property is missing or empty, no HDMI audio\n");
@@ -2102,6 +2341,30 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
        vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
        vc4_hdmi->audio.dma_data.maxburst = 2;
 
+       /*
+        * NOTE: Strictly speaking, we should probably use a DRM-managed
+        * registration there to avoid removing all the audio components
+        * by the time the driver doesn't have any user anymore.
+        *
+        * However, the ASoC core uses a number of devm_kzalloc calls
+        * when registering, even when using non-device-managed
+        * functions (such as in snd_soc_register_component()).
+        *
+        * If we call snd_soc_unregister_component() in a DRM-managed
+        * action, the device-managed actions have already been executed
+        * and thus we would access memory that has been freed.
+        *
+        * Using device-managed hooks here probably leaves us open to a
+        * bunch of issues if userspace still has a handle on the ALSA
+        * device when the device is removed. However, this is mitigated
+        * by the use of drm_dev_enter()/drm_dev_exit() in the audio
+        * path to prevent the access to the device resources if it
+        * isn't there anymore.
+        *
+        * Then, the vc4_hdmi structure is DRM-managed and thus only
+        * freed whenever the last user has closed the DRM device file.
+        * It should thus outlive ALSA in most situations.
+        */
        ret = devm_snd_dmaengine_pcm_register(dev, &pcm_conf, 0);
        if (ret) {
                dev_err(dev, "Could not register PCM component: %d\n", ret);
@@ -2125,6 +2388,10 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
        }
        vc4_hdmi->audio.codec_pdev = codec_pdev;
 
+       ret = devm_add_action_or_reset(dev, vc4_hdmi_audio_codec_release, vc4_hdmi);
+       if (ret)
+               return ret;
+
        dai_link->cpus          = &vc4_hdmi->audio.cpu;
        dai_link->codecs        = &vc4_hdmi->audio.codec;
        dai_link->platforms     = &vc4_hdmi->audio.platform;
@@ -2163,12 +2430,6 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
 
 }
 
-static void vc4_hdmi_audio_exit(struct vc4_hdmi *vc4_hdmi)
-{
-       platform_device_unregister(vc4_hdmi->audio.codec_pdev);
-       vc4_hdmi->audio.codec_pdev = NULL;
-}
-
 static irqreturn_t vc4_hdmi_hpd_irq_thread(int irq, void *priv)
 {
        struct vc4_hdmi *vc4_hdmi = priv;
@@ -2191,21 +2452,19 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
                unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected");
                unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed");
 
-               ret = request_threaded_irq(hpd_con,
-                                          NULL,
-                                          vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
-                                          "vc4 hdmi hpd connected", vc4_hdmi);
+               ret = devm_request_threaded_irq(&pdev->dev, hpd_con,
+                                               NULL,
+                                               vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
+                                               "vc4 hdmi hpd connected", vc4_hdmi);
                if (ret)
                        return ret;
 
-               ret = request_threaded_irq(hpd_rm,
-                                          NULL,
-                                          vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
-                                          "vc4 hdmi hpd disconnected", vc4_hdmi);
-               if (ret) {
-                       free_irq(hpd_con, vc4_hdmi);
+               ret = devm_request_threaded_irq(&pdev->dev, hpd_rm,
+                                               NULL,
+                                               vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
+                                               "vc4 hdmi hpd disconnected", vc4_hdmi);
+               if (ret)
                        return ret;
-               }
 
                connector->polled = DRM_CONNECTOR_POLL_HPD;
        }
@@ -2213,16 +2472,6 @@ static int vc4_hdmi_hotplug_init(struct vc4_hdmi *vc4_hdmi)
        return 0;
 }
 
-static void vc4_hdmi_hotplug_exit(struct vc4_hdmi *vc4_hdmi)
-{
-       struct platform_device *pdev = vc4_hdmi->pdev;
-
-       if (vc4_hdmi->variant->external_irq_controller) {
-               free_irq(platform_get_irq_byname(pdev, "hpd-connected"), vc4_hdmi);
-               free_irq(platform_get_irq_byname(pdev, "hpd-removed"), vc4_hdmi);
-       }
-}
-
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 static irqreturn_t vc4_cec_irq_handler_rx_thread(int irq, void *priv)
 {
@@ -2296,6 +2545,17 @@ static irqreturn_t vc4_cec_irq_handler_tx_bare_locked(struct vc4_hdmi *vc4_hdmi)
 {
        u32 cntrl1;
 
+       /*
+        * We don't need to protect the register access using
+        * drm_dev_enter() there because the interrupt handler lifetime
+        * is tied to the device itself, and not to the DRM device.
+        *
+        * So when the device will be gone, one of the first thing we
+        * will be doing will be to unregister the interrupt handler,
+        * and then unregister the DRM device. drm_dev_enter() would
+        * thus always succeed if we are here.
+        */
+
        lockdep_assert_held(&vc4_hdmi->hw_lock);
 
        cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
@@ -2324,6 +2584,17 @@ static irqreturn_t vc4_cec_irq_handler_rx_bare_locked(struct vc4_hdmi *vc4_hdmi)
 
        lockdep_assert_held(&vc4_hdmi->hw_lock);
 
+       /*
+        * We don't need to protect the register access using
+        * drm_dev_enter() there because the interrupt handler lifetime
+        * is tied to the device itself, and not to the DRM device.
+        *
+        * So when the device will be gone, one of the first thing we
+        * will be doing will be to unregister the interrupt handler,
+        * and then unregister the DRM device. drm_dev_enter() would
+        * thus always succeed if we are here.
+        */
+
        vc4_hdmi->cec_rx_msg.len = 0;
        cntrl1 = HDMI_READ(HDMI_CEC_CNTRL_1);
        vc4_cec_read_msg(vc4_hdmi, cntrl1);
@@ -2355,6 +2626,17 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
        irqreturn_t ret;
        u32 cntrl5;
 
+       /*
+        * We don't need to protect the register access using
+        * drm_dev_enter() there because the interrupt handler lifetime
+        * is tied to the device itself, and not to the DRM device.
+        *
+        * So when the device will be gone, one of the first thing we
+        * will be doing will be to unregister the interrupt handler,
+        * and then unregister the DRM device. drm_dev_enter() would
+        * thus always succeed if we are here.
+        */
+
        if (!(stat & VC4_HDMI_CPU_CEC))
                return IRQ_NONE;
 
@@ -2375,11 +2657,13 @@ static irqreturn_t vc4_cec_irq_handler(int irq, void *priv)
 static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
 {
        struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        /* clock period in microseconds */
        const u32 usecs = 1000000 / CEC_CLOCK_FREQ;
        unsigned long flags;
        u32 val;
        int ret;
+       int idx;
 
        /*
         * NOTE: This function should really take vc4_hdmi->mutex, but doing so
@@ -2392,9 +2676,19 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
         * keep it in mind if we were to change that assumption.
         */
 
+       if (!drm_dev_enter(drm, &idx))
+               /*
+                * We can't return an error code, because the CEC
+                * framework will emit WARN_ON messages at unbind
+                * otherwise.
+                */
+               return 0;
+
        ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev);
-       if (ret)
+       if (ret) {
+               drm_dev_exit(idx);
                return ret;
+       }
 
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
 
@@ -2430,13 +2724,25 @@ static int vc4_hdmi_cec_enable(struct cec_adapter *adap)
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
 static int vc4_hdmi_cec_disable(struct cec_adapter *adap)
 {
        struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               /*
+                * We can't return an error code, because the CEC
+                * framework will emit WARN_ON messages at unbind
+                * otherwise.
+                */
+               return 0;
 
        /*
         * NOTE: This function should really take vc4_hdmi->mutex, but doing so
@@ -2461,6 +2767,8 @@ static int vc4_hdmi_cec_disable(struct cec_adapter *adap)
 
        pm_runtime_put(&vc4_hdmi->pdev->dev);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
@@ -2475,7 +2783,9 @@ static int vc4_hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable)
 static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
 {
        struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap);
+       struct drm_device *drm = vc4_hdmi->connector.dev;
        unsigned long flags;
+       int idx;
 
        /*
         * NOTE: This function should really take vc4_hdmi->mutex, but doing so
@@ -2488,12 +2798,22 @@ static int vc4_hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
         * keep it in mind if we were to change that assumption.
         */
 
+       if (!drm_dev_enter(drm, &idx))
+               /*
+                * We can't return an error code, because the CEC
+                * framework will emit WARN_ON messages at unbind
+                * otherwise.
+                */
+               return 0;
+
        spin_lock_irqsave(&vc4_hdmi->hw_lock, flags);
        HDMI_WRITE(HDMI_CEC_CNTRL_1,
                   (HDMI_READ(HDMI_CEC_CNTRL_1) & ~VC4_HDMI_CEC_ADDR_MASK) |
                   (log_addr & 0xf) << VC4_HDMI_CEC_ADDR_SHIFT);
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
@@ -2505,6 +2825,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
        unsigned long flags;
        u32 val;
        unsigned int i;
+       int idx;
 
        /*
         * NOTE: This function should really take vc4_hdmi->mutex, but doing so
@@ -2517,8 +2838,12 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
         * keep it in mind if we were to change that assumption.
         */
 
+       if (!drm_dev_enter(dev, &idx))
+               return -ENODEV;
+
        if (msg->len > 16) {
                drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len);
+               drm_dev_exit(idx);
                return -ENOMEM;
        }
 
@@ -2542,6 +2867,8 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
 
        spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
@@ -2551,6 +2878,14 @@ static const struct cec_adap_ops vc4_hdmi_cec_adap_ops = {
        .adap_transmit = vc4_hdmi_cec_adap_transmit,
 };
 
+static void vc4_hdmi_cec_release(void *ptr)
+{
+       struct vc4_hdmi *vc4_hdmi = ptr;
+
+       cec_unregister_adapter(vc4_hdmi->cec_adap);
+       vc4_hdmi->cec_adap = NULL;
+}
+
 static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
 {
        struct cec_connector_info conn_info;
@@ -2575,73 +2910,82 @@ static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
        cec_s_conn_info(vc4_hdmi->cec_adap, &conn_info);
 
        if (vc4_hdmi->variant->external_irq_controller) {
-               ret = request_threaded_irq(platform_get_irq_byname(pdev, "cec-rx"),
-                                          vc4_cec_irq_handler_rx_bare,
-                                          vc4_cec_irq_handler_rx_thread, 0,
-                                          "vc4 hdmi cec rx", vc4_hdmi);
+               ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-rx"),
+                                               vc4_cec_irq_handler_rx_bare,
+                                               vc4_cec_irq_handler_rx_thread, 0,
+                                               "vc4 hdmi cec rx", vc4_hdmi);
                if (ret)
                        goto err_delete_cec_adap;
 
-               ret = request_threaded_irq(platform_get_irq_byname(pdev, "cec-tx"),
-                                          vc4_cec_irq_handler_tx_bare,
-                                          vc4_cec_irq_handler_tx_thread, 0,
-                                          "vc4 hdmi cec tx", vc4_hdmi);
+               ret = devm_request_threaded_irq(dev, platform_get_irq_byname(pdev, "cec-tx"),
+                                               vc4_cec_irq_handler_tx_bare,
+                                               vc4_cec_irq_handler_tx_thread, 0,
+                                               "vc4 hdmi cec tx", vc4_hdmi);
                if (ret)
-                       goto err_remove_cec_rx_handler;
+                       goto err_delete_cec_adap;
        } else {
-               ret = request_threaded_irq(platform_get_irq(pdev, 0),
-                                          vc4_cec_irq_handler,
-                                          vc4_cec_irq_handler_thread, 0,
-                                          "vc4 hdmi cec", vc4_hdmi);
+               ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0),
+                                               vc4_cec_irq_handler,
+                                               vc4_cec_irq_handler_thread, 0,
+                                               "vc4 hdmi cec", vc4_hdmi);
                if (ret)
                        goto err_delete_cec_adap;
        }
 
        ret = cec_register_adapter(vc4_hdmi->cec_adap, &pdev->dev);
        if (ret < 0)
-               goto err_remove_handlers;
+               goto err_delete_cec_adap;
 
-       return 0;
-
-err_remove_handlers:
-       if (vc4_hdmi->variant->external_irq_controller)
-               free_irq(platform_get_irq_byname(pdev, "cec-tx"), vc4_hdmi);
-       else
-               free_irq(platform_get_irq(pdev, 0), vc4_hdmi);
+       /*
+        * NOTE: Strictly speaking, we should probably use a DRM-managed
+        * registration there to avoid removing the CEC adapter by the
+        * time the DRM driver doesn't have any user anymore.
+        *
+        * However, the CEC framework already cleans up the CEC adapter
+        * only when the last user has closed its file descriptor, so we
+        * don't need to handle it in DRM.
+        *
+        * By the time the device-managed hook is executed, we will give
+        * up our reference to the CEC adapter and therefore don't
+        * really care when it's actually freed.
+        *
+        * There's still a problematic sequence: if we unregister our
+        * CEC adapter, but the userspace keeps a handle on the CEC
+        * adapter but not the DRM device for some reason. In such a
+        * case, our vc4_hdmi structure will be freed, but the
+        * cec_adapter structure will have a dangling pointer to what
+        * used to be our HDMI controller. If we get a CEC call at that
+        * moment, we could end up with a use-after-free. Fortunately,
+        * the CEC framework already handles this too, by calling
+        * cec_is_registered() in cec_ioctl() and cec_poll().
+        */
+       ret = devm_add_action_or_reset(dev, vc4_hdmi_cec_release, vc4_hdmi);
+       if (ret)
+               return ret;
 
-err_remove_cec_rx_handler:
-       if (vc4_hdmi->variant->external_irq_controller)
-               free_irq(platform_get_irq_byname(pdev, "cec-rx"), vc4_hdmi);
+       return 0;
 
 err_delete_cec_adap:
        cec_delete_adapter(vc4_hdmi->cec_adap);
 
        return ret;
 }
-
-static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi)
-{
-       struct platform_device *pdev = vc4_hdmi->pdev;
-
-       if (vc4_hdmi->variant->external_irq_controller) {
-               free_irq(platform_get_irq_byname(pdev, "cec-rx"), vc4_hdmi);
-               free_irq(platform_get_irq_byname(pdev, "cec-tx"), vc4_hdmi);
-       } else {
-               free_irq(platform_get_irq(pdev, 0), vc4_hdmi);
-       }
-
-       cec_unregister_adapter(vc4_hdmi->cec_adap);
-}
 #else
 static int vc4_hdmi_cec_init(struct vc4_hdmi *vc4_hdmi)
 {
        return 0;
 }
-
-static void vc4_hdmi_cec_exit(struct vc4_hdmi *vc4_hdmi) {};
 #endif
 
-static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
+static void vc4_hdmi_free_regset(struct drm_device *drm, void *ptr)
+{
+       struct debugfs_reg32 *regs = ptr;
+
+       kfree(regs);
+}
+
+static int vc4_hdmi_build_regset(struct drm_device *drm,
+                                struct vc4_hdmi *vc4_hdmi,
                                 struct debugfs_regset32 *regset,
                                 enum vc4_hdmi_regs reg)
 {
@@ -2649,6 +2993,7 @@ static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
        struct debugfs_reg32 *regs, *new_regs;
        unsigned int count = 0;
        unsigned int i;
+       int ret;
 
        regs = kcalloc(variant->num_registers, sizeof(*regs),
                       GFP_KERNEL);
@@ -2674,10 +3019,15 @@ static int vc4_hdmi_build_regset(struct vc4_hdmi *vc4_hdmi,
        regset->regs = new_regs;
        regset->nregs = count;
 
+       ret = drmm_add_action_or_reset(drm, vc4_hdmi_free_regset, new_regs);
+       if (ret)
+               return ret;
+
        return 0;
 }
 
-static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+static int vc4_hdmi_init_resources(struct drm_device *drm,
+                                  struct vc4_hdmi *vc4_hdmi)
 {
        struct platform_device *pdev = vc4_hdmi->pdev;
        struct device *dev = &pdev->dev;
@@ -2691,11 +3041,11 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
        if (IS_ERR(vc4_hdmi->hd_regs))
                return PTR_ERR(vc4_hdmi->hd_regs);
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
        if (ret)
                return ret;
 
@@ -2718,7 +3068,8 @@ static int vc4_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
        return 0;
 }
 
-static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
+static int vc5_hdmi_init_resources(struct drm_device *drm,
+                                  struct vc4_hdmi *vc4_hdmi)
 {
        struct platform_device *pdev = vc4_hdmi->pdev;
        struct device *dev = &pdev->dev;
@@ -2820,42 +3171,42 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
                return PTR_ERR(vc4_hdmi->reset);
        }
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hdmi_regset, VC4_HDMI);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->hd_regset, VC4_HD);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->cec_regset, VC5_CEC);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->csc_regset, VC5_CSC);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->dvp_regset, VC5_DVP);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->phy_regset, VC5_PHY);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->ram_regset, VC5_RAM);
        if (ret)
                return ret;
 
-       ret = vc4_hdmi_build_regset(vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM);
+       ret = vc4_hdmi_build_regset(drm, vc4_hdmi, &vc4_hdmi->rm_regset, VC5_RM);
        if (ret)
                return ret;
 
        return 0;
 }
 
-static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev)
+static int vc4_hdmi_runtime_suspend(struct device *dev)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
 
@@ -2898,6 +3249,13 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
        return 0;
 }
 
+static void vc4_hdmi_put_ddc_device(void *ptr)
+{
+       struct vc4_hdmi *vc4_hdmi = ptr;
+
+       put_device(&vc4_hdmi->ddc->dev);
+}
+
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev);
@@ -2908,10 +3266,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
        struct device_node *ddc_node;
        int ret;
 
-       vc4_hdmi = devm_kzalloc(dev, sizeof(*vc4_hdmi), GFP_KERNEL);
+       vc4_hdmi = drmm_kzalloc(drm, sizeof(*vc4_hdmi), GFP_KERNEL);
        if (!vc4_hdmi)
                return -ENOMEM;
-       mutex_init(&vc4_hdmi->mutex);
+
+       ret = drmm_mutex_init(drm, &vc4_hdmi->mutex);
+       if (ret)
+               return ret;
+
        spin_lock_init(&vc4_hdmi->hw_lock);
        INIT_DELAYED_WORK(&vc4_hdmi->scrambling_work, vc4_hdmi_scrambling_wq);
 
@@ -2935,7 +3297,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
        if (variant->max_pixel_clock > HDMI_14_MAX_TMDS_CLK)
                vc4_hdmi->scdc_enabled = true;
 
-       ret = variant->init_resources(vc4_hdmi);
+       ret = variant->init_resources(drm, vc4_hdmi);
        if (ret)
                return ret;
 
@@ -2952,13 +3314,16 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                return -EPROBE_DEFER;
        }
 
+       ret = devm_add_action_or_reset(dev, vc4_hdmi_put_ddc_device, vc4_hdmi);
+       if (ret)
+               return ret;
+
        /* Only use the GPIO HPD pin if present in the DT, otherwise
         * we'll use the HDMI core's register.
         */
        vc4_hdmi->hpd_gpio = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
        if (IS_ERR(vc4_hdmi->hpd_gpio)) {
-               ret = PTR_ERR(vc4_hdmi->hpd_gpio);
-               goto err_put_ddc;
+               return PTR_ERR(vc4_hdmi->hpd_gpio);
        }
 
        vc4_hdmi->disable_wifi_frequencies =
@@ -2972,17 +3337,17 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                        vc4_hdmi->disable_4kp60 = true;
        }
 
+       ret = devm_pm_runtime_enable(dev);
+       if (ret)
+               return ret;
+
        /*
-        * We need to have the device powered up at this point to call
-        * our reset hook and for the CEC init.
+        *  We need to have the device powered up at this point to call
+        *  our reset hook and for the CEC init.
         */
-       ret = vc4_hdmi_runtime_resume(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret)
-               goto err_put_ddc;
-
-       pm_runtime_get_noresume(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
+               return ret;
 
        if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
             of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
@@ -2992,92 +3357,43 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                clk_prepare_enable(vc4_hdmi->pixel_bvb_clock);
        }
 
-       drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
+       ret = drmm_encoder_init(drm, encoder,
+                               &vc4_hdmi_encoder_funcs,
+                               DRM_MODE_ENCODER_TMDS,
+                               NULL);
+       if (ret)
+               goto err_put_runtime_pm;
+
        drm_encoder_helper_add(encoder, &vc4_hdmi_encoder_helper_funcs);
 
        ret = vc4_hdmi_connector_init(drm, vc4_hdmi);
        if (ret)
-               goto err_destroy_encoder;
+               goto err_put_runtime_pm;
 
        ret = vc4_hdmi_hotplug_init(vc4_hdmi);
        if (ret)
-               goto err_destroy_conn;
+               goto err_put_runtime_pm;
 
        ret = vc4_hdmi_cec_init(vc4_hdmi);
        if (ret)
-               goto err_free_hotplug;
+               goto err_put_runtime_pm;
 
        ret = vc4_hdmi_audio_init(vc4_hdmi);
        if (ret)
-               goto err_free_cec;
-
-       vc4_debugfs_add_file(drm, variant->debugfs_name,
-                            vc4_hdmi_debugfs_regs,
-                            vc4_hdmi);
+               goto err_put_runtime_pm;
 
        pm_runtime_put_sync(dev);
 
        return 0;
 
-err_free_cec:
-       vc4_hdmi_cec_exit(vc4_hdmi);
-err_free_hotplug:
-       vc4_hdmi_hotplug_exit(vc4_hdmi);
-err_destroy_conn:
-       vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
-err_destroy_encoder:
-       drm_encoder_cleanup(encoder);
+err_put_runtime_pm:
        pm_runtime_put_sync(dev);
-       pm_runtime_disable(dev);
-err_put_ddc:
-       put_device(&vc4_hdmi->ddc->dev);
 
        return ret;
 }
 
-static void vc4_hdmi_unbind(struct device *dev, struct device *master,
-                           void *data)
-{
-       struct vc4_hdmi *vc4_hdmi;
-
-       /*
-        * ASoC makes it a bit hard to retrieve a pointer to the
-        * vc4_hdmi structure. Registering the card will overwrite our
-        * device drvdata with a pointer to the snd_soc_card structure,
-        * which can then be used to retrieve whatever drvdata we want
-        * to associate.
-        *
-        * However, that doesn't fly in the case where we wouldn't
-        * register an ASoC card (because of an old DT that is missing
-        * the dmas properties for example), then the card isn't
-        * registered and the device drvdata wouldn't be set.
-        *
-        * We can deal with both cases by making sure a snd_soc_card
-        * pointer and a vc4_hdmi structure are pointing to the same
-        * memory address, so we can treat them indistinctly without any
-        * issue.
-        */
-       BUILD_BUG_ON(offsetof(struct vc4_hdmi_audio, card) != 0);
-       BUILD_BUG_ON(offsetof(struct vc4_hdmi, audio) != 0);
-       vc4_hdmi = dev_get_drvdata(dev);
-
-       kfree(vc4_hdmi->hdmi_regset.regs);
-       kfree(vc4_hdmi->hd_regset.regs);
-
-       vc4_hdmi_audio_exit(vc4_hdmi);
-       vc4_hdmi_cec_exit(vc4_hdmi);
-       vc4_hdmi_hotplug_exit(vc4_hdmi);
-       vc4_hdmi_connector_destroy(&vc4_hdmi->connector);
-       drm_encoder_cleanup(&vc4_hdmi->encoder.base);
-
-       pm_runtime_disable(dev);
-
-       put_device(&vc4_hdmi->ddc->dev);
-}
-
 static const struct component_ops vc4_hdmi_ops = {
        .bind   = vc4_hdmi_bind,
-       .unbind = vc4_hdmi_unbind,
 };
 
 static int vc4_hdmi_dev_probe(struct platform_device *pdev)
index c3ed2b07df235527992f51e66511366855c94924..99b0bc1297be8c6d5e1d40c940f87e0de5116010 100644 (file)
@@ -58,7 +58,8 @@ struct vc4_hdmi_variant {
        /* Callback to get the resources (memory region, interrupts,
         * clocks, etc) for that variant.
         */
-       int (*init_resources)(struct vc4_hdmi *vc4_hdmi);
+       int (*init_resources)(struct drm_device *drm,
+                             struct vc4_hdmi *vc4_hdmi);
 
        /* Callback to reset the HDMI block */
        void (*reset)(struct vc4_hdmi *vc4_hdmi);
index fbaa741dda5f98badb605439956a783de8b35058..9e823e0de197c7212ed4fb5bb9103b367d6d8972 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/platform_device.h>
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_vblank.h>
 
 #include "vc4_drv.h"
@@ -66,11 +67,15 @@ static const struct debugfs_reg32 hvs_regs[] = {
 
 void vc4_hvs_dump_state(struct vc4_hvs *hvs)
 {
+       struct drm_device *drm = &hvs->vc4->base;
        struct drm_printer p = drm_info_printer(&hvs->pdev->dev);
-       int i;
+       int idx, i;
 
        drm_print_regset32(&p, &hvs->regset);
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        DRM_INFO("HVS ctx:\n");
        for (i = 0; i < 64; i += 4) {
                DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
@@ -80,6 +85,8 @@ void vc4_hvs_dump_state(struct vc4_hvs *hvs)
                         readl((u32 __iomem *)hvs->dlist + i + 2),
                         readl((u32 __iomem *)hvs->dlist + i + 3));
        }
+
+       drm_dev_exit(idx);
 }
 
 static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
@@ -175,6 +182,11 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
        int ret, i;
        u32 __iomem *dst_kernel;
 
+       /*
+        * NOTE: We don't need a call to drm_dev_enter()/drm_dev_exit()
+        * here since that function is only called from vc4_hvs_bind().
+        */
+
        ret = drm_mm_insert_node(&hvs->dlist_mm, space, VC4_KERNEL_DWORDS);
        if (ret) {
                DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
@@ -199,10 +211,15 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs *hvs,
 static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
                             struct vc4_crtc *vc4_crtc)
 {
+       struct drm_device *drm = &hvs->vc4->base;
        struct drm_crtc *crtc = &vc4_crtc->base;
        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+       int idx;
        u32 i;
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        /* The LUT memory is laid out with each HVS channel in order,
         * each of which takes 256 writes for R, 256 for G, then 256
         * for B.
@@ -217,6 +234,8 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
                HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
        for (i = 0; i < crtc->gamma_size; i++)
                HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
@@ -238,7 +257,12 @@ static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
 
 u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
 {
+       struct drm_device *drm = &hvs->vc4->base;
        u8 field = 0;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return 0;
 
        switch (fifo) {
        case 0:
@@ -255,6 +279,7 @@ u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
                break;
        }
 
+       drm_dev_exit(idx);
        return field;
 }
 
@@ -267,6 +292,12 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
        if (!vc4->is_vc5)
                return output;
 
+       /*
+        * NOTE: We should probably use drm_dev_enter()/drm_dev_exit()
+        * here, but this function is only used during the DRM device
+        * initialization, so we should be fine.
+        */
+
        switch (output) {
        case 0:
                return 0;
@@ -315,12 +346,17 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
                                struct drm_display_mode *mode, bool oneshot)
 {
        struct vc4_dev *vc4 = hvs->vc4;
+       struct drm_device *drm = &vc4->base;
        struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
        struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
        unsigned int chan = vc4_crtc_state->assigned_channel;
        bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE;
        u32 dispbkgndx;
        u32 dispctrl;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return -ENODEV;
 
        HVS_WRITE(SCALER_DISPCTRLX(chan), 0);
        HVS_WRITE(SCALER_DISPCTRLX(chan), SCALER_DISPCTRLX_RESET);
@@ -362,14 +398,22 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
         */
        vc4_hvs_lut_load(hvs, vc4_crtc);
 
+       drm_dev_exit(idx);
+
        return 0;
 }
 
 void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan)
 {
-       if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
+       struct drm_device *drm = &hvs->vc4->base;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
                return;
 
+       if (HVS_READ(SCALER_DISPCTRLX(chan)) & SCALER_DISPCTRLX_ENABLE)
+               goto out;
+
        HVS_WRITE(SCALER_DISPCTRLX(chan),
                  HVS_READ(SCALER_DISPCTRLX(chan)) | SCALER_DISPCTRLX_RESET);
        HVS_WRITE(SCALER_DISPCTRLX(chan),
@@ -385,6 +429,9 @@ void vc4_hvs_stop_channel(struct vc4_hvs *hvs, unsigned int chan)
        WARN_ON_ONCE((HVS_READ(SCALER_DISPSTATX(chan)) &
                      (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) !=
                     SCALER_DISPSTATX_EMPTY);
+
+out:
+       drm_dev_exit(idx);
 }
 
 int vc4_hvs_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
@@ -426,9 +473,15 @@ static void vc4_hvs_install_dlist(struct drm_crtc *crtc)
        struct vc4_dev *vc4 = to_vc4_dev(dev);
        struct vc4_hvs *hvs = vc4->hvs;
        struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
+       int idx;
+
+       if (!drm_dev_enter(dev, &idx))
+               return;
 
        HVS_WRITE(SCALER_DISPLISTX(vc4_state->assigned_channel),
                  vc4_state->mm.start);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hvs_update_dlist(struct drm_crtc *crtc)
@@ -513,6 +566,12 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
        bool enable_bg_fill = false;
        u32 __iomem *dlist_start = vc4->hvs->dlist + vc4_state->mm.start;
        u32 __iomem *dlist_next = dlist_start;
+       int idx;
+
+       if (!drm_dev_enter(dev, &idx)) {
+               vc4_crtc_send_vblank(crtc);
+               return;
+       }
 
        if (debug_dump_regs) {
                DRM_INFO("CRTC %d HVS before:\n", drm_crtc_index(crtc));
@@ -583,26 +642,44 @@ void vc4_hvs_atomic_flush(struct drm_crtc *crtc,
                DRM_INFO("CRTC %d HVS after:\n", drm_crtc_index(crtc));
                vc4_hvs_dump_state(hvs);
        }
+
+       drm_dev_exit(idx);
 }
 
 void vc4_hvs_mask_underrun(struct vc4_hvs *hvs, int channel)
 {
-       u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
+       struct drm_device *drm = &hvs->vc4->base;
+       u32 dispctrl;
+       int idx;
 
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       dispctrl = HVS_READ(SCALER_DISPCTRL);
        dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
 
        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
+
+       drm_dev_exit(idx);
 }
 
 void vc4_hvs_unmask_underrun(struct vc4_hvs *hvs, int channel)
 {
-       u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
+       struct drm_device *drm = &hvs->vc4->base;
+       u32 dispctrl;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
+       dispctrl = HVS_READ(SCALER_DISPCTRL);
        dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
 
        HVS_WRITE(SCALER_DISPSTAT,
                  SCALER_DISPSTAT_EUFLOW(channel));
        HVS_WRITE(SCALER_DISPCTRL, dispctrl);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_hvs_report_underrun(struct drm_device *dev)
@@ -623,6 +700,17 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
        u32 control;
        u32 status;
 
+       /*
+        * NOTE: We don't need to protect the register access using
+        * drm_dev_enter() there because the interrupt handler lifetime
+        * is tied to the device itself, and not to the DRM device.
+        *
+        * So when the device will be gone, one of the first thing we
+        * will be doing will be to unregister the interrupt handler,
+        * and then unregister the DRM device. drm_dev_enter() would
+        * thus always succeed if we are here.
+        */
+
        status = HVS_READ(SCALER_DISPSTAT);
        control = HVS_READ(SCALER_DISPCTRL);
 
@@ -645,6 +733,39 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
        return irqret;
 }
 
+int vc4_hvs_debugfs_init(struct drm_minor *minor)
+{
+       struct drm_device *drm = minor->dev;
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
+       struct vc4_hvs *hvs = vc4->hvs;
+       int ret;
+
+       if (!vc4->hvs)
+               return -ENODEV;
+
+       if (!vc4->is_vc5)
+               debugfs_create_bool("hvs_load_tracker", S_IRUGO | S_IWUSR,
+                                   minor->debugfs_root,
+                                   &vc4->load_tracker_enabled);
+
+       ret = vc4_debugfs_add_file(minor, "hvs_dlists",
+                                  vc4_hvs_debugfs_dlist, NULL);
+       if (ret)
+               return ret;
+
+       ret = vc4_debugfs_add_file(minor, "hvs_underrun",
+                                  vc4_hvs_debugfs_underrun, NULL);
+       if (ret)
+               return ret;
+
+       ret = vc4_debugfs_add_regset32(minor, "hvs_regs",
+                                      &hvs->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -655,10 +776,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
        u32 dispctrl;
        u32 reg;
 
-       hvs = devm_kzalloc(&pdev->dev, sizeof(*hvs), GFP_KERNEL);
+       hvs = drmm_kzalloc(drm, sizeof(*hvs), GFP_KERNEL);
        if (!hvs)
                return -ENOMEM;
-
        hvs->vc4 = vc4;
        hvs->pdev = pdev;
 
@@ -771,12 +891,6 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
        if (ret)
                return ret;
 
-       vc4_debugfs_add_regset32(drm, "hvs_regs", &hvs->regset);
-       vc4_debugfs_add_file(drm, "hvs_underrun", vc4_hvs_debugfs_underrun,
-                            NULL);
-       vc4_debugfs_add_file(drm, "hvs_dlists", vc4_hvs_debugfs_dlist,
-                            NULL);
-
        return 0;
 }
 
@@ -786,11 +900,18 @@ static void vc4_hvs_unbind(struct device *dev, struct device *master,
        struct drm_device *drm = dev_get_drvdata(master);
        struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_hvs *hvs = vc4->hvs;
+       struct drm_mm_node *node, *next;
 
        if (drm_mm_node_allocated(&vc4->hvs->mitchell_netravali_filter))
                drm_mm_remove_node(&vc4->hvs->mitchell_netravali_filter);
 
+       drm_mm_for_each_node_safe(node, next, &vc4->hvs->dlist_mm)
+               drm_mm_remove_node(node);
+
        drm_mm_takedown(&vc4->hvs->dlist_mm);
+
+       drm_mm_for_each_node_safe(node, next, &vc4->hvs->lbm_mm)
+               drm_mm_remove_node(node);
        drm_mm_takedown(&vc4->hvs->lbm_mm);
 
        clk_disable_unprepare(hvs->core_clk);
index 2eacfb6773d28600608589b0264ac63b03c25178..1e6db0121ccd5f9aebfbeffe9abc891f7fe4679a 100644 (file)
@@ -105,7 +105,7 @@ vc4_overflow_mem_work(struct work_struct *work)
        }
        vc4->bin_alloc_overflow = BIT(bin_bo_slot);
 
-       V3D_WRITE(V3D_BPOA, bo->base.paddr + bin_bo_slot * vc4->bin_alloc_size);
+       V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size);
        V3D_WRITE(V3D_BPOS, bo->base.base.size);
        V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM);
        V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM);
@@ -295,7 +295,7 @@ vc4_irq_disable(struct drm_device *dev)
        V3D_WRITE(V3D_INTCTL, V3D_DRIVER_IRQS);
 
        /* Finish any interrupt handler still in flight. */
-       disable_irq(vc4->irq);
+       synchronize_irq(vc4->irq);
 
        cancel_work_sync(&vc4->overflow_mem_work);
 }
index b45dcdfd73064ae8f59035f663624a282ee674ee..4419e810103de3e77525163226d7bbd7270d5b9b 100644 (file)
@@ -18,7 +18,6 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_vblank.h>
 
index 79a74184d732804f7f168c8fd1f44b5003d36376..c4ac2c946238150f9897f9eb81cfbab3764ee630 100644 (file)
@@ -133,6 +133,7 @@ void vc4_perfmon_close_file(struct vc4_file *vc4file)
        idr_for_each(&vc4file->perfmon.idr, vc4_perfmon_idr_del, NULL);
        idr_destroy(&vc4file->perfmon.idr);
        mutex_unlock(&vc4file->perfmon.lock);
+       mutex_destroy(&vc4file->perfmon.lock);
 }
 
 int vc4_perfmon_create_ioctl(struct drm_device *dev, void *data,
index f27e87a23df77c4daa2b22c8247be317cf7bb310..eff9c63adfa78ded6f167e7ad2bd4137918036bc 100644 (file)
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_atomic_uapi.h>
 #include <drm/drm_blend.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_gem_atomic_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "uapi/drm/vc4_drm.h"
 
@@ -340,7 +339,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
 {
        struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
        struct drm_framebuffer *fb = state->fb;
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0);
        int num_planes = fb->format->num_planes;
        struct drm_crtc_state *crtc_state;
        u32 h_subsample = fb->format->hsub;
@@ -360,7 +359,7 @@ static int vc4_plane_setup_clipping_and_scaling(struct drm_plane_state *state)
                return ret;
 
        for (i = 0; i < num_planes; i++)
-               vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
+               vc4_state->offsets[i] = bo->dma_addr + fb->offsets[i];
 
        /*
         * We don't support subpixel source positioning for scaling,
@@ -1244,14 +1243,14 @@ u32 vc4_plane_dlist_size(const struct drm_plane_state *state)
 void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)
 {
        struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
-       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
+       struct drm_gem_dma_object *bo = drm_fb_dma_get_gem_obj(fb, 0);
        uint32_t addr;
 
        /* We're skipping the address adjustment for negative origin,
         * because this is only called on the primary plane.
         */
        WARN_ON_ONCE(plane->state->crtc_x < 0 || plane->state->crtc_y < 0);
-       addr = bo->paddr + fb->offsets[0];
+       addr = bo->dma_addr + fb->offsets[0];
 
        /* Write the new address into the hardware immediately.  The
         * scanout will start from this address as soon as the FIFO
@@ -1388,7 +1387,7 @@ static int vc4_prepare_fb(struct drm_plane *plane,
        if (!state->fb)
                return 0;
 
-       bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base);
+       bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base);
 
        drm_gem_plane_helper_prepare_fb(plane, state);
 
@@ -1406,7 +1405,7 @@ static void vc4_cleanup_fb(struct drm_plane *plane,
        if (plane->state->fb == state->fb || !state->fb)
                return;
 
-       bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base);
+       bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base);
        vc4_bo_dec_usecnt(bo);
 }
 
@@ -1483,8 +1482,6 @@ static bool vc4_format_mod_supported(struct drm_plane *plane,
 static const struct drm_plane_funcs vc4_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
-       .destroy = drm_plane_cleanup,
-       .set_property = NULL,
        .reset = vc4_plane_reset,
        .atomic_duplicate_state = vc4_plane_duplicate_state,
        .atomic_destroy_state = vc4_plane_destroy_state,
@@ -1492,14 +1489,14 @@ static const struct drm_plane_funcs vc4_plane_funcs = {
 };
 
 struct drm_plane *vc4_plane_init(struct drm_device *dev,
-                                enum drm_plane_type type)
+                                enum drm_plane_type type,
+                                uint32_t possible_crtcs)
 {
        struct vc4_dev *vc4 = to_vc4_dev(dev);
-       struct drm_plane *plane = NULL;
+       struct drm_plane *plane;
        struct vc4_plane *vc4_plane;
        u32 formats[ARRAY_SIZE(hvs_formats)];
        int num_formats = 0;
-       int ret = 0;
        unsigned i;
        static const uint64_t modifiers[] = {
                DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
@@ -1510,11 +1507,6 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
                DRM_FORMAT_MOD_INVALID
        };
 
-       vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
-                                GFP_KERNEL);
-       if (!vc4_plane)
-               return ERR_PTR(-ENOMEM);
-
        for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
                if (!hvs_formats[i].hvs5_only || vc4->is_vc5) {
                        formats[num_formats] = hvs_formats[i].drm;
@@ -1522,13 +1514,14 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
                }
        }
 
+       vc4_plane = drmm_universal_plane_alloc(dev, struct vc4_plane, base,
+                                              possible_crtcs,
+                                              &vc4_plane_funcs,
+                                              formats, num_formats,
+                                              modifiers, type, NULL);
+       if (IS_ERR(vc4_plane))
+               return ERR_CAST(vc4_plane);
        plane = &vc4_plane->base;
-       ret = drm_universal_plane_init(dev, plane, 0,
-                                      &vc4_plane_funcs,
-                                      formats, num_formats,
-                                      modifiers, type, NULL);
-       if (ret)
-               return ERR_PTR(ret);
 
        if (vc4->is_vc5)
                drm_plane_helper_add(plane, &vc5_plane_helper_funcs);
@@ -1575,13 +1568,11 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
         */
        for (i = 0; i < 16; i++) {
                struct drm_plane *plane =
-                       vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
+                       vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
+                                      GENMASK(drm->mode_config.num_crtc - 1, 0));
 
                if (IS_ERR(plane))
                        continue;
-
-               plane->possible_crtcs =
-                       GENMASK(drm->mode_config.num_crtc - 1, 0);
        }
 
        drm_for_each_crtc(crtc, drm) {
@@ -1589,9 +1580,9 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
                 * since we overlay planes on the CRTC in the order they were
                 * initialized.
                 */
-               cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
+               cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
+                                             drm_crtc_mask(crtc));
                if (!IS_ERR(cursor_plane)) {
-                       cursor_plane->possible_crtcs = drm_crtc_mask(crtc);
                        crtc->cursor = cursor_plane;
                }
        }
index f6b7dc3df08cd52c6f778b14cd02aac74b0ffb6e..1bda5010f15a8673239583e1bb4fa00f2e12cdeb 100644 (file)
 #include "vc4_packet.h"
 
 struct vc4_rcl_setup {
-       struct drm_gem_cma_object *color_read;
-       struct drm_gem_cma_object *color_write;
-       struct drm_gem_cma_object *zs_read;
-       struct drm_gem_cma_object *zs_write;
-       struct drm_gem_cma_object *msaa_color_write;
-       struct drm_gem_cma_object *msaa_zs_write;
-
-       struct drm_gem_cma_object *rcl;
+       struct drm_gem_dma_object *color_read;
+       struct drm_gem_dma_object *color_write;
+       struct drm_gem_dma_object *zs_read;
+       struct drm_gem_dma_object *zs_write;
+       struct drm_gem_dma_object *msaa_color_write;
+       struct drm_gem_dma_object *msaa_zs_write;
+
+       struct drm_gem_dma_object *rcl;
        u32 next_offset;
 
        u32 next_write_bo_index;
@@ -97,11 +97,11 @@ static void vc4_store_before_load(struct vc4_rcl_setup *setup)
  * coordinates packet, and instead just store to the address given.
  */
 static uint32_t vc4_full_res_offset(struct vc4_exec_info *exec,
-                                   struct drm_gem_cma_object *bo,
+                                   struct drm_gem_dma_object *bo,
                                    struct drm_vc4_submit_rcl_surface *surf,
                                    uint8_t x, uint8_t y)
 {
-       return bo->paddr + surf->offset + VC4_TILE_BUFFER_SIZE *
+       return bo->dma_addr + surf->offset + VC4_TILE_BUFFER_SIZE *
                (DIV_ROUND_UP(exec->args->width, 32) * y + x);
 }
 
@@ -142,7 +142,7 @@ static void emit_tile(struct vc4_exec_info *exec,
                } else {
                        rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
                        rcl_u16(setup, args->color_read.bits);
-                       rcl_u32(setup, setup->color_read->paddr +
+                       rcl_u32(setup, setup->color_read->dma_addr +
                                args->color_read.offset);
                }
        }
@@ -164,7 +164,7 @@ static void emit_tile(struct vc4_exec_info *exec,
                } else {
                        rcl_u8(setup, VC4_PACKET_LOAD_TILE_BUFFER_GENERAL);
                        rcl_u16(setup, args->zs_read.bits);
-                       rcl_u32(setup, setup->zs_read->paddr +
+                       rcl_u32(setup, setup->zs_read->dma_addr +
                                args->zs_read.offset);
                }
        }
@@ -232,7 +232,7 @@ static void emit_tile(struct vc4_exec_info *exec,
                        (last_tile_write ?
                         0 : VC4_STORE_TILE_BUFFER_DISABLE_COLOR_CLEAR));
                rcl_u32(setup,
-                       (setup->zs_write->paddr + args->zs_write.offset) |
+                       (setup->zs_write->dma_addr + args->zs_write.offset) |
                        ((last && last_tile_write) ?
                         VC4_LOADSTORE_TILE_BUFFER_EOF : 0));
        }
@@ -355,7 +355,7 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
 
        rcl_u8(setup, VC4_PACKET_TILE_RENDERING_MODE_CONFIG);
        rcl_u32(setup,
-               (setup->color_write ? (setup->color_write->paddr +
+               (setup->color_write ? (setup->color_write->dma_addr +
                                       args->color_write.offset) :
                 0));
        rcl_u16(setup, args->width);
@@ -374,14 +374,14 @@ static int vc4_create_rcl_bo(struct drm_device *dev, struct vc4_exec_info *exec,
        }
 
        BUG_ON(setup->next_offset != size);
-       exec->ct1ca = setup->rcl->paddr;
-       exec->ct1ea = setup->rcl->paddr + setup->next_offset;
+       exec->ct1ca = setup->rcl->dma_addr;
+       exec->ct1ea = setup->rcl->dma_addr + setup->next_offset;
 
        return 0;
 }
 
 static int vc4_full_res_bounds_check(struct vc4_exec_info *exec,
-                                    struct drm_gem_cma_object *obj,
+                                    struct drm_gem_dma_object *obj,
                                     struct drm_vc4_submit_rcl_surface *surf)
 {
        struct drm_vc4_submit_cl *args = exec->args;
@@ -407,7 +407,7 @@ static int vc4_full_res_bounds_check(struct vc4_exec_info *exec,
 }
 
 static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec,
-                                     struct drm_gem_cma_object **obj,
+                                     struct drm_gem_dma_object **obj,
                                      struct drm_vc4_submit_rcl_surface *surf)
 {
        if (surf->flags != 0 || surf->bits != 0) {
@@ -433,7 +433,7 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec,
 }
 
 static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
-                                struct drm_gem_cma_object **obj,
+                                struct drm_gem_dma_object **obj,
                                 struct drm_vc4_submit_rcl_surface *surf,
                                 bool is_write)
 {
@@ -533,7 +533,7 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec,
 static int
 vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec,
                                    struct vc4_rcl_setup *setup,
-                                   struct drm_gem_cma_object **obj,
+                                   struct drm_gem_dma_object **obj,
                                    struct drm_vc4_submit_rcl_surface *surf)
 {
        uint8_t tiling = VC4_GET_FIELD(surf->bits,
index d20b0bc51a18632cd2f200a9530684f0bf95bf78..bd181b5a7b520dc132fcafd36d853f258b552f65 100644 (file)
@@ -15,8 +15,9 @@
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_panel.h>
@@ -155,7 +156,6 @@ struct vc4_txp {
        struct drm_writeback_connector connector;
 
        void __iomem *regs;
-       struct debugfs_regset32 regset;
 };
 
 static inline struct vc4_txp *encoder_to_vc4_txp(struct drm_encoder *encoder)
@@ -276,13 +276,15 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn,
 static void vc4_txp_connector_atomic_commit(struct drm_connector *conn,
                                        struct drm_atomic_state *state)
 {
+       struct drm_device *drm = conn->dev;
        struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state,
                                                                                    conn);
        struct vc4_txp *txp = connector_to_vc4_txp(conn);
-       struct drm_gem_cma_object *gem;
+       struct drm_gem_dma_object *gem;
        struct drm_display_mode *mode;
        struct drm_framebuffer *fb;
        u32 ctrl;
+       int idx;
        int i;
 
        if (WARN_ON(!conn_state->writeback_job))
@@ -312,8 +314,11 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn,
                 */
                ctrl |= TXP_ALPHA_INVERT;
 
-       gem = drm_fb_cma_get_gem_obj(fb, 0);
-       TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]);
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
+       gem = drm_fb_dma_get_gem_obj(fb, 0);
+       TXP_WRITE(TXP_DST_PTR, gem->dma_addr + fb->offsets[0]);
        TXP_WRITE(TXP_DST_PITCH, fb->pitches[0]);
        TXP_WRITE(TXP_DIM,
                  VC4_SET_FIELD(mode->hdisplay, TXP_WIDTH) |
@@ -322,6 +327,8 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn,
        TXP_WRITE(TXP_DST_CTRL, ctrl);
 
        drm_writeback_queue_job(&txp->connector, conn_state);
+
+       drm_dev_exit(idx);
 }
 
 static const struct drm_connector_helper_funcs vc4_txp_connector_helper_funcs = {
@@ -337,16 +344,10 @@ vc4_txp_connector_detect(struct drm_connector *connector, bool force)
        return connector_status_connected;
 }
 
-static void vc4_txp_connector_destroy(struct drm_connector *connector)
-{
-       drm_connector_unregister(connector);
-       drm_connector_cleanup(connector);
-}
-
 static const struct drm_connector_funcs vc4_txp_connector_funcs = {
        .detect = vc4_txp_connector_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_txp_connector_destroy,
+       .destroy = drm_connector_cleanup,
        .reset = drm_atomic_helper_connector_reset,
        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -354,7 +355,12 @@ static const struct drm_connector_funcs vc4_txp_connector_funcs = {
 
 static void vc4_txp_encoder_disable(struct drm_encoder *encoder)
 {
+       struct drm_device *drm = encoder->dev;
        struct vc4_txp *txp = encoder_to_vc4_txp(encoder);
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        if (TXP_READ(TXP_DST_CTRL) & TXP_BUSY) {
                unsigned long timeout = jiffies + msecs_to_jiffies(1000);
@@ -369,6 +375,8 @@ static void vc4_txp_encoder_disable(struct drm_encoder *encoder)
        }
 
        TXP_WRITE(TXP_DST_CTRL, TXP_POWERDOWN);
+
+       drm_dev_exit(idx);
 }
 
 static const struct drm_encoder_helper_funcs vc4_txp_encoder_helper_funcs = {
@@ -384,13 +392,13 @@ static void vc4_txp_disable_vblank(struct drm_crtc *crtc) {}
 
 static const struct drm_crtc_funcs vc4_txp_crtc_funcs = {
        .set_config             = drm_atomic_helper_set_config,
-       .destroy                = vc4_crtc_destroy,
        .page_flip              = vc4_page_flip,
        .reset                  = vc4_crtc_reset,
        .atomic_duplicate_state = vc4_crtc_duplicate_state,
        .atomic_destroy_state   = vc4_crtc_destroy_state,
        .enable_vblank          = vc4_txp_enable_vblank,
        .disable_vblank         = vc4_txp_disable_vblank,
+       .late_register          = vc4_crtc_late_register,
 };
 
 static int vc4_txp_atomic_check(struct drm_crtc *crtc,
@@ -453,6 +461,16 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
        struct vc4_txp *txp = data;
        struct vc4_crtc *vc4_crtc = &txp->base;
 
+       /*
+        * We don't need to protect the register access using
+        * drm_dev_enter() there because the interrupt handler lifetime
+        * is tied to the device itself, and not to the DRM device.
+        *
+        * So when the device will be gone, one of the first thing we
+        * will be doing will be to unregister the interrupt handler,
+        * and then unregister the DRM device. drm_dev_enter() would
+        * thus always succeed if we are here.
+        */
        TXP_WRITE(TXP_DST_CTRL, TXP_READ(TXP_DST_CTRL) & ~TXP_EI);
        vc4_crtc_handle_vblank(vc4_crtc);
        drm_writeback_signal_completion(&txp->connector, 0);
@@ -461,6 +479,7 @@ static irqreturn_t vc4_txp_interrupt(int irq, void *data)
 }
 
 static const struct vc4_crtc_data vc4_txp_crtc_data = {
+       .debugfs_name = "txp_regs",
        .hvs_available_channels = BIT(2),
        .hvs_output = 2,
 };
@@ -469,7 +488,6 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_crtc *vc4_crtc;
        struct vc4_txp *txp;
        struct drm_crtc *crtc;
@@ -480,7 +498,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
        if (irq < 0)
                return irq;
 
-       txp = devm_kzalloc(dev, sizeof(*txp), GFP_KERNEL);
+       txp = drmm_kzalloc(drm, sizeof(*txp), GFP_KERNEL);
        if (!txp)
                return -ENOMEM;
        vc4_crtc = &txp->base;
@@ -495,9 +513,9 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
        txp->regs = vc4_ioremap_regs(pdev, 0);
        if (IS_ERR(txp->regs))
                return PTR_ERR(txp->regs);
-       txp->regset.base = txp->regs;
-       txp->regset.regs = txp_regs;
-       txp->regset.nregs = ARRAY_SIZE(txp_regs);
+       vc4_crtc->regset.base = txp->regs;
+       vc4_crtc->regset.regs = txp_regs;
+       vc4_crtc->regset.nregs = ARRAY_SIZE(txp_regs);
 
        drm_connector_helper_add(&txp->connector.base,
                                 &vc4_txp_connector_helper_funcs);
@@ -523,9 +541,6 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
                return ret;
 
        dev_set_drvdata(dev, txp);
-       vc4->txp = txp;
-
-       vc4_debugfs_add_regset32(drm, "txp_regs", &txp->regset);
 
        return 0;
 }
@@ -533,13 +548,9 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
 static void vc4_txp_unbind(struct device *dev, struct device *master,
                           void *data)
 {
-       struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_txp *txp = dev_get_drvdata(dev);
 
-       vc4_txp_connector_destroy(&txp->connector.base);
-
-       vc4->txp = NULL;
+       drm_connector_cleanup(&txp->connector.base);
 }
 
 static const struct component_ops vc4_txp_ops = {
index cc714dcfe1f2296dbeccc44df9def4d945e34b25..56abb0d6bc39b62c0678cd6ab2466f88a6c5face 100644 (file)
@@ -231,7 +231,7 @@ try_again:
  * if it doesn't fit within the buffer that we allocated up front.
  * However, it turns out that 16MB is "enough for anybody", and
  * real-world applications run into allocation failures from the
- * overall CMA pool before they make scenes complicated enough to run
+ * overall DMA pool before they make scenes complicated enough to run
  * out of bin space.
  */
 static int bin_bo_alloc(struct vc4_dev *vc4)
@@ -261,15 +261,15 @@ static int bin_bo_alloc(struct vc4_dev *vc4)
 
                        dev_err(&v3d->pdev->dev,
                                "Failed to allocate memory for tile binning: "
-                               "%d. You may need to enable CMA or give it "
+                               "%d. You may need to enable DMA or give it "
                                "more memory.",
                                ret);
                        break;
                }
 
                /* Check if this BO won't trigger the addressing bug. */
-               if ((bo->base.paddr & 0xf0000000) ==
-                   ((bo->base.paddr + bo->base.base.size - 1) & 0xf0000000)) {
+               if ((bo->base.dma_addr & 0xf0000000) ==
+                   ((bo->base.dma_addr + bo->base.base.size - 1) & 0xf0000000)) {
                        vc4->bin_bo = bo;
 
                        /* Set up for allocating 512KB chunks of
@@ -393,14 +393,34 @@ static int vc4_v3d_runtime_resume(struct device *dev)
 
        vc4_v3d_init_hw(&vc4->base);
 
-       /* We disabled the IRQ as part of vc4_irq_uninstall in suspend. */
-       enable_irq(vc4->irq);
        vc4_irq_enable(&vc4->base);
 
        return 0;
 }
 #endif
 
+int vc4_v3d_debugfs_init(struct drm_minor *minor)
+{
+       struct drm_device *drm = minor->dev;
+       struct vc4_dev *vc4 = to_vc4_dev(drm);
+       struct vc4_v3d *v3d = vc4->v3d;
+       int ret;
+
+       if (!vc4->v3d)
+               return -ENODEV;
+
+       ret = vc4_debugfs_add_file(minor, "v3d_ident",
+                                  vc4_v3d_debugfs_ident, NULL);
+       if (ret)
+               return ret;
+
+       ret = vc4_debugfs_add_regset32(minor, "v3d_regs", &v3d->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -443,44 +463,47 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
                }
        }
 
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               return ret;
+       vc4->irq = ret;
+
+       ret = devm_pm_runtime_enable(dev);
+       if (ret)
+               return ret;
+
+       ret = pm_runtime_resume_and_get(dev);
+       if (ret)
+               return ret;
+
        if (V3D_READ(V3D_IDENT0) != V3D_EXPECTED_IDENT0) {
                DRM_ERROR("V3D_IDENT0 read 0x%08x instead of 0x%08x\n",
                          V3D_READ(V3D_IDENT0), V3D_EXPECTED_IDENT0);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_put_runtime_pm;
        }
 
-       ret = clk_prepare_enable(v3d->clk);
-       if (ret != 0)
-               return ret;
-
        /* Reset the binner overflow address/size at setup, to be sure
         * we don't reuse an old one.
         */
        V3D_WRITE(V3D_BPOA, 0);
        V3D_WRITE(V3D_BPOS, 0);
 
-       vc4_v3d_init_hw(drm);
-
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0)
-               return ret;
-       vc4->irq = ret;
-
        ret = vc4_irq_install(drm, vc4->irq);
        if (ret) {
                DRM_ERROR("Failed to install IRQ handler\n");
-               return ret;
+               goto err_put_runtime_pm;
        }
 
-       pm_runtime_set_active(dev);
        pm_runtime_use_autosuspend(dev);
        pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
-       pm_runtime_enable(dev);
-
-       vc4_debugfs_add_file(drm, "v3d_ident", vc4_v3d_debugfs_ident, NULL);
-       vc4_debugfs_add_regset32(drm, "v3d_regs", &v3d->regset);
 
        return 0;
+
+err_put_runtime_pm:
+       pm_runtime_put(dev);
+
+       return ret;
 }
 
 static void vc4_v3d_unbind(struct device *dev, struct device *master,
@@ -489,8 +512,6 @@ static void vc4_v3d_unbind(struct device *dev, struct device *master,
        struct drm_device *drm = dev_get_drvdata(master);
        struct vc4_dev *vc4 = to_vc4_dev(drm);
 
-       pm_runtime_disable(dev);
-
        vc4_irq_uninstall(drm);
 
        /* Disable the binner's overflow memory address, so the next
index 2feba55bcef7bb7d171ad13a10c28ee792a119aa..520231af4df9c4c4773e42c2fbdf19f9c74c14b6 100644 (file)
@@ -102,11 +102,11 @@ size_is_lt(uint32_t width, uint32_t height, int cpp)
                height <= 4 * utile_height(cpp));
 }
 
-struct drm_gem_cma_object *
+struct drm_gem_dma_object *
 vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex)
 {
        struct vc4_dev *vc4 = exec->dev;
-       struct drm_gem_cma_object *obj;
+       struct drm_gem_dma_object *obj;
        struct vc4_bo *bo;
 
        if (WARN_ON_ONCE(vc4->is_vc5))
@@ -129,7 +129,7 @@ vc4_use_bo(struct vc4_exec_info *exec, uint32_t hindex)
        return obj;
 }
 
-static struct drm_gem_cma_object *
+static struct drm_gem_dma_object *
 vc4_use_handle(struct vc4_exec_info *exec, uint32_t gem_handles_packet_index)
 {
        return vc4_use_bo(exec, exec->bo_index[gem_handles_packet_index]);
@@ -160,7 +160,7 @@ gl_shader_rec_size(uint32_t pointer_bits)
 }
 
 bool
-vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_cma_object *fbo,
+vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_dma_object *fbo,
                   uint32_t offset, uint8_t tiling_format,
                   uint32_t width, uint32_t height, uint8_t cpp)
 {
@@ -263,7 +263,7 @@ validate_increment_semaphore(VALIDATE_ARGS)
 static int
 validate_indexed_prim_list(VALIDATE_ARGS)
 {
-       struct drm_gem_cma_object *ib;
+       struct drm_gem_dma_object *ib;
        uint32_t length = *(uint32_t *)(untrusted + 1);
        uint32_t offset = *(uint32_t *)(untrusted + 5);
        uint32_t max_index = *(uint32_t *)(untrusted + 9);
@@ -294,7 +294,7 @@ validate_indexed_prim_list(VALIDATE_ARGS)
                return -EINVAL;
        }
 
-       *(uint32_t *)(validated + 5) = ib->paddr + offset;
+       *(uint32_t *)(validated + 5) = ib->dma_addr + offset;
 
        return 0;
 }
@@ -400,7 +400,7 @@ validate_tile_binning_config(VALIDATE_ARGS)
         * free when the job completes rendering.
         */
        exec->bin_slots |= BIT(bin_slot);
-       bin_addr = vc4->bin_bo->base.paddr + bin_slot * vc4->bin_alloc_size;
+       bin_addr = vc4->bin_bo->base.dma_addr + bin_slot * vc4->bin_alloc_size;
 
        /* The tile state data array is 48 bytes per tile, and we put it at
         * the start of a BO containing both it and the tile alloc.
@@ -575,7 +575,7 @@ reloc_tex(struct vc4_exec_info *exec,
          struct vc4_texture_sample_info *sample,
          uint32_t texture_handle_index, bool is_cs)
 {
-       struct drm_gem_cma_object *tex;
+       struct drm_gem_dma_object *tex;
        uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]);
        uint32_t p1 = *(uint32_t *)(uniform_data_u + sample->p_offset[1]);
        uint32_t p2 = (sample->p_offset[2] != ~0 ?
@@ -608,7 +608,7 @@ reloc_tex(struct vc4_exec_info *exec,
                                  "outside of UBO\n");
                        goto fail;
                }
-               *validated_p0 = tex->paddr + p0;
+               *validated_p0 = tex->dma_addr + p0;
                return true;
        }
 
@@ -736,7 +736,7 @@ reloc_tex(struct vc4_exec_info *exec,
                offset -= level_size;
        }
 
-       *validated_p0 = tex->paddr + p0;
+       *validated_p0 = tex->dma_addr + p0;
 
        if (is_cs) {
                exec->bin_dep_seqno = max(exec->bin_dep_seqno,
@@ -765,7 +765,7 @@ validate_gl_shader_rec(struct drm_device *dev,
                28, /* cs */
        };
        uint32_t shader_reloc_count = ARRAY_SIZE(shader_reloc_offsets);
-       struct drm_gem_cma_object *bo[ARRAY_SIZE(shader_reloc_offsets) + 8];
+       struct drm_gem_dma_object *bo[ARRAY_SIZE(shader_reloc_offsets) + 8];
        uint32_t nr_attributes, nr_relocs, packet_size;
        int i;
 
@@ -840,7 +840,7 @@ validate_gl_shader_rec(struct drm_device *dev,
                void *uniform_data_u;
                uint32_t tex, uni;
 
-               *(uint32_t *)(pkt_v + o) = bo[i]->paddr + src_offset;
+               *(uint32_t *)(pkt_v + o) = bo[i]->dma_addr + src_offset;
 
                if (src_offset != 0) {
                        DRM_DEBUG("Shaders must be at offset 0 of "
@@ -896,7 +896,7 @@ validate_gl_shader_rec(struct drm_device *dev,
        }
 
        for (i = 0; i < nr_attributes; i++) {
-               struct drm_gem_cma_object *vbo =
+               struct drm_gem_dma_object *vbo =
                        bo[ARRAY_SIZE(shader_reloc_offsets) + i];
                uint32_t o = 36 + i * 8;
                uint32_t offset = *(uint32_t *)(pkt_u + o + 0);
@@ -928,7 +928,7 @@ validate_gl_shader_rec(struct drm_device *dev,
                        }
                }
 
-               *(uint32_t *)(pkt_v + o) = vbo->paddr + offset;
+               *(uint32_t *)(pkt_v + o) = vbo->dma_addr + offset;
        }
 
        return 0;
index e315aeb5fef5a8a667bc7803452cde4056eeebc6..9745f8810eca6d2559f8a2e912eca5f28d01eb65 100644 (file)
@@ -776,7 +776,7 @@ vc4_handle_branch_target(struct vc4_shader_validation_state *validation_state)
 }
 
 struct vc4_validated_shader_info *
-vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
+vc4_validate_shader(struct drm_gem_dma_object *shader_obj)
 {
        struct vc4_dev *vc4 = to_vc4_dev(shader_obj->base.dev);
        bool found_shader_end = false;
index 11fc3d6f66b1ec5c9c3ff2873f3a21a1cb1cbe68..4a788c1c9058715dd0735a238f013d99bec2c088 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_probe_helper.h>
@@ -160,12 +161,12 @@ struct vc4_vec_variant {
 
 /* General VEC hardware state. */
 struct vc4_vec {
+       struct vc4_encoder encoder;
+       struct drm_connector connector;
+
        struct platform_device *pdev;
        const struct vc4_vec_variant *variant;
 
-       struct drm_encoder *encoder;
-       struct drm_connector *connector;
-
        void __iomem *regs;
 
        struct clk *clock;
@@ -178,30 +179,12 @@ struct vc4_vec {
 #define VEC_READ(offset) readl(vec->regs + (offset))
 #define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
 
-/* VC4 VEC encoder KMS struct */
-struct vc4_vec_encoder {
-       struct vc4_encoder base;
-       struct vc4_vec *vec;
-};
-
-static inline struct vc4_vec_encoder *
-to_vc4_vec_encoder(struct drm_encoder *encoder)
+static inline struct vc4_vec *
+encoder_to_vc4_vec(struct drm_encoder *encoder)
 {
-       return container_of(encoder, struct vc4_vec_encoder, base.base);
+       return container_of(encoder, struct vc4_vec, encoder.base);
 }
 
-/* VC4 VEC connector KMS struct */
-struct vc4_vec_connector {
-       struct drm_connector base;
-       struct vc4_vec *vec;
-
-       /* Since the connector is attached to just the one encoder,
-        * this is the reference to it so we can do the best_encoder()
-        * hook.
-        */
-       struct drm_encoder *encoder;
-};
-
 enum vc4_vec_tv_mode_id {
        VC4_VEC_TV_MODE_NTSC,
        VC4_VEC_TV_MODE_NTSC_J,
@@ -243,14 +226,30 @@ static const struct debugfs_reg32 vec_regs[] = {
 
 static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
 {
+       struct drm_device *drm = vec->connector.dev;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
 {
+       struct drm_device *drm = vec->connector.dev;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+
+       drm_dev_exit(idx);
 }
 
 static const struct drm_display_mode ntsc_mode = {
@@ -262,17 +261,33 @@ static const struct drm_display_mode ntsc_mode = {
 
 static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
 {
+       struct drm_device *drm = vec->connector.dev;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
        VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+
+       drm_dev_exit(idx);
 }
 
 static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
 {
+       struct drm_device *drm = vec->connector.dev;
+       int idx;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
+
        VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
        VEC_WRITE(VEC_CONFIG1,
                  VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
        VEC_WRITE(VEC_FREQ3_2, 0x223b);
        VEC_WRITE(VEC_FREQ1_0, 0x61d1);
+
+       drm_dev_exit(idx);
 }
 
 static const struct drm_display_mode pal_mode = {
@@ -307,12 +322,6 @@ vc4_vec_connector_detect(struct drm_connector *connector, bool force)
        return connector_status_unknown;
 }
 
-static void vc4_vec_connector_destroy(struct drm_connector *connector)
-{
-       drm_connector_unregister(connector);
-       drm_connector_cleanup(connector);
-}
-
 static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 {
        struct drm_connector_state *state = connector->state;
@@ -333,7 +342,6 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector)
 static const struct drm_connector_funcs vc4_vec_connector_funcs = {
        .detect = vc4_vec_connector_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
-       .destroy = vc4_vec_connector_destroy,
        .reset = drm_atomic_helper_connector_reset,
        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -343,25 +351,18 @@ static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs =
        .get_modes = vc4_vec_connector_get_modes,
 };
 
-static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
-                                                   struct vc4_vec *vec)
+static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec)
 {
-       struct drm_connector *connector = NULL;
-       struct vc4_vec_connector *vec_connector;
-
-       vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector),
-                                    GFP_KERNEL);
-       if (!vec_connector)
-               return ERR_PTR(-ENOMEM);
+       struct drm_connector *connector = &vec->connector;
+       int ret;
 
-       connector = &vec_connector->base;
        connector->interlace_allowed = true;
 
-       vec_connector->encoder = vec->encoder;
-       vec_connector->vec = vec;
+       ret = drmm_connector_init(dev, connector, &vc4_vec_connector_funcs,
+                                DRM_MODE_CONNECTOR_Composite, NULL);
+       if (ret)
+               return ret;
 
-       drm_connector_init(dev, connector, &vc4_vec_connector_funcs,
-                          DRM_MODE_CONNECTOR_Composite);
        drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
 
        drm_object_attach_property(&connector->base,
@@ -369,16 +370,19 @@ static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
                                   VC4_VEC_TV_MODE_NTSC);
        vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
 
-       drm_connector_attach_encoder(connector, vec->encoder);
+       drm_connector_attach_encoder(connector, &vec->encoder.base);
 
-       return connector;
+       return 0;
 }
 
 static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
 {
-       struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
-       struct vc4_vec *vec = vc4_vec_encoder->vec;
-       int ret;
+       struct drm_device *drm = encoder->dev;
+       struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
+       int idx, ret;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        VEC_WRITE(VEC_CFG, 0);
        VEC_WRITE(VEC_DAC_MISC,
@@ -392,20 +396,29 @@ static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
        ret = pm_runtime_put(&vec->pdev->dev);
        if (ret < 0) {
                DRM_ERROR("Failed to release power domain: %d\n", ret);
-               return;
+               goto err_dev_exit;
        }
+
+       drm_dev_exit(idx);
+       return;
+
+err_dev_exit:
+       drm_dev_exit(idx);
 }
 
 static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
 {
-       struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
-       struct vc4_vec *vec = vc4_vec_encoder->vec;
-       int ret;
+       struct drm_device *drm = encoder->dev;
+       struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
+       int idx, ret;
+
+       if (!drm_dev_enter(drm, &idx))
+               return;
 
        ret = pm_runtime_get_sync(&vec->pdev->dev);
        if (ret < 0) {
                DRM_ERROR("Failed to retain power domain: %d\n", ret);
-               return;
+               goto err_dev_exit;
        }
 
        /*
@@ -418,13 +431,13 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
        ret = clk_set_rate(vec->clock, 108000000);
        if (ret) {
                DRM_ERROR("Failed to set clock rate: %d\n", ret);
-               return;
+               goto err_put_runtime_pm;
        }
 
        ret = clk_prepare_enable(vec->clock);
        if (ret) {
                DRM_ERROR("Failed to turn on core clock: %d\n", ret);
-               return;
+               goto err_put_runtime_pm;
        }
 
        /* Reset the different blocks */
@@ -460,6 +473,14 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
        VEC_WRITE(VEC_DAC_MISC,
                  VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
        VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
+
+       drm_dev_exit(idx);
+       return;
+
+err_put_runtime_pm:
+       pm_runtime_put(&vec->pdev->dev);
+err_dev_exit:
+       drm_dev_exit(idx);
 }
 
 
@@ -474,8 +495,7 @@ static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
                                        struct drm_crtc_state *crtc_state,
                                        struct drm_connector_state *conn_state)
 {
-       struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
-       struct vc4_vec *vec = vc4_vec_encoder->vec;
+       struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
 
        vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
 }
@@ -503,6 +523,24 @@ static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
        .atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
 };
 
+static int vc4_vec_late_register(struct drm_encoder *encoder)
+{
+       struct drm_device *drm = encoder->dev;
+       struct vc4_vec *vec = encoder_to_vc4_vec(encoder);
+       int ret;
+
+       ret = vc4_debugfs_add_regset32(drm->primary, "vec_regs",
+                                      &vec->regset);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct drm_encoder_funcs vc4_vec_encoder_funcs = {
+       .late_register = vc4_vec_late_register,
+};
+
 static const struct vc4_vec_variant bcm2835_vec_variant = {
        .dac_config = VEC_DAC_CONFIG_DAC_CTRL(0xc) |
                      VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
@@ -532,9 +570,7 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
        struct vc4_vec *vec;
-       struct vc4_vec_encoder *vc4_vec_encoder;
        int ret;
 
        ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
@@ -542,18 +578,11 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
        if (ret)
                return ret;
 
-       vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
+       vec = drmm_kzalloc(drm, sizeof(*vec), GFP_KERNEL);
        if (!vec)
                return -ENOMEM;
 
-       vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
-                                      GFP_KERNEL);
-       if (!vc4_vec_encoder)
-               return -ENOMEM;
-       vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
-       vc4_vec_encoder->vec = vec;
-       vec->encoder = &vc4_vec_encoder->base.base;
-
+       vec->encoder.type = VC4_ENCODER_TYPE_VEC;
        vec->pdev = pdev;
        vec->variant = (const struct vc4_vec_variant *)
                of_device_get_match_data(dev);
@@ -572,49 +601,30 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
                return ret;
        }
 
-       pm_runtime_enable(dev);
-
-       drm_simple_encoder_init(drm, vec->encoder, DRM_MODE_ENCODER_TVDAC);
-       drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
+       ret = devm_pm_runtime_enable(dev);
+       if (ret)
+               return ret;
 
-       vec->connector = vc4_vec_connector_init(drm, vec);
-       if (IS_ERR(vec->connector)) {
-               ret = PTR_ERR(vec->connector);
-               goto err_destroy_encoder;
-       }
+       ret = drmm_encoder_init(drm, &vec->encoder.base,
+                               &vc4_vec_encoder_funcs,
+                               DRM_MODE_ENCODER_TVDAC,
+                               NULL);
+       if (ret)
+               return ret;
 
-       dev_set_drvdata(dev, vec);
+       drm_encoder_helper_add(&vec->encoder.base, &vc4_vec_encoder_helper_funcs);
 
-       vc4->vec = vec;
+       ret = vc4_vec_connector_init(drm, vec);
+       if (ret)
+               return ret;
 
-       vc4_debugfs_add_regset32(drm, "vec_regs", &vec->regset);
+       dev_set_drvdata(dev, vec);
 
        return 0;
-
-err_destroy_encoder:
-       drm_encoder_cleanup(vec->encoder);
-       pm_runtime_disable(dev);
-
-       return ret;
-}
-
-static void vc4_vec_unbind(struct device *dev, struct device *master,
-                          void *data)
-{
-       struct drm_device *drm = dev_get_drvdata(master);
-       struct vc4_dev *vc4 = to_vc4_dev(drm);
-       struct vc4_vec *vec = dev_get_drvdata(dev);
-
-       vc4_vec_connector_destroy(vec->connector);
-       drm_encoder_cleanup(vec->encoder);
-       pm_runtime_disable(dev);
-
-       vc4->vec = NULL;
 }
 
 static const struct component_ops vc4_vec_ops = {
        .bind   = vc4_vec_bind,
-       .unbind = vc4_vec_unbind,
 };
 
 static int vc4_vec_dev_probe(struct platform_device *pdev)
index 84db4eee78280610247471dadc8f118ae367a307..8b978dd51a2572148cb261f9ea02bc8aa81a14c0 100644 (file)
@@ -3,6 +3,6 @@
 # Makefile for the drm device driver.  This driver provides support for the
 # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
 
-via-y    := via_irq.o via_drv.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o
+via-y    := via_dri1.o
 
 obj-$(CONFIG_DRM_VIA)  +=via.o
index 462375d543b909c924b85fae7b7f64ea11a89f43..eb848508b12b4870487c9ffc569c53dd91aa61a9 100644 (file)
@@ -1,25 +1,7 @@
+/* SPDX-License-Identifier: MIT */
 /*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+ * Copyright 1998-2011 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2011 S3 Graphics, Inc. All Rights Reserved.
  */
 
 #ifndef VIA_3D_REG_H
@@ -50,6 +32,7 @@
 #define HC_ParaType_Palette     0x0003
 #define HC_ParaType_PreCR       0x0010
 #define HC_ParaType_Auto        0x00fe
+#define INV_ParaType_Dummy          0x00300000
 
 /* Transmission Space
  */
 #define HC_HSPXOS_SHIFT         12
 #define HC_HSPYOS_MASK          0x00000fff
 
-/* Command
+/*
  * Command A
  */
-#define HC_HCmdHeader_MASK      0xfe000000     /*0xffe00000 */
+#define HC_HCmdHeader_MASK      0xfe000000  /*0xffe00000 */
 #define HC_HE3Fire_MASK         0x00100000
 #define HC_HPMType_MASK         0x000f0000
 #define HC_HEFlag_MASK          0x0000e000
 /* Enable Setting
  */
 #define HC_SubA_HEnable         0x0000
+#define HC_HenForce1P_MASK      0x00800000  /* [Force 1 Pipe] */
+#define HC_HenZDCheck_MASK      0x00400000  /* [Z dirty bit settings] */
 #define HC_HenTXEnvMap_MASK     0x00200000
 #define HC_HenVertexCNT_MASK    0x00100000
 #define HC_HenCPUDAZ_MASK       0x00080000
 #define HC_FogDenst_MASK        0x001fff00
 #define HC_FogEndL_MASK         0x000000ff
 
+/* Texture subtype definitions
+ */
+#define HC_SubType_Samp0        0x00000020
+#define HC_SubType_Samp1        0x00000021
+
+
 /* Texture subtype definitions
  */
 #define HC_SubType_Tex0         0x00000000
 #define HC_SubA_HTXnBumpM10     0x0092
 #define HC_SubA_HTXnBumpM11     0x0093
 #define HC_SubA_HTXnLScale      0x0094
-#define HC_SubA_HTXSMD          0x0000
+
+#define HC_SubA_HTXSMD             0x0000
+#define HC_SubA_HTXYUV2RGB1        0x0001
+#define HC_SubA_HTXYUV2RGB2        0x0002
+#define HC_SubA_HTXYUV2RGB3        0x0003
+#define HTXYUV2RGB4BT601           (1<<23)
+#define HTXYUV2RGB4BT709           (1<<22)
 /* HC_SubA_HTXnL012BasH    0x0020
  */
 #define HC_HTXnL0BasH_MASK      0x000000ff
 #define HC_HTXnFM_Lum           0x00100000
 #define HC_HTXnFM_Alpha         0x00180000
 #define HC_HTXnFM_DX            0x00280000
+#define HC_HTXnFM_YUV           0x00300000
 #define HC_HTXnFM_ARGB16        0x00880000
 #define HC_HTXnFM_ARGB32        0x00980000
 #define HC_HTXnFM_ABGR16        0x00a80000
 #define HC_HTXnFM_DX1           (HC_HTXnFM_DX        | 0x00010000)
 #define HC_HTXnFM_DX23          (HC_HTXnFM_DX        | 0x00020000)
 #define HC_HTXnFM_DX45          (HC_HTXnFM_DX        | 0x00030000)
+/* YUV package mode */
+#define HC_HTXnFM_YUY2          (HC_HTXnFM_YUV           | 0x00000000)
+/* YUV planner mode */
+#define HC_HTXnFM_YV12          (HC_HTXnFM_YUV           | 0x00040000)
+/* YUV planner mode */
+#define HC_HTXnFM_IYUV          (HC_HTXnFM_YUV           | 0x00040000)
 #define HC_HTXnFM_RGB555        (HC_HTXnFM_ARGB16    | 0x00000000)
 #define HC_HTXnFM_RGB565        (HC_HTXnFM_ARGB16    | 0x00010000)
 #define HC_HTXnFM_ARGB1555      (HC_HTXnFM_ARGB16    | 0x00020000)
 #define HC_HTXnLoc_Local        0x00000000
 #define HC_HTXnLoc_Sys          0x00000002
 #define HC_HTXnLoc_AGP          0x00000003
+
+/* Video Texture */
+#define HC_HTXnYUV2RGBMode_RGB          0x00000000
+#define HC_HTXnYUV2RGBMode_SDTV         0x00000001
+#define HC_HTXnYUV2RGBMode_HDTV         0x00000002
+#define HC_HTXnYUV2RGBMode_TABLE        0x00000003
+
 /* HC_SubA_HTXnTRAH        0x007f
  */
 #define HC_HTXnTRAH_MASK        0x00ff0000
  */
 #define HC_HFthRTXA_MASK        0x000000ff
 
-/******************************************************************************
-** Define the Halcyon Internal register access constants. For simulator only.
-******************************************************************************/
+/****************************************************************************
+ * Define the Halcyon Internal register access constants. For simulator only.
+ ***************************************************************************/
 #define HC_SIMA_HAGPBstL        0x0000
 #define HC_SIMA_HAGPBendL       0x0001
 #define HC_SIMA_HAGPCMNT        0x0002
 #define HC_SIMA_TX0TX1_OFF      0x0050
 /*---- start of texture 1 setting ----
  */
-#define HC_SIMA_HTX1L0BasL      (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L1BasL      (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L2BasL      (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L3BasL      (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L4BasL      (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L5BasL      (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6BasL      (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L7BasL      (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L8BasL      (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9BasL      (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LaBasL      (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LbBasL      (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcBasL      (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LdBasL      (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LeBasL      (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LfBasL      (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L10BasL     (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L11BasL     (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L012BasH    (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L345BasH    (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L678BasH    (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9abBasH    (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcdeBasH    (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1Lf1011BasH  (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0Pit       (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L1Pit       (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L2Pit       (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L3Pit       (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L4Pit       (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L5Pit       (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6Pit       (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L7Pit       (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L8Pit       (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L9Pit       (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LaPit       (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LbPit       (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LcPit       (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LdPit       (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LePit       (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LfPit       (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L10Pit      (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L11Pit      (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0_5WE      (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6_bWE      (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1Lc_11WE     (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0_5HE      (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L6_bHE      (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0BasL       (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1BasL       (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2BasL       (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3BasL       (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4BasL       (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5BasL       (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6BasL       (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7BasL       (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8BasL       (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9BasL       (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaBasL       (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbBasL       (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcBasL       (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdBasL       (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LeBasL       (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfBasL       (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10BasL      (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11BasL      (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L012BasH     (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L345BasH     (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L678BasH     (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9abBasH     (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcdeBasH     (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lf1011BasH   (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0Pit        (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L1Pit        (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L2Pit        (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L3Pit        (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L4Pit        (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L5Pit        (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6Pit        (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L7Pit        (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L8Pit        (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L9Pit        (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LaPit        (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LbPit        (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LcPit        (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LdPit        (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LePit        (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LfPit        (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L10Pit       (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L11Pit       (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5WE       (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bWE       (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1Lc_11WE      (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0_5HE       (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L6_bHE       (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
 #define HC_SIMA_HTX1Lc_11HE      (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1L0OS        (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TB          (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1MPMD        (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1CLODu       (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1FM          (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRCH        (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRCL        (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBC         (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TRAH        (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LTC         (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LTA         (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLCsat     (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLCop      (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLMPfog    (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLAsat     (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCa      (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCb      (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCc      (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRCbias   (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRAa      (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1TBLRFog     (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM00     (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM01     (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM10     (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1BumpM11     (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
-#define HC_SIMA_HTX1LScale      (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1L0OS         (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TB           (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1MPMD         (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1CLODu        (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1FM           (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCH         (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRCL         (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBC          (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TRAH         (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTC          (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LTA          (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCsat      (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLCop       (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLMPfog     (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLAsat      (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCa       (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCb       (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCc       (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRCbias    (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRAa       (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1TBLRFog      (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM00      (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM01      (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM10      (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1BumpM11      (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
+#define HC_SIMA_HTX1LScale       (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
 /*---- end of texture 1 setting ---- 0xaf
  */
 #define HC_SIMA_HTXSMD          0x00b0
 #define HC_SIMA_HRErr           0x0445
 #define HC_SIMA_FIFOstatus      0x0446
 
-/******************************************************************************
-** Define the AGP command header.
-******************************************************************************/
+/****************************************************************************
+ * Define the AGP command header.
+ ***************************************************************************/
 #define HC_ACMD_MASK            0xfe000000
 #define HC_ACMD_SUB_MASK        0x0c000000
 #define HC_ACMD_HCmdA           0xee000000
 #define HC_ACMD_H4COUNT_MASK    0x01fffe00
 #define HC_ACMD_H4COUNT_SHIFT   9
 
-/********************************************************************************
-** Define Header
-********************************************************************************/
-#define HC_HEADER2             0xF210F110
+/*****************************************************************************
+ * Define Header
+ ****************************************************************************/
+#define HC_HEADER2        0xF210F110
 
-/********************************************************************************
-** Define Dummy Value
-********************************************************************************/
-#define HC_DUMMY               0xCCCCCCCC
-/********************************************************************************
-** Define for DMA use
-********************************************************************************/
+/*****************************************************************************
+ * Define Dummy Value
+ ****************************************************************************/
+#define HC_DUMMY        0xCCCCCCCC
+/*****************************************************************************
+ * Define for DMA use
+ ****************************************************************************/
 #define HALCYON_HEADER2     0XF210F110
 #define HALCYON_FIRECMD     0XEE100000
 #define HALCYON_FIREMASK    0XFFF00000
 #define HC_HAGPBpID_STOP        0x00000002
 #define HC_HAGPBpH_MASK         0x00ffffff
 
+
 #define VIA_VIDEO_HEADER5       0xFE040000
 #define VIA_VIDEO_HEADER6       0xFE050000
 #define VIA_VIDEO_HEADER7       0xFE060000
 #define VIA_VIDEOMASK           0xFFFF0000
+
+/*****************************************************************************
+ * Define for H5 DMA use
+ ****************************************************************************/
+#define H5_HC_DUMMY                    0xCC000000
+
+/* Command Header Type */
+#define INV_DUMMY_MASK         0xFF000000
+#define INV_AGPHeader0              0xFE000000
+#define INV_AGPHeader1              0xFE010000
+#define INV_AGPHeader2              0xFE020000
+#define INV_AGPHeader3              0xFE030000
+#define INV_AGPHeader4              0xFE040000
+#define INV_AGPHeader5              0xFE050000
+#define INV_AGPHeader6              0xFE060000
+#define INV_AGPHeader7              0xFE070000
+#define INV_AGPHeader9              0xFE090000
+#define INV_AGPHeaderA              0xFE0A0000
+#define INV_AGPHeader40             0xFE400000
+#define INV_AGPHeader41             0xFE410000
+#define INV_AGPHeader43             0xFE430000
+#define INV_AGPHeader45             0xFE450000
+#define INV_AGPHeader47             0xFE470000
+#define INV_AGPHeader4A             0xFE4A0000
+#define INV_AGPHeader82             0xFE820000
+#define INV_AGPHeader83             0xFE830000
+#define INV_AGPHeader_MASK          0xFFFF0000
+#define INV_AGPHeader2A             0xFE2A0000
+#define INV_AGPHeader25             0xFE250000
+#define INV_AGPHeader20             0xFE200000
+#define INV_AGPHeader23             0xFE230000
+#define INV_AGPHeaderE2             0xFEE20000
+#define INV_AGPHeaderE3             0xFEE30000
+
+/*Transmission IO Space*/
+#define INV_REG_CR_TRANS            0x041C
+#define INV_REG_CR_BEGIN            0x0420
+#define INV_REG_CR_END              0x0438
+
+#define INV_REG_3D_TRANS            0x043C
+#define INV_REG_3D_BEGIN            0x0440
+#define INV_REG_3D_END              0x06FC
+
+#define INV_ParaType_CmdVdata        0x0000
+
+/* H5 Enable Setting
+ */
+#define INV_HC_SubA_HEnable1        0x00
+
+#define INV_HC_HenAT4ALLRT_MASK     0x00100000
+#define INV_HC_HenATMRT3_MASK       0x00080000
+#define INV_HC_HenATMRT2_MASK       0x00040000
+#define INV_HC_HenATMRT1_MASK       0x00020000
+#define INV_HC_HenATMRT0_MASK        0x00010000
+#define INV_HC_HenSCMRT3_MASK        0x00008000
+#define INV_HC_HenSCMRT2_MASK        0x00004000
+#define INV_HC_HenSCMRT1_MASK        0x00002000
+#define INV_HC_HenSCMRT0_MASK        0x00001000
+#define INV_HC_HenFOGMRT3_MASK        0x00000800
+#define INV_HC_HenFOGMRT2_MASK        0x00000400
+#define INV_HC_HenFOGMRT1_MASK        0x00000200
+#define INV_HC_HenFOGMRT0_MASK        0x00000100
+#define INV_HC_HenABLMRT3_MASK        0x00000080
+#define INV_HC_HenABLMRT2_MASK        0x00000040
+#define INV_HC_HenABLMRT1_MASK        0x00000020
+#define INV_HC_HenABLMRT0_MASK        0x00000010
+#define INV_HC_HenDTMRT3_MASK        0x00000008
+#define INV_HC_HenDTMRT2_MASK        0x00000004
+#define INV_HC_HenDTMRT1_MASK        0x00000002
+#define INV_HC_HenDTMRT0_MASK        0x00000001
+
+#define INV_HC_SubA_HEnable2        0x01
+
+#define INV_HC_HenLUL2DR_MASK         0x00800000
+#define INV_HC_HenLDIAMOND_MASK     0x00400000
+#define INV_HC_HenPSPRITE_MASK         0x00200000
+#define INV_HC_HenC2S_MASK             0x00100000
+#define INV_HC_HenFOGPP_MASK           0x00080000
+#define INV_HC_HenSCPP_MASK           0x00040000
+#define INV_HC_HenCPP_MASK           0x00020000
+#define INV_HC_HenCZ_MASK            0x00002000
+#define INV_HC_HenVC_MASK            0x00001000
+#define INV_HC_HenCL_MASK            0x00000800
+#define INV_HC_HenPS_MASK            0x00000400
+#define INV_HC_HenWCZ_MASK            0x00000200
+#define INV_HC_HenTXCH_MASK            0x00000100
+#define INV_HC_HenBFCULL_MASK        0x00000080
+#define INV_HC_HenCW_MASK            0x00000040
+#define INV_HC_HenAA_MASK            0x00000020
+#define INV_HC_HenST_MASK            0x00000010
+#define INV_HC_HenZT_MASK            0x00000008
+#define INV_HC_HenZW_MASK            0x00000004
+#define INV_HC_HenSP_MASK            0x00000002
+#define INV_HC_HenLP_MASK            0x00000001
+
+/* H5 Miscellaneous Settings
+ */
+#define INV_HC_SubA_HCClipTL           0x0080
+#define INV_HC_SubA_HCClipBL           0x0081
+#define INV_HC_SubA_HSClipTL           0x0082
+#define INV_HC_SubA_HSClipBL           0x0083
+#define INV_HC_SubA_HSolidCL        0x0086
+#define INV_HC_SubA_HSolidCH        0x0087
+#define INV_HC_SubA_HGBClipGL       0x0088
+#define INV_HC_SubA_HGBClipGR       0x0089
+
+
+#define INV_HC_ParaType_Vetex        0x00040000
+
 #endif
diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c
deleted file mode 100644 (file)
index 177b049..0000000
+++ /dev/null
@@ -1,744 +0,0 @@
-/* via_dma.c -- DMA support for the VIA Unichrome/Pro
- *
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- *
- * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
- * All Rights Reserved.
- *
- * Copyright 2004 The Unichrome project.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Tungsten Graphics,
- *    Erdi Chen,
- *    Thomas Hellstrom.
- */
-
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-
-#include <drm/drm.h>
-#include <drm/drm_device.h>
-#include <drm/drm_file.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-#include "via_3d_reg.h"
-
-#define CMDBUF_ALIGNMENT_SIZE   (0x100)
-#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
-
-/* defines for VIA 3D registers */
-#define VIA_REG_STATUS          0x400
-#define VIA_REG_TRANSET         0x43C
-#define VIA_REG_TRANSPACE       0x440
-
-/* VIA_REG_STATUS(0x400): Engine Status */
-#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
-#define VIA_2D_ENG_BUSY         0x00000001     /* 2D Engine is busy */
-#define VIA_3D_ENG_BUSY         0x00000002     /* 3D Engine is busy */
-#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
-
-#define SetReg2DAGP(nReg, nData) {                             \
-       *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;  \
-       *((uint32_t *)(vb) + 1) = (nData);                      \
-       vb = ((uint32_t *)vb) + 2;                              \
-       dev_priv->dma_low += 8;                                 \
-}
-
-#define via_flush_write_combine() mb()
-
-#define VIA_OUT_RING_QW(w1, w2)        do {            \
-       *vb++ = (w1);                           \
-       *vb++ = (w2);                           \
-       dev_priv->dma_low += 8;                 \
-} while (0)
-
-static void via_cmdbuf_start(drm_via_private_t *dev_priv);
-static void via_cmdbuf_pause(drm_via_private_t *dev_priv);
-static void via_cmdbuf_reset(drm_via_private_t *dev_priv);
-static void via_cmdbuf_rewind(drm_via_private_t *dev_priv);
-static int via_wait_idle(drm_via_private_t *dev_priv);
-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
-
-/*
- * Free space in command buffer.
- */
-
-static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
-       return ((hw_addr <= dev_priv->dma_low) ?
-               (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
-               (hw_addr - dev_priv->dma_low));
-}
-
-/*
- * How much does the command regulator lag behind?
- */
-
-static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
-
-       return ((hw_addr <= dev_priv->dma_low) ?
-               (dev_priv->dma_low - hw_addr) :
-               (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
-}
-
-/*
- * Check that the given size fits in the buffer, otherwise wait.
- */
-
-static inline int
-via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size)
-{
-       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       uint32_t cur_addr, hw_addr, next_addr;
-       volatile uint32_t *hw_addr_ptr;
-       uint32_t count;
-       hw_addr_ptr = dev_priv->hw_addr_ptr;
-       cur_addr = dev_priv->dma_low;
-       next_addr = cur_addr + size + 512 * 1024;
-       count = 1000000;
-       do {
-               hw_addr = *hw_addr_ptr - agp_base;
-               if (count-- == 0) {
-                       DRM_ERROR
-                           ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
-                            hw_addr, cur_addr, next_addr);
-                       return -1;
-               }
-               if  ((cur_addr < hw_addr) && (next_addr >= hw_addr))
-                       msleep(1);
-       } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
-       return 0;
-}
-
-/*
- * Checks whether buffer head has reach the end. Rewind the ring buffer
- * when necessary.
- *
- * Returns virtual pointer to ring buffer.
- */
-
-static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
-                                     unsigned int size)
-{
-       if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
-           dev_priv->dma_high) {
-               via_cmdbuf_rewind(dev_priv);
-       }
-       if (via_cmdbuf_wait(dev_priv, size) != 0)
-               return NULL;
-
-       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
-}
-
-int via_dma_cleanup(struct drm_device *dev)
-{
-       if (dev->dev_private) {
-               drm_via_private_t *dev_priv =
-                   (drm_via_private_t *) dev->dev_private;
-
-               if (dev_priv->ring.virtual_start) {
-                       via_cmdbuf_reset(dev_priv);
-
-                       drm_legacy_ioremapfree(&dev_priv->ring.map, dev);
-                       dev_priv->ring.virtual_start = NULL;
-               }
-
-       }
-
-       return 0;
-}
-
-static int via_initialize(struct drm_device *dev,
-                         drm_via_private_t *dev_priv,
-                         drm_via_dma_init_t *init)
-{
-       if (!dev_priv || !dev_priv->mmio) {
-               DRM_ERROR("via_dma_init called before via_map_init\n");
-               return -EFAULT;
-       }
-
-       if (dev_priv->ring.virtual_start != NULL) {
-               DRM_ERROR("called again without calling cleanup\n");
-               return -EFAULT;
-       }
-
-       if (!dev->agp || !dev->agp->base) {
-               DRM_ERROR("called with no agp memory available\n");
-               return -EFAULT;
-       }
-
-       if (dev_priv->chipset == VIA_DX9_0) {
-               DRM_ERROR("AGP DMA is not supported on this chip\n");
-               return -EINVAL;
-       }
-
-       dev_priv->ring.map.offset = dev->agp->base + init->offset;
-       dev_priv->ring.map.size = init->size;
-       dev_priv->ring.map.type = 0;
-       dev_priv->ring.map.flags = 0;
-       dev_priv->ring.map.mtrr = 0;
-
-       drm_legacy_ioremap(&dev_priv->ring.map, dev);
-
-       if (dev_priv->ring.map.handle == NULL) {
-               via_dma_cleanup(dev);
-               DRM_ERROR("can not ioremap virtual address for"
-                         " ring buffer\n");
-               return -ENOMEM;
-       }
-
-       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-       dev_priv->dma_ptr = dev_priv->ring.virtual_start;
-       dev_priv->dma_low = 0;
-       dev_priv->dma_high = init->size;
-       dev_priv->dma_wrap = init->size;
-       dev_priv->dma_offset = init->offset;
-       dev_priv->last_pause_ptr = NULL;
-       dev_priv->hw_addr_ptr =
-               (volatile uint32_t *)((char *)dev_priv->mmio->handle +
-               init->reg_pause_addr);
-
-       via_cmdbuf_start(dev_priv);
-
-       return 0;
-}
-
-static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_dma_init_t *init = data;
-       int retcode = 0;
-
-       switch (init->func) {
-       case VIA_INIT_DMA:
-               if (!capable(CAP_SYS_ADMIN))
-                       retcode = -EPERM;
-               else
-                       retcode = via_initialize(dev, dev_priv, init);
-               break;
-       case VIA_CLEANUP_DMA:
-               if (!capable(CAP_SYS_ADMIN))
-                       retcode = -EPERM;
-               else
-                       retcode = via_dma_cleanup(dev);
-               break;
-       case VIA_DMA_INITIALIZED:
-               retcode = (dev_priv->ring.virtual_start != NULL) ?
-                       0 : -EFAULT;
-               break;
-       default:
-               retcode = -EINVAL;
-               break;
-       }
-
-       return retcode;
-}
-
-static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd)
-{
-       drm_via_private_t *dev_priv;
-       uint32_t *vb;
-       int ret;
-
-       dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (dev_priv->ring.virtual_start == NULL) {
-               DRM_ERROR("called without initializing AGP ring buffer.\n");
-               return -EFAULT;
-       }
-
-       if (cmd->size > VIA_PCI_BUF_SIZE)
-               return -ENOMEM;
-
-       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return -EFAULT;
-
-       /*
-        * Running this function on AGP memory is dead slow. Therefore
-        * we run it on a temporary cacheable system memory buffer and
-        * copy it to AGP memory when ready.
-        */
-
-       if ((ret =
-            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
-                                      cmd->size, dev, 1))) {
-               return ret;
-       }
-
-       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
-       if (vb == NULL)
-               return -EAGAIN;
-
-       memcpy(vb, dev_priv->pci_buf, cmd->size);
-
-       dev_priv->dma_low += cmd->size;
-
-       /*
-        * Small submissions somehow stalls the CPU. (AGP cache effects?)
-        * pad to greater size.
-        */
-
-       if (cmd->size < 0x100)
-               via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
-       via_cmdbuf_pause(dev_priv);
-
-       return 0;
-}
-
-int via_driver_dma_quiescent(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       if (!via_wait_idle(dev_priv))
-               return -EBUSY;
-       return 0;
-}
-
-static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       return via_driver_dma_quiescent(dev);
-}
-
-static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuffer_t *cmdbuf = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
-
-       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
-       return ret;
-}
-
-static int via_dispatch_pci_cmdbuffer(struct drm_device *dev,
-                                     drm_via_cmdbuffer_t *cmd)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       int ret;
-
-       if (cmd->size > VIA_PCI_BUF_SIZE)
-               return -ENOMEM;
-       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
-               return -EFAULT;
-
-       if ((ret =
-            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
-                                      cmd->size, dev, 0))) {
-               return ret;
-       }
-
-       ret =
-           via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
-                                    cmd->size);
-       return ret;
-}
-
-static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuffer_t *cmdbuf = data;
-       int ret;
-
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
-
-       ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
-       return ret;
-}
-
-static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv,
-                                        uint32_t * vb, int qw_count)
-{
-       for (; qw_count > 0; --qw_count)
-               VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
-       return vb;
-}
-
-/*
- * This function is used internally by ring buffer management code.
- *
- * Returns virtual pointer to ring buffer.
- */
-static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv)
-{
-       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
-}
-
-/*
- * Hooks a segment of data into the tail of the ring-buffer by
- * modifying the pause address stored in the buffer itself. If
- * the regulator has already paused, restart it.
- */
-static int via_hook_segment(drm_via_private_t *dev_priv,
-                           uint32_t pause_addr_hi, uint32_t pause_addr_lo,
-                           int no_pci_fire)
-{
-       int paused, count;
-       volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
-       uint32_t reader, ptr;
-       uint32_t diff;
-
-       paused = 0;
-       via_flush_write_combine();
-       (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1);
-
-       *paused_at = pause_addr_lo;
-       via_flush_write_combine();
-       (void) *paused_at;
-
-       reader = *(dev_priv->hw_addr_ptr);
-       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
-               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-       dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
-
-       /*
-        * If there is a possibility that the command reader will
-        * miss the new pause address and pause on the old one,
-        * In that case we need to program the new start address
-        * using PCI.
-        */
-
-       diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-       count = 10000000;
-       while (diff == 0 && count--) {
-               paused = (via_read(dev_priv, 0x41c) & 0x80000000);
-               if (paused)
-                       break;
-               reader = *(dev_priv->hw_addr_ptr);
-               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-       }
-
-       paused = via_read(dev_priv, 0x41c) & 0x80000000;
-
-       if (paused && !no_pci_fire) {
-               reader = *(dev_priv->hw_addr_ptr);
-               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
-               diff &= (dev_priv->dma_high - 1);
-               if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
-                       DRM_ERROR("Paused at incorrect address. "
-                                 "0x%08x, 0x%08x 0x%08x\n",
-                                 ptr, reader, dev_priv->dma_diff);
-               } else if (diff == 0) {
-                       /*
-                        * There is a concern that these writes may stall the PCI bus
-                        * if the GPU is not idle. However, idling the GPU first
-                        * doesn't make a difference.
-                        */
-
-                       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
-                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
-                       via_read(dev_priv, VIA_REG_TRANSPACE);
-               }
-       }
-       return paused;
-}
-
-static int via_wait_idle(drm_via_private_t *dev_priv)
-{
-       int count = 10000000;
-
-       while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count)
-               ;
-
-       while (count && (via_read(dev_priv, VIA_REG_STATUS) &
-                          (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
-                           VIA_3D_ENG_BUSY)))
-               --count;
-       return count;
-}
-
-static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type,
-                              uint32_t addr, uint32_t *cmd_addr_hi,
-                              uint32_t *cmd_addr_lo, int skip_wait)
-{
-       uint32_t agp_base;
-       uint32_t cmd_addr, addr_lo, addr_hi;
-       uint32_t *vb;
-       uint32_t qw_pad_count;
-
-       if (!skip_wait)
-               via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
-
-       vb = via_get_dma(dev_priv);
-       VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
-                       (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
-       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
-           ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
-
-       cmd_addr = (addr) ? addr :
-           agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
-       addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
-                  (cmd_addr & HC_HAGPBpL_MASK));
-       addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
-
-       vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
-       VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
-       return vb;
-}
-
-static void via_cmdbuf_start(drm_via_private_t *dev_priv)
-{
-       uint32_t pause_addr_lo, pause_addr_hi;
-       uint32_t start_addr, start_addr_lo;
-       uint32_t end_addr, end_addr_lo;
-       uint32_t command;
-       uint32_t agp_base;
-       uint32_t ptr;
-       uint32_t reader;
-       int count;
-
-       dev_priv->dma_low = 0;
-
-       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
-       start_addr = agp_base;
-       end_addr = agp_base + dev_priv->dma_high;
-
-       start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
-       end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
-       command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
-                  ((end_addr & 0xff000000) >> 16));
-
-       dev_priv->last_pause_ptr =
-           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
-                         &pause_addr_hi, &pause_addr_lo, 1) - 1;
-
-       via_flush_write_combine();
-       (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
-
-       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
-       via_write(dev_priv, VIA_REG_TRANSPACE, command);
-       via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo);
-       via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo);
-
-       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
-       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
-       wmb();
-       via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
-       via_read(dev_priv, VIA_REG_TRANSPACE);
-
-       dev_priv->dma_diff = 0;
-
-       count = 10000000;
-       while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--);
-
-       reader = *(dev_priv->hw_addr_ptr);
-       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
-           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
-
-       /*
-        * This is the difference between where we tell the
-        * command reader to pause and where it actually pauses.
-        * This differs between hw implementation so we need to
-        * detect it.
-        */
-
-       dev_priv->dma_diff = ptr - reader;
-}
-
-static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
-{
-       uint32_t *vb;
-
-       via_cmdbuf_wait(dev_priv, qwords + 2);
-       vb = via_get_dma(dev_priv);
-       VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
-       via_align_buffer(dev_priv, vb, qwords);
-}
-
-static inline void via_dummy_bitblt(drm_via_private_t *dev_priv)
-{
-       uint32_t *vb = via_get_dma(dev_priv);
-       SetReg2DAGP(0x0C, (0 | (0 << 16)));
-       SetReg2DAGP(0x10, 0 | (0 << 16));
-       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
-}
-
-static void via_cmdbuf_jump(drm_via_private_t *dev_priv)
-{
-       uint32_t pause_addr_lo, pause_addr_hi;
-       uint32_t jump_addr_lo, jump_addr_hi;
-       volatile uint32_t *last_pause_ptr;
-       uint32_t dma_low_save1, dma_low_save2;
-
-       via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
-                     &jump_addr_lo, 0);
-
-       dev_priv->dma_wrap = dev_priv->dma_low;
-
-       /*
-        * Wrap command buffer to the beginning.
-        */
-
-       dev_priv->dma_low = 0;
-       if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0)
-               DRM_ERROR("via_cmdbuf_jump failed\n");
-
-       via_dummy_bitblt(dev_priv);
-       via_dummy_bitblt(dev_priv);
-
-       last_pause_ptr =
-           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                         &pause_addr_lo, 0) - 1;
-       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                     &pause_addr_lo, 0);
-
-       *last_pause_ptr = pause_addr_lo;
-       dma_low_save1 = dev_priv->dma_low;
-
-       /*
-        * Now, set a trap that will pause the regulator if it tries to rerun the old
-        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
-        * and reissues the jump command over PCI, while the regulator has already taken the jump
-        * and actually paused at the current buffer end).
-        * There appears to be no other way to detect this condition, since the hw_addr_pointer
-        * does not seem to get updated immediately when a jump occurs.
-        */
-
-       last_pause_ptr =
-               via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                             &pause_addr_lo, 0) - 1;
-       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
-                     &pause_addr_lo, 0);
-       *last_pause_ptr = pause_addr_lo;
-
-       dma_low_save2 = dev_priv->dma_low;
-       dev_priv->dma_low = dma_low_save1;
-       via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
-       dev_priv->dma_low = dma_low_save2;
-       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
-}
-
-
-static void via_cmdbuf_rewind(drm_via_private_t *dev_priv)
-{
-       via_cmdbuf_jump(dev_priv);
-}
-
-static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type)
-{
-       uint32_t pause_addr_lo, pause_addr_hi;
-
-       via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
-       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
-}
-
-static void via_cmdbuf_pause(drm_via_private_t *dev_priv)
-{
-       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
-}
-
-static void via_cmdbuf_reset(drm_via_private_t *dev_priv)
-{
-       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
-       via_wait_idle(dev_priv);
-}
-
-/*
- * User interface to the space and lag functions.
- */
-
-static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_cmdbuf_size_t *d_siz = data;
-       int ret = 0;
-       uint32_t tmp_size, count;
-       drm_via_private_t *dev_priv;
-
-       DRM_DEBUG("\n");
-       LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-       dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (dev_priv->ring.virtual_start == NULL) {
-               DRM_ERROR("called without initializing AGP ring buffer.\n");
-               return -EFAULT;
-       }
-
-       count = 1000000;
-       tmp_size = d_siz->size;
-       switch (d_siz->func) {
-       case VIA_CMDBUF_SPACE:
-               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
-                      && --count) {
-                       if (!d_siz->wait)
-                               break;
-               }
-               if (!count) {
-                       DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
-                       ret = -EAGAIN;
-               }
-               break;
-       case VIA_CMDBUF_LAG:
-               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
-                      && --count) {
-                       if (!d_siz->wait)
-                               break;
-               }
-               if (!count) {
-                       DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
-                       ret = -EAGAIN;
-               }
-               break;
-       default:
-               ret = -EFAULT;
-       }
-       d_siz->size = tmp_size;
-
-       return ret;
-}
-
-const struct drm_ioctl_desc via_ioctls[] = {
-       DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
-       DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
-       DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
-};
-
-int via_max_ioctl = ARRAY_SIZE(via_ioctls);
diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
deleted file mode 100644 (file)
index e016a4d..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-/* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro
- *
- * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Thomas Hellstrom.
- *    Partially based on code obtained from Digeo Inc.
- */
-
-
-/*
- * Unmaps the DMA mappings.
- * FIXME: Is this a NoOp on x86? Also
- * FIXME: What happens if this one is called and a pending blit has previously done
- * the same DMA mappings?
- */
-
-#include <linux/pagemap.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <drm/drm_device.h>
-#include <drm/via_drm.h>
-
-#include "via_dmablit.h"
-#include "via_drv.h"
-
-#define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
-#define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
-#define VIA_PFN(x)           ((unsigned long)(x) >> PAGE_SHIFT)
-
-typedef struct _drm_via_descriptor {
-       uint32_t mem_addr;
-       uint32_t dev_addr;
-       uint32_t size;
-       uint32_t next;
-} drm_via_descriptor_t;
-
-
-/*
- * Unmap a DMA mapping.
- */
-
-
-
-static void
-via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
-{
-       int num_desc = vsg->num_desc;
-       unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
-       unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
-       drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
-               descriptor_this_page;
-       dma_addr_t next = vsg->chain_start;
-
-       while (num_desc--) {
-               if (descriptor_this_page-- == 0) {
-                       cur_descriptor_page--;
-                       descriptor_this_page = vsg->descriptors_per_page - 1;
-                       desc_ptr = vsg->desc_pages[cur_descriptor_page] +
-                               descriptor_this_page;
-               }
-               dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
-               dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
-               next = (dma_addr_t) desc_ptr->next;
-               desc_ptr--;
-       }
-}
-
-/*
- * If mode = 0, count how many descriptors are needed.
- * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
- * Descriptors are run in reverse order by the hardware because we are not allowed to update the
- * 'next' field without syncing calls when the descriptor is already mapped.
- */
-
-static void
-via_map_blit_for_device(struct pci_dev *pdev,
-                  const drm_via_dmablit_t *xfer,
-                  drm_via_sg_info_t *vsg,
-                  int mode)
-{
-       unsigned cur_descriptor_page = 0;
-       unsigned num_descriptors_this_page = 0;
-       unsigned char *mem_addr = xfer->mem_addr;
-       unsigned char *cur_mem;
-       unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
-       uint32_t fb_addr = xfer->fb_addr;
-       uint32_t cur_fb;
-       unsigned long line_len;
-       unsigned remaining_len;
-       int num_desc = 0;
-       int cur_line;
-       dma_addr_t next = 0 | VIA_DMA_DPR_EC;
-       drm_via_descriptor_t *desc_ptr = NULL;
-
-       if (mode == 1)
-               desc_ptr = vsg->desc_pages[cur_descriptor_page];
-
-       for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
-
-               line_len = xfer->line_length;
-               cur_fb = fb_addr;
-               cur_mem = mem_addr;
-
-               while (line_len > 0) {
-
-                       remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
-                       line_len -= remaining_len;
-
-                       if (mode == 1) {
-                               desc_ptr->mem_addr =
-                                       dma_map_page(&pdev->dev,
-                                                    vsg->pages[VIA_PFN(cur_mem) -
-                                                               VIA_PFN(first_addr)],
-                                                    VIA_PGOFF(cur_mem), remaining_len,
-                                                    vsg->direction);
-                               desc_ptr->dev_addr = cur_fb;
-
-                               desc_ptr->size = remaining_len;
-                               desc_ptr->next = (uint32_t) next;
-                               next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
-                                                     DMA_TO_DEVICE);
-                               desc_ptr++;
-                               if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
-                                       num_descriptors_this_page = 0;
-                                       desc_ptr = vsg->desc_pages[++cur_descriptor_page];
-                               }
-                       }
-
-                       num_desc++;
-                       cur_mem += remaining_len;
-                       cur_fb += remaining_len;
-               }
-
-               mem_addr += xfer->mem_stride;
-               fb_addr += xfer->fb_stride;
-       }
-
-       if (mode == 1) {
-               vsg->chain_start = next;
-               vsg->state = dr_via_device_mapped;
-       }
-       vsg->num_desc = num_desc;
-}
-
-/*
- * Function that frees up all resources for a blit. It is usable even if the
- * blit info has only been partially built as long as the status enum is consistent
- * with the actual status of the used resources.
- */
-
-
-static void
-via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
-{
-       int i;
-
-       switch (vsg->state) {
-       case dr_via_device_mapped:
-               via_unmap_blit_from_device(pdev, vsg);
-               fallthrough;
-       case dr_via_desc_pages_alloc:
-               for (i = 0; i < vsg->num_desc_pages; ++i) {
-                       if (vsg->desc_pages[i] != NULL)
-                               free_page((unsigned long)vsg->desc_pages[i]);
-               }
-               kfree(vsg->desc_pages);
-               fallthrough;
-       case dr_via_pages_locked:
-               unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
-                                          (vsg->direction == DMA_FROM_DEVICE));
-               fallthrough;
-       case dr_via_pages_alloc:
-               vfree(vsg->pages);
-               fallthrough;
-       default:
-               vsg->state = dr_via_sg_init;
-       }
-       vfree(vsg->bounce_buffer);
-       vsg->bounce_buffer = NULL;
-       vsg->free_on_sequence = 0;
-}
-
-/*
- * Fire a blit engine.
- */
-
-static void
-via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0);
-       via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0);
-       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
-                 VIA_DMA_CSR_DE);
-       via_write(dev_priv, VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
-       via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0);
-       via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
-       wmb();
-       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
-       via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04);
-}
-
-/*
- * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
- * occur here if the calling user does not have access to the submitted address.
- */
-
-static int
-via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
-{
-       int ret;
-       unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
-       vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) -
-               first_pfn + 1;
-
-       vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages));
-       if (NULL == vsg->pages)
-               return -ENOMEM;
-       ret = pin_user_pages_fast((unsigned long)xfer->mem_addr,
-                       vsg->num_pages,
-                       vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
-                       vsg->pages);
-       if (ret != vsg->num_pages) {
-               if (ret < 0)
-                       return ret;
-               vsg->state = dr_via_pages_locked;
-               return -EINVAL;
-       }
-       vsg->state = dr_via_pages_locked;
-       DRM_DEBUG("DMA pages locked\n");
-       return 0;
-}
-
-/*
- * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
- * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
- * quite large for some blits, and pages don't need to be contiguous.
- */
-
-static int
-via_alloc_desc_pages(drm_via_sg_info_t *vsg)
-{
-       int i;
-
-       vsg->descriptors_per_page = PAGE_SIZE / sizeof(drm_via_descriptor_t);
-       vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
-               vsg->descriptors_per_page;
-
-       if (NULL ==  (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL)))
-               return -ENOMEM;
-
-       vsg->state = dr_via_desc_pages_alloc;
-       for (i = 0; i < vsg->num_desc_pages; ++i) {
-               if (NULL == (vsg->desc_pages[i] =
-                            (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
-                       return -ENOMEM;
-       }
-       DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
-                 vsg->num_desc);
-       return 0;
-}
-
-static void
-via_abort_dmablit(struct drm_device *dev, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
-}
-
-static void
-via_dmablit_engine_off(struct drm_device *dev, int engine)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-
-       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
-}
-
-
-
-/*
- * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
- * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
- * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
- * the workqueue task takes care of processing associated with the old blit.
- */
-
-void
-via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
-       int cur;
-       int done_transfer;
-       unsigned long irqsave = 0;
-       uint32_t status = 0;
-
-       DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
-                 engine, from_irq, (unsigned long) blitq);
-
-       if (from_irq)
-               spin_lock(&blitq->blit_lock);
-       else
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       done_transfer = blitq->is_active &&
-         ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
-       done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE));
-
-       cur = blitq->cur;
-       if (done_transfer) {
-
-               blitq->blits[cur]->aborted = blitq->aborting;
-               blitq->done_blit_handle++;
-               wake_up(blitq->blit_queue + cur);
-
-               cur++;
-               if (cur >= VIA_NUM_BLIT_SLOTS)
-                       cur = 0;
-               blitq->cur = cur;
-
-               /*
-                * Clear transfer done flag.
-                */
-
-               via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
-
-               blitq->is_active = 0;
-               blitq->aborting = 0;
-               schedule_work(&blitq->wq);
-
-       } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
-
-               /*
-                * Abort transfer after one second.
-                */
-
-               via_abort_dmablit(dev, engine);
-               blitq->aborting = 1;
-               blitq->end = jiffies + HZ;
-       }
-
-       if (!blitq->is_active) {
-               if (blitq->num_outstanding) {
-                       via_fire_dmablit(dev, blitq->blits[cur], engine);
-                       blitq->is_active = 1;
-                       blitq->cur = cur;
-                       blitq->num_outstanding--;
-                       blitq->end = jiffies + HZ;
-                       if (!timer_pending(&blitq->poll_timer))
-                               mod_timer(&blitq->poll_timer, jiffies + 1);
-               } else {
-                       if (timer_pending(&blitq->poll_timer))
-                               del_timer(&blitq->poll_timer);
-                       via_dmablit_engine_off(dev, engine);
-               }
-       }
-
-       if (from_irq)
-               spin_unlock(&blitq->blit_lock);
-       else
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-}
-
-
-
-/*
- * Check whether this blit is still active, performing necessary locking.
- */
-
-static int
-via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
-{
-       unsigned long irqsave;
-       uint32_t slot;
-       int active;
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       /*
-        * Allow for handle wraparounds.
-        */
-
-       active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
-               ((blitq->cur_blit_handle - handle) <= (1 << 23));
-
-       if (queue && active) {
-               slot = handle - blitq->done_blit_handle + blitq->cur - 1;
-               if (slot >= VIA_NUM_BLIT_SLOTS)
-                       slot -= VIA_NUM_BLIT_SLOTS;
-               *queue = blitq->blit_queue + slot;
-       }
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-       return active;
-}
-
-/*
- * Sync. Wait for at least three seconds for the blit to be performed.
- */
-
-static int
-via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
-       wait_queue_head_t *queue;
-       int ret = 0;
-
-       if (via_dmablit_active(blitq, engine, handle, &queue)) {
-               VIA_WAIT_ON(ret, *queue, 3 * HZ,
-                           !via_dmablit_active(blitq, engine, handle, NULL));
-       }
-       DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
-                 handle, engine, ret);
-
-       return ret;
-}
-
-
-/*
- * A timer that regularly polls the blit engine in cases where we don't have interrupts:
- * a) Broken hardware (typically those that don't have any video capture facility).
- * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
- * The timer and hardware IRQ's can and do work in parallel. If the hardware has
- * irqs, it will shorten the latency somewhat.
- */
-
-
-
-static void
-via_dmablit_timer(struct timer_list *t)
-{
-       drm_via_blitq_t *blitq = from_timer(blitq, t, poll_timer);
-       struct drm_device *dev = blitq->dev;
-       int engine = (int)
-               (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
-
-       DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
-                 (unsigned long) jiffies);
-
-       via_dmablit_handler(dev, engine, 0);
-
-       if (!timer_pending(&blitq->poll_timer)) {
-               mod_timer(&blitq->poll_timer, jiffies + 1);
-
-              /*
-               * Rerun handler to delete timer if engines are off, and
-               * to shorten abort latency. This is a little nasty.
-               */
-
-              via_dmablit_handler(dev, engine, 0);
-
-       }
-}
-
-
-
-
-/*
- * Workqueue task that frees data and mappings associated with a blit.
- * Also wakes up waiting processes. Each of these tasks handles one
- * blit engine only and may not be called on each interrupt.
- */
-
-
-static void
-via_dmablit_workqueue(struct work_struct *work)
-{
-       drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
-       struct drm_device *dev = blitq->dev;
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
-       unsigned long irqsave;
-       drm_via_sg_info_t *cur_sg;
-       int cur_released;
-
-
-       DRM_DEBUG("Workqueue task called for blit engine %ld\n", (unsigned long)
-                 (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       while (blitq->serviced != blitq->cur) {
-
-               cur_released = blitq->serviced++;
-
-               DRM_DEBUG("Releasing blit slot %d\n", cur_released);
-
-               if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
-                       blitq->serviced = 0;
-
-               cur_sg = blitq->blits[cur_released];
-               blitq->num_free++;
-
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-               wake_up(&blitq->busy_queue);
-
-               via_free_sg_info(pdev, cur_sg);
-               kfree(cur_sg);
-
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       }
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-}
-
-
-/*
- * Init all blit engines. Currently we use two, but some hardware have 4.
- */
-
-
-void
-via_init_dmablit(struct drm_device *dev)
-{
-       int i, j;
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
-       drm_via_blitq_t *blitq;
-
-       pci_set_master(pdev);
-
-       for (i = 0; i < VIA_NUM_BLIT_ENGINES; ++i) {
-               blitq = dev_priv->blit_queues + i;
-               blitq->dev = dev;
-               blitq->cur_blit_handle = 0;
-               blitq->done_blit_handle = 0;
-               blitq->head = 0;
-               blitq->cur = 0;
-               blitq->serviced = 0;
-               blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
-               blitq->num_outstanding = 0;
-               blitq->is_active = 0;
-               blitq->aborting = 0;
-               spin_lock_init(&blitq->blit_lock);
-               for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j)
-                       init_waitqueue_head(blitq->blit_queue + j);
-               init_waitqueue_head(&blitq->busy_queue);
-               INIT_WORK(&blitq->wq, via_dmablit_workqueue);
-               timer_setup(&blitq->poll_timer, via_dmablit_timer, 0);
-       }
-}
-
-/*
- * Build all info and do all mappings required for a blit.
- */
-
-
-static int
-via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
-{
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
-       int draw = xfer->to_fb;
-       int ret = 0;
-
-       vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
-       vsg->bounce_buffer = NULL;
-
-       vsg->state = dr_via_sg_init;
-
-       if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
-               DRM_ERROR("Zero size bitblt.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Below check is a driver limitation, not a hardware one. We
-        * don't want to lock unused pages, and don't want to incoporate the
-        * extra logic of avoiding them. Make sure there are no.
-        * (Not a big limitation anyway.)
-        */
-
-       if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
-               DRM_ERROR("Too large system memory stride. Stride: %d, "
-                         "Length: %d\n", xfer->mem_stride, xfer->line_length);
-               return -EINVAL;
-       }
-
-       if ((xfer->mem_stride == xfer->line_length) &&
-          (xfer->fb_stride == xfer->line_length)) {
-               xfer->mem_stride *= xfer->num_lines;
-               xfer->line_length = xfer->mem_stride;
-               xfer->fb_stride = xfer->mem_stride;
-               xfer->num_lines = 1;
-       }
-
-       /*
-        * Don't lock an arbitrary large number of pages, since that causes a
-        * DOS security hole.
-        */
-
-       if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
-               DRM_ERROR("Too large PCI DMA bitblt.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * we allow a negative fb stride to allow flipping of images in
-        * transfer.
-        */
-
-       if (xfer->mem_stride < xfer->line_length ||
-               abs(xfer->fb_stride) < xfer->line_length) {
-               DRM_ERROR("Invalid frame-buffer / memory stride.\n");
-               return -EINVAL;
-       }
-
-       /*
-        * A hardware bug seems to be worked around if system memory addresses start on
-        * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
-        * about this. Meanwhile, impose the following restrictions:
-        */
-
-#ifdef VIA_BUGFREE
-       if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
-           ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
-               DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return -EINVAL;
-       }
-#else
-       if ((((unsigned long)xfer->mem_addr & 15) ||
-             ((unsigned long)xfer->fb_addr & 3)) ||
-          ((xfer->num_lines > 1) &&
-          ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
-               DRM_ERROR("Invalid DRM bitblt alignment.\n");
-               return -EINVAL;
-       }
-#endif
-
-       if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
-               DRM_ERROR("Could not lock DMA pages.\n");
-               via_free_sg_info(pdev, vsg);
-               return ret;
-       }
-
-       via_map_blit_for_device(pdev, xfer, vsg, 0);
-       if (0 != (ret = via_alloc_desc_pages(vsg))) {
-               DRM_ERROR("Could not allocate DMA descriptor pages.\n");
-               via_free_sg_info(pdev, vsg);
-               return ret;
-       }
-       via_map_blit_for_device(pdev, xfer, vsg, 1);
-
-       return 0;
-}
-
-
-/*
- * Reserve one free slot in the blit queue. Will wait for one second for one
- * to become available. Otherwise -EBUSY is returned.
- */
-
-static int
-via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
-{
-       int ret = 0;
-       unsigned long irqsave;
-
-       DRM_DEBUG("Num free is %d\n", blitq->num_free);
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       while (blitq->num_free == 0) {
-               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-               VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
-               if (ret)
-                       return (-EINTR == ret) ? -EAGAIN : ret;
-
-               spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       }
-
-       blitq->num_free--;
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-
-       return 0;
-}
-
-/*
- * Hand back a free slot if we changed our mind.
- */
-
-static void
-via_dmablit_release_slot(drm_via_blitq_t *blitq)
-{
-       unsigned long irqsave;
-
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-       blitq->num_free++;
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       wake_up(&blitq->busy_queue);
-}
-
-/*
- * Grab a free slot. Build blit info and queue a blit.
- */
-
-
-static int
-via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
-       drm_via_sg_info_t *vsg;
-       drm_via_blitq_t *blitq;
-       int ret;
-       int engine;
-       unsigned long irqsave;
-
-       if (dev_priv == NULL) {
-               DRM_ERROR("Called without initialization.\n");
-               return -EINVAL;
-       }
-
-       engine = (xfer->to_fb) ? 0 : 1;
-       blitq = dev_priv->blit_queues + engine;
-       if (0 != (ret = via_dmablit_grab_slot(blitq, engine)))
-               return ret;
-       if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
-               via_dmablit_release_slot(blitq);
-               return -ENOMEM;
-       }
-       if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
-               via_dmablit_release_slot(blitq);
-               kfree(vsg);
-               return ret;
-       }
-       spin_lock_irqsave(&blitq->blit_lock, irqsave);
-
-       blitq->blits[blitq->head++] = vsg;
-       if (blitq->head >= VIA_NUM_BLIT_SLOTS)
-               blitq->head = 0;
-       blitq->num_outstanding++;
-       xfer->sync.sync_handle = ++blitq->cur_blit_handle;
-
-       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
-       xfer->sync.engine = engine;
-
-       via_dmablit_handler(dev, engine, 0);
-
-       return 0;
-}
-
-/*
- * Sync on a previously submitted blit. Note that the X server use signals extensively, and
- * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
- * case it returns with -EAGAIN for the signal to be delivered.
- * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
- */
-
-int
-via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_blitsync_t *sync = data;
-       int err;
-
-       if (sync->engine >= VIA_NUM_BLIT_ENGINES)
-               return -EINVAL;
-
-       err = via_dmablit_sync(dev, sync->sync_handle, sync->engine);
-
-       if (-EINTR == err)
-               err = -EAGAIN;
-
-       return err;
-}
-
-
-/*
- * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
- * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
- * be reissued. See the above IOCTL code.
- */
-
-int
-via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_dmablit_t *xfer = data;
-       int err;
-
-       err = via_dmablit(dev, xfer);
-
-       return err;
-}
diff --git a/drivers/gpu/drm/via/via_dmablit.h b/drivers/gpu/drm/via/via_dmablit.h
deleted file mode 100644 (file)
index 9b662a3..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro
- *
- * Copyright 2005 Thomas Hellstrom.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Thomas Hellstrom.
- *    Register info from Digeo Inc.
- */
-
-#ifndef _VIA_DMABLIT_H
-#define _VIA_DMABLIT_H
-
-#include <linux/dma-mapping.h>
-
-#define VIA_NUM_BLIT_ENGINES 2
-#define VIA_NUM_BLIT_SLOTS 8
-
-struct _drm_via_descriptor;
-
-typedef struct _drm_via_sg_info {
-       struct page **pages;
-       unsigned long num_pages;
-       struct _drm_via_descriptor **desc_pages;
-       int num_desc_pages;
-       int num_desc;
-       enum dma_data_direction direction;
-       unsigned char *bounce_buffer;
-       dma_addr_t chain_start;
-       uint32_t free_on_sequence;
-       unsigned int descriptors_per_page;
-       int aborted;
-       enum {
-               dr_via_device_mapped,
-               dr_via_desc_pages_alloc,
-               dr_via_pages_locked,
-               dr_via_pages_alloc,
-               dr_via_sg_init
-       } state;
-} drm_via_sg_info_t;
-
-typedef struct _drm_via_blitq {
-       struct drm_device *dev;
-       uint32_t cur_blit_handle;
-       uint32_t done_blit_handle;
-       unsigned serviced;
-       unsigned head;
-       unsigned cur;
-       unsigned num_free;
-       unsigned num_outstanding;
-       unsigned long end;
-       int aborting;
-       int is_active;
-       drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
-       spinlock_t blit_lock;
-       wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
-       wait_queue_head_t busy_queue;
-       struct work_struct wq;
-       struct timer_list poll_timer;
-} drm_via_blitq_t;
-
-
-/*
- *  PCI DMA Registers
- *  Channels 2 & 3 don't seem to be implemented in hardware.
- */
-
-#define VIA_PCI_DMA_MAR0            0xE40   /* Memory Address Register of Channel 0 */
-#define VIA_PCI_DMA_DAR0            0xE44   /* Device Address Register of Channel 0 */
-#define VIA_PCI_DMA_BCR0            0xE48   /* Byte Count Register of Channel 0 */
-#define VIA_PCI_DMA_DPR0            0xE4C   /* Descriptor Pointer Register of Channel 0 */
-
-#define VIA_PCI_DMA_MAR1            0xE50   /* Memory Address Register of Channel 1 */
-#define VIA_PCI_DMA_DAR1            0xE54   /* Device Address Register of Channel 1 */
-#define VIA_PCI_DMA_BCR1            0xE58   /* Byte Count Register of Channel 1 */
-#define VIA_PCI_DMA_DPR1            0xE5C   /* Descriptor Pointer Register of Channel 1 */
-
-#define VIA_PCI_DMA_MAR2            0xE60   /* Memory Address Register of Channel 2 */
-#define VIA_PCI_DMA_DAR2            0xE64   /* Device Address Register of Channel 2 */
-#define VIA_PCI_DMA_BCR2            0xE68   /* Byte Count Register of Channel 2 */
-#define VIA_PCI_DMA_DPR2            0xE6C   /* Descriptor Pointer Register of Channel 2 */
-
-#define VIA_PCI_DMA_MAR3            0xE70   /* Memory Address Register of Channel 3 */
-#define VIA_PCI_DMA_DAR3            0xE74   /* Device Address Register of Channel 3 */
-#define VIA_PCI_DMA_BCR3            0xE78   /* Byte Count Register of Channel 3 */
-#define VIA_PCI_DMA_DPR3            0xE7C   /* Descriptor Pointer Register of Channel 3 */
-
-#define VIA_PCI_DMA_MR0             0xE80   /* Mode Register of Channel 0 */
-#define VIA_PCI_DMA_MR1             0xE84   /* Mode Register of Channel 1 */
-#define VIA_PCI_DMA_MR2             0xE88   /* Mode Register of Channel 2 */
-#define VIA_PCI_DMA_MR3             0xE8C   /* Mode Register of Channel 3 */
-
-#define VIA_PCI_DMA_CSR0            0xE90   /* Command/Status Register of Channel 0 */
-#define VIA_PCI_DMA_CSR1            0xE94   /* Command/Status Register of Channel 1 */
-#define VIA_PCI_DMA_CSR2            0xE98   /* Command/Status Register of Channel 2 */
-#define VIA_PCI_DMA_CSR3            0xE9C   /* Command/Status Register of Channel 3 */
-
-#define VIA_PCI_DMA_PTR             0xEA0   /* Priority Type Register */
-
-/* Define for DMA engine */
-/* DPR */
-#define VIA_DMA_DPR_EC         (1<<1)  /* end of chain */
-#define VIA_DMA_DPR_DDIE       (1<<2)  /* descriptor done interrupt enable */
-#define VIA_DMA_DPR_DT         (1<<3)  /* direction of transfer (RO) */
-
-/* MR */
-#define VIA_DMA_MR_CM          (1<<0)  /* chaining mode */
-#define VIA_DMA_MR_TDIE                (1<<1)  /* transfer done interrupt enable */
-#define VIA_DMA_MR_HENDMACMD           (1<<7) /* ? */
-
-/* CSR */
-#define VIA_DMA_CSR_DE         (1<<0)  /* DMA enable */
-#define VIA_DMA_CSR_TS         (1<<1)  /* transfer start */
-#define VIA_DMA_CSR_TA         (1<<2)  /* transfer abort */
-#define VIA_DMA_CSR_TD         (1<<3)  /* transfer done */
-#define VIA_DMA_CSR_DD         (1<<4)  /* descriptor done */
-#define VIA_DMA_DPR_EC          (1<<1)  /* end of chain */
-
-
-
-#endif
diff --git a/drivers/gpu/drm/via/via_dri1.c b/drivers/gpu/drm/via/via_dri1.c
new file mode 100644 (file)
index 0000000..f659c0c
--- /dev/null
@@ -0,0 +1,3630 @@
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ * Copyright 2002 Tungsten Graphics, Inc.
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. All Rights Reserved.
+ * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
+ * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A. All Rights Reserved.
+ * Copyright 2004 The Unichrome project. All Rights Reserved.
+ * Copyright 2004 BEAM Ltd.
+ * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_legacy.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_pciids.h>
+#include <drm/drm_print.h>
+#include <drm/drm_vblank.h>
+#include <drm/via_drm.h>
+
+#include "via_3d_reg.h"
+
+#define DRIVER_AUTHOR  "Various"
+
+#define DRIVER_NAME            "via"
+#define DRIVER_DESC            "VIA Unichrome / Pro"
+#define DRIVER_DATE            "20070202"
+
+#define DRIVER_MAJOR           2
+#define DRIVER_MINOR           11
+#define DRIVER_PATCHLEVEL      1
+
+typedef enum {
+       no_sequence = 0,
+       z_address,
+       dest_address,
+       tex_address
+} drm_via_sequence_t;
+
+typedef struct {
+       unsigned texture;
+       uint32_t z_addr;
+       uint32_t d_addr;
+       uint32_t t_addr[2][10];
+       uint32_t pitch[2][10];
+       uint32_t height[2][10];
+       uint32_t tex_level_lo[2];
+       uint32_t tex_level_hi[2];
+       uint32_t tex_palette_size[2];
+       uint32_t tex_npot[2];
+       drm_via_sequence_t unfinished;
+       int agp_texture;
+       int multitex;
+       struct drm_device *dev;
+       drm_local_map_t *map_cache;
+       uint32_t vertex_count;
+       int agp;
+       const uint32_t *buf_start;
+} drm_via_state_t;
+
+#define VIA_PCI_BUF_SIZE 60000
+#define VIA_FIRE_BUF_SIZE  1024
+#define VIA_NUM_IRQS 4
+
+
+#define VIA_NUM_BLIT_ENGINES 2
+#define VIA_NUM_BLIT_SLOTS 8
+
+struct _drm_via_descriptor;
+
+typedef struct _drm_via_sg_info {
+       struct page **pages;
+       unsigned long num_pages;
+       struct _drm_via_descriptor **desc_pages;
+       int num_desc_pages;
+       int num_desc;
+       enum dma_data_direction direction;
+       unsigned char *bounce_buffer;
+       dma_addr_t chain_start;
+       uint32_t free_on_sequence;
+       unsigned int descriptors_per_page;
+       int aborted;
+       enum {
+               dr_via_device_mapped,
+               dr_via_desc_pages_alloc,
+               dr_via_pages_locked,
+               dr_via_pages_alloc,
+               dr_via_sg_init
+       } state;
+} drm_via_sg_info_t;
+
+typedef struct _drm_via_blitq {
+       struct drm_device *dev;
+       uint32_t cur_blit_handle;
+       uint32_t done_blit_handle;
+       unsigned serviced;
+       unsigned head;
+       unsigned cur;
+       unsigned num_free;
+       unsigned num_outstanding;
+       unsigned long end;
+       int aborting;
+       int is_active;
+       drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS];
+       spinlock_t blit_lock;
+       wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS];
+       wait_queue_head_t busy_queue;
+       struct work_struct wq;
+       struct timer_list poll_timer;
+} drm_via_blitq_t;
+
+typedef struct drm_via_ring_buffer {
+       drm_local_map_t map;
+       char *virtual_start;
+} drm_via_ring_buffer_t;
+
+typedef uint32_t maskarray_t[5];
+
+typedef struct drm_via_irq {
+       atomic_t irq_received;
+       uint32_t pending_mask;
+       uint32_t enable_mask;
+       wait_queue_head_t irq_queue;
+} drm_via_irq_t;
+
+typedef struct drm_via_private {
+       drm_via_sarea_t *sarea_priv;
+       drm_local_map_t *sarea;
+       drm_local_map_t *fb;
+       drm_local_map_t *mmio;
+       unsigned long agpAddr;
+       wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
+       char *dma_ptr;
+       unsigned int dma_low;
+       unsigned int dma_high;
+       unsigned int dma_offset;
+       uint32_t dma_wrap;
+       volatile uint32_t *last_pause_ptr;
+       volatile uint32_t *hw_addr_ptr;
+       drm_via_ring_buffer_t ring;
+       ktime_t last_vblank;
+       int last_vblank_valid;
+       ktime_t nsec_per_vblank;
+       atomic_t vbl_received;
+       drm_via_state_t hc_state;
+       char pci_buf[VIA_PCI_BUF_SIZE];
+       const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
+       uint32_t num_fire_offsets;
+       int chipset;
+       drm_via_irq_t via_irqs[VIA_NUM_IRQS];
+       unsigned num_irqs;
+       maskarray_t *irq_masks;
+       uint32_t irq_enable_mask;
+       uint32_t irq_pending_mask;
+       int *irq_map;
+       unsigned int idle_fault;
+       int vram_initialized;
+       struct drm_mm vram_mm;
+       int agp_initialized;
+       struct drm_mm agp_mm;
+       /** Mapping of userspace keys to mm objects */
+       struct idr object_idr;
+       unsigned long vram_offset;
+       unsigned long agp_offset;
+       drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
+       uint32_t dma_diff;
+} drm_via_private_t;
+
+struct via_file_private {
+       struct list_head obj_list;
+};
+
+enum via_family {
+  VIA_OTHER = 0,     /* Baseline */
+  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
+  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
+};
+
+/* VIA MMIO register access */
+static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg)
+{
+       return readl((void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write(struct drm_via_private *dev_priv, u32 reg,
+                            u32 val)
+{
+       writel(val, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write8(struct drm_via_private *dev_priv, u32 reg,
+                             u32 val)
+{
+       writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+static inline void via_write8_mask(struct drm_via_private *dev_priv,
+                                  u32 reg, u32 mask, u32 val)
+{
+       u32 tmp;
+
+       tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg));
+       tmp = (tmp & ~mask) | (val & mask);
+       writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg));
+}
+
+/*
+ * Poll in a loop waiting for 'contidition' to be true.
+ * Note: A direct replacement with wait_event_interruptible_timeout()
+ *       will not work unless driver is updated to emit wake_up()
+ *       in relevant places that can impact the 'condition'
+ *
+ * Returns:
+ *   ret keeps current value if 'condition' becomes true
+ *   ret = -BUSY if timeout happens
+ *   ret = -EINTR if a signal interrupted the waiting period
+ */
+#define VIA_WAIT_ON( ret, queue, timeout, condition )          \
+do {                                                           \
+       DECLARE_WAITQUEUE(entry, current);                      \
+       unsigned long end = jiffies + (timeout);                \
+       add_wait_queue(&(queue), &entry);                       \
+                                                               \
+       for (;;) {                                              \
+               __set_current_state(TASK_INTERRUPTIBLE);        \
+               if (condition)                                  \
+                       break;                                  \
+               if (time_after_eq(jiffies, end)) {              \
+                       ret = -EBUSY;                           \
+                       break;                                  \
+               }                                               \
+               schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);    \
+               if (signal_pending(current)) {                  \
+                       ret = -EINTR;                           \
+                       break;                                  \
+               }                                               \
+       }                                                       \
+       __set_current_state(TASK_RUNNING);                      \
+       remove_wait_queue(&(queue), &entry);                    \
+} while (0)
+
+int via_do_cleanup_map(struct drm_device *dev);
+
+int via_dma_cleanup(struct drm_device *dev);
+int via_driver_dma_quiescent(struct drm_device *dev);
+
+#define CMDBUF_ALIGNMENT_SIZE   (0x100)
+#define CMDBUF_ALIGNMENT_MASK   (0x0ff)
+
+/* defines for VIA 3D registers */
+#define VIA_REG_STATUS          0x400
+#define VIA_REG_TRANSET         0x43C
+#define VIA_REG_TRANSPACE       0x440
+
+/* VIA_REG_STATUS(0x400): Engine Status */
+#define VIA_CMD_RGTR_BUSY       0x00000080     /* Command Regulator is busy */
+#define VIA_2D_ENG_BUSY         0x00000001     /* 2D Engine is busy */
+#define VIA_3D_ENG_BUSY         0x00000002     /* 3D Engine is busy */
+#define VIA_VR_QUEUE_BUSY       0x00020000     /* Virtual Queue is busy */
+
+#define SetReg2DAGP(nReg, nData) {                             \
+       *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1;  \
+       *((uint32_t *)(vb) + 1) = (nData);                      \
+       vb = ((uint32_t *)vb) + 2;                              \
+       dev_priv->dma_low += 8;                                 \
+}
+
+#define via_flush_write_combine() mb()
+
+#define VIA_OUT_RING_QW(w1, w2)        do {            \
+       *vb++ = (w1);                           \
+       *vb++ = (w2);                           \
+       dev_priv->dma_low += 8;                 \
+} while (0)
+
+#define VIA_MM_ALIGN_SHIFT 4
+#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1)
+
+struct via_memblock {
+       struct drm_mm_node mm_node;
+       struct list_head owner_list;
+};
+
+#define VIA_REG_INTERRUPT       0x200
+
+/* VIA_REG_INTERRUPT */
+#define VIA_IRQ_GLOBAL   (1 << 31)
+#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
+#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
+#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
+#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
+#define VIA_IRQ_HQV0_PENDING    (1 << 9)
+#define VIA_IRQ_HQV1_PENDING    (1 << 10)
+#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
+#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
+#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
+#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
+#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
+#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
+#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
+#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
+
+/*
+ *  PCI DMA Registers
+ *  Channels 2 & 3 don't seem to be implemented in hardware.
+ */
+
+#define VIA_PCI_DMA_MAR0            0xE40   /* Memory Address Register of Channel 0 */
+#define VIA_PCI_DMA_DAR0            0xE44   /* Device Address Register of Channel 0 */
+#define VIA_PCI_DMA_BCR0            0xE48   /* Byte Count Register of Channel 0 */
+#define VIA_PCI_DMA_DPR0            0xE4C   /* Descriptor Pointer Register of Channel 0 */
+
+#define VIA_PCI_DMA_MAR1            0xE50   /* Memory Address Register of Channel 1 */
+#define VIA_PCI_DMA_DAR1            0xE54   /* Device Address Register of Channel 1 */
+#define VIA_PCI_DMA_BCR1            0xE58   /* Byte Count Register of Channel 1 */
+#define VIA_PCI_DMA_DPR1            0xE5C   /* Descriptor Pointer Register of Channel 1 */
+
+#define VIA_PCI_DMA_MAR2            0xE60   /* Memory Address Register of Channel 2 */
+#define VIA_PCI_DMA_DAR2            0xE64   /* Device Address Register of Channel 2 */
+#define VIA_PCI_DMA_BCR2            0xE68   /* Byte Count Register of Channel 2 */
+#define VIA_PCI_DMA_DPR2            0xE6C   /* Descriptor Pointer Register of Channel 2 */
+
+#define VIA_PCI_DMA_MAR3            0xE70   /* Memory Address Register of Channel 3 */
+#define VIA_PCI_DMA_DAR3            0xE74   /* Device Address Register of Channel 3 */
+#define VIA_PCI_DMA_BCR3            0xE78   /* Byte Count Register of Channel 3 */
+#define VIA_PCI_DMA_DPR3            0xE7C   /* Descriptor Pointer Register of Channel 3 */
+
+#define VIA_PCI_DMA_MR0             0xE80   /* Mode Register of Channel 0 */
+#define VIA_PCI_DMA_MR1             0xE84   /* Mode Register of Channel 1 */
+#define VIA_PCI_DMA_MR2             0xE88   /* Mode Register of Channel 2 */
+#define VIA_PCI_DMA_MR3             0xE8C   /* Mode Register of Channel 3 */
+
+#define VIA_PCI_DMA_CSR0            0xE90   /* Command/Status Register of Channel 0 */
+#define VIA_PCI_DMA_CSR1            0xE94   /* Command/Status Register of Channel 1 */
+#define VIA_PCI_DMA_CSR2            0xE98   /* Command/Status Register of Channel 2 */
+#define VIA_PCI_DMA_CSR3            0xE9C   /* Command/Status Register of Channel 3 */
+
+#define VIA_PCI_DMA_PTR             0xEA0   /* Priority Type Register */
+
+/* Define for DMA engine */
+/* DPR */
+#define VIA_DMA_DPR_EC         (1<<1)  /* end of chain */
+#define VIA_DMA_DPR_DDIE       (1<<2)  /* descriptor done interrupt enable */
+#define VIA_DMA_DPR_DT         (1<<3)  /* direction of transfer (RO) */
+
+/* MR */
+#define VIA_DMA_MR_CM          (1<<0)  /* chaining mode */
+#define VIA_DMA_MR_TDIE                (1<<1)  /* transfer done interrupt enable */
+#define VIA_DMA_MR_HENDMACMD           (1<<7) /* ? */
+
+/* CSR */
+#define VIA_DMA_CSR_DE         (1<<0)  /* DMA enable */
+#define VIA_DMA_CSR_TS         (1<<1)  /* transfer start */
+#define VIA_DMA_CSR_TA         (1<<2)  /* transfer abort */
+#define VIA_DMA_CSR_TD         (1<<3)  /* transfer done */
+#define VIA_DMA_CSR_DD         (1<<4)  /* descriptor done */
+#define VIA_DMA_DPR_EC          (1<<1)  /* end of chain */
+
+/*
+ * Device-specific IRQs go here. This type might need to be extended with
+ * the register if there are multiple IRQ control registers.
+ * Currently we activate the HQV interrupts of  Unichrome Pro group A.
+ */
+
+static maskarray_t via_pro_group_a_irqs[] = {
+       {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
+        0x00000000 },
+       {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
+        0x00000000 },
+       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+};
+static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
+static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
+
+static maskarray_t via_unichrome_irqs[] = {
+       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
+       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
+        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
+};
+static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
+static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
+
+
+/*
+ * Unmaps the DMA mappings.
+ * FIXME: Is this a NoOp on x86? Also
+ * FIXME: What happens if this one is called and a pending blit has previously done
+ * the same DMA mappings?
+ */
+#define VIA_PGDN(x)         (((unsigned long)(x)) & PAGE_MASK)
+#define VIA_PGOFF(x)       (((unsigned long)(x)) & ~PAGE_MASK)
+#define VIA_PFN(x)           ((unsigned long)(x) >> PAGE_SHIFT)
+
+typedef struct _drm_via_descriptor {
+       uint32_t mem_addr;
+       uint32_t dev_addr;
+       uint32_t size;
+       uint32_t next;
+} drm_via_descriptor_t;
+
+typedef enum {
+       state_command,
+       state_header2,
+       state_header1,
+       state_vheader5,
+       state_vheader6,
+       state_error
+} verifier_state_t;
+
+typedef enum {
+       no_check = 0,
+       check_for_header2,
+       check_for_header1,
+       check_for_header2_err,
+       check_for_header1_err,
+       check_for_fire,
+       check_z_buffer_addr0,
+       check_z_buffer_addr1,
+       check_z_buffer_addr_mode,
+       check_destination_addr0,
+       check_destination_addr1,
+       check_destination_addr_mode,
+       check_for_dummy,
+       check_for_dd,
+       check_texture_addr0,
+       check_texture_addr1,
+       check_texture_addr2,
+       check_texture_addr3,
+       check_texture_addr4,
+       check_texture_addr5,
+       check_texture_addr6,
+       check_texture_addr7,
+       check_texture_addr8,
+       check_texture_addr_mode,
+       check_for_vertex_count,
+       check_number_texunits,
+       forbidden_command
+} hazard_t;
+
+/*
+ * Associates each hazard above with a possible multi-command
+ * sequence. For example an address that is split over multiple
+ * commands and that needs to be checked at the first command
+ * that does not include any part of the address.
+ */
+
+static drm_via_sequence_t seqs[] = {
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       no_sequence,
+       z_address,
+       z_address,
+       z_address,
+       dest_address,
+       dest_address,
+       dest_address,
+       no_sequence,
+       no_sequence,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       tex_address,
+       no_sequence
+};
+
+typedef struct {
+       unsigned int code;
+       hazard_t hz;
+} hz_init_t;
+
+static hz_init_t init_table1[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xee, check_for_fire},
+       {0xcc, check_for_dummy},
+       {0xdd, check_for_dd},
+       {0x00, no_check},
+       {0x10, check_z_buffer_addr0},
+       {0x11, check_z_buffer_addr1},
+       {0x12, check_z_buffer_addr_mode},
+       {0x13, no_check},
+       {0x14, no_check},
+       {0x15, no_check},
+       {0x23, no_check},
+       {0x24, no_check},
+       {0x33, no_check},
+       {0x34, no_check},
+       {0x35, no_check},
+       {0x36, no_check},
+       {0x37, no_check},
+       {0x38, no_check},
+       {0x39, no_check},
+       {0x3A, no_check},
+       {0x3B, no_check},
+       {0x3C, no_check},
+       {0x3D, no_check},
+       {0x3E, no_check},
+       {0x40, check_destination_addr0},
+       {0x41, check_destination_addr1},
+       {0x42, check_destination_addr_mode},
+       {0x43, no_check},
+       {0x44, no_check},
+       {0x50, no_check},
+       {0x51, no_check},
+       {0x52, no_check},
+       {0x53, no_check},
+       {0x54, no_check},
+       {0x55, no_check},
+       {0x56, no_check},
+       {0x57, no_check},
+       {0x58, no_check},
+       {0x70, no_check},
+       {0x71, no_check},
+       {0x78, no_check},
+       {0x79, no_check},
+       {0x7A, no_check},
+       {0x7B, no_check},
+       {0x7C, no_check},
+       {0x7D, check_for_vertex_count}
+};
+
+static hz_init_t init_table2[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xee, check_for_fire},
+       {0xcc, check_for_dummy},
+       {0x00, check_texture_addr0},
+       {0x01, check_texture_addr0},
+       {0x02, check_texture_addr0},
+       {0x03, check_texture_addr0},
+       {0x04, check_texture_addr0},
+       {0x05, check_texture_addr0},
+       {0x06, check_texture_addr0},
+       {0x07, check_texture_addr0},
+       {0x08, check_texture_addr0},
+       {0x09, check_texture_addr0},
+       {0x20, check_texture_addr1},
+       {0x21, check_texture_addr1},
+       {0x22, check_texture_addr1},
+       {0x23, check_texture_addr4},
+       {0x2B, check_texture_addr3},
+       {0x2C, check_texture_addr3},
+       {0x2D, check_texture_addr3},
+       {0x2E, check_texture_addr3},
+       {0x2F, check_texture_addr3},
+       {0x30, check_texture_addr3},
+       {0x31, check_texture_addr3},
+       {0x32, check_texture_addr3},
+       {0x33, check_texture_addr3},
+       {0x34, check_texture_addr3},
+       {0x4B, check_texture_addr5},
+       {0x4C, check_texture_addr6},
+       {0x51, check_texture_addr7},
+       {0x52, check_texture_addr8},
+       {0x77, check_texture_addr2},
+       {0x78, no_check},
+       {0x79, no_check},
+       {0x7A, no_check},
+       {0x7B, check_texture_addr_mode},
+       {0x7C, no_check},
+       {0x7D, no_check},
+       {0x7E, no_check},
+       {0x7F, no_check},
+       {0x80, no_check},
+       {0x81, no_check},
+       {0x82, no_check},
+       {0x83, no_check},
+       {0x85, no_check},
+       {0x86, no_check},
+       {0x87, no_check},
+       {0x88, no_check},
+       {0x89, no_check},
+       {0x8A, no_check},
+       {0x90, no_check},
+       {0x91, no_check},
+       {0x92, no_check},
+       {0x93, no_check}
+};
+
+static hz_init_t init_table3[] = {
+       {0xf2, check_for_header2_err},
+       {0xf0, check_for_header1_err},
+       {0xcc, check_for_dummy},
+       {0x00, check_number_texunits}
+};
+
+static hazard_t table1[256];
+static hazard_t table2[256];
+static hazard_t table3[256];
+
+static __inline__ int
+eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
+{
+       if ((buf_end - *buf) >= num_words) {
+               *buf += num_words;
+               return 0;
+       }
+       DRM_ERROR("Illegal termination of DMA command buffer\n");
+       return 1;
+}
+
+/*
+ * Partially stolen from drm_memory.h
+ */
+
+static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
+                                                   unsigned long offset,
+                                                   unsigned long size,
+                                                   struct drm_device *dev)
+{
+       struct drm_map_list *r_list;
+       drm_local_map_t *map = seq->map_cache;
+
+       if (map && map->offset <= offset
+           && (offset + size) <= (map->offset + map->size)) {
+               return map;
+       }
+
+       list_for_each_entry(r_list, &dev->maplist, head) {
+               map = r_list->map;
+               if (!map)
+                       continue;
+               if (map->offset <= offset
+                   && (offset + size) <= (map->offset + map->size)
+                   && !(map->flags & _DRM_RESTRICTED)
+                   && (map->type == _DRM_AGP)) {
+                       seq->map_cache = map;
+                       return map;
+               }
+       }
+       return NULL;
+}
+
+/*
+ * Require that all AGP texture levels reside in the same AGP map which should
+ * be mappable by the client. This is not a big restriction.
+ * FIXME: To actually enforce this security policy strictly, drm_rmmap
+ * would have to wait for dma quiescent before removing an AGP map.
+ * The via_drm_lookup_agp_map call in reality seems to take
+ * very little CPU time.
+ */
+
+static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
+{
+       switch (cur_seq->unfinished) {
+       case z_address:
+               DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
+               break;
+       case dest_address:
+               DRM_DEBUG("Destination start address is 0x%x\n",
+                         cur_seq->d_addr);
+               break;
+       case tex_address:
+               if (cur_seq->agp_texture) {
+                       unsigned start =
+                           cur_seq->tex_level_lo[cur_seq->texture];
+                       unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
+                       unsigned long lo = ~0, hi = 0, tmp;
+                       uint32_t *addr, *pitch, *height, tex;
+                       unsigned i;
+                       int npot;
+
+                       if (end > 9)
+                               end = 9;
+                       if (start > 9)
+                               start = 9;
+
+                       addr =
+                           &(cur_seq->t_addr[tex = cur_seq->texture][start]);
+                       pitch = &(cur_seq->pitch[tex][start]);
+                       height = &(cur_seq->height[tex][start]);
+                       npot = cur_seq->tex_npot[tex];
+                       for (i = start; i <= end; ++i) {
+                               tmp = *addr++;
+                               if (tmp < lo)
+                                       lo = tmp;
+                               if (i == 0 && npot)
+                                       tmp += (*height++ * *pitch++);
+                               else
+                                       tmp += (*height++ << *pitch++);
+                               if (tmp > hi)
+                                       hi = tmp;
+                       }
+
+                       if (!via_drm_lookup_agp_map
+                           (cur_seq, lo, hi - lo, cur_seq->dev)) {
+                               DRM_ERROR
+                                   ("AGP texture is not in allowed map\n");
+                               return 2;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+       cur_seq->unfinished = no_sequence;
+       return 0;
+}
+
+static __inline__ int
+investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
+{
+       register uint32_t tmp, *tmp_addr;
+
+       if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
+               int ret;
+               if ((ret = finish_current_sequence(cur_seq)))
+                       return ret;
+       }
+
+       switch (hz) {
+       case check_for_header2:
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
+               return 0;
+       case check_for_header1:
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
+               return 0;
+       case check_for_header2_err:
+               if (cmd == HALCYON_HEADER2)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
+               break;
+       case check_for_header1_err:
+               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
+               break;
+       case check_for_fire:
+               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
+                       return 1;
+               DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
+               break;
+       case check_for_dummy:
+               if (HC_DUMMY == cmd)
+                       return 0;
+               DRM_ERROR("Illegal DMA HC_DUMMY command\n");
+               break;
+       case check_for_dd:
+               if (0xdddddddd == cmd)
+                       return 0;
+               DRM_ERROR("Illegal DMA 0xdddddddd command\n");
+               break;
+       case check_z_buffer_addr0:
+               cur_seq->unfinished = z_address;
+               cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
+                   (cmd & 0x00FFFFFF);
+               return 0;
+       case check_z_buffer_addr1:
+               cur_seq->unfinished = z_address;
+               cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
+                   ((cmd & 0xFF) << 24);
+               return 0;
+       case check_z_buffer_addr_mode:
+               cur_seq->unfinished = z_address;
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
+               DRM_ERROR("Attempt to place Z buffer in system memory\n");
+               return 2;
+       case check_destination_addr0:
+               cur_seq->unfinished = dest_address;
+               cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
+                   (cmd & 0x00FFFFFF);
+               return 0;
+       case check_destination_addr1:
+               cur_seq->unfinished = dest_address;
+               cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
+                   ((cmd & 0xFF) << 24);
+               return 0;
+       case check_destination_addr_mode:
+               cur_seq->unfinished = dest_address;
+               if ((cmd & 0x0000C000) == 0)
+                       return 0;
+               DRM_ERROR
+                   ("Attempt to place 3D drawing buffer in system memory\n");
+               return 2;
+       case check_texture_addr0:
+               cur_seq->unfinished = tex_address;
+               tmp = (cmd >> 24);
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+               *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
+               return 0;
+       case check_texture_addr1:
+               cur_seq->unfinished = tex_address;
+               tmp = ((cmd >> 24) - 0x20);
+               tmp += tmp << 1;
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+               tmp_addr++;
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
+               tmp_addr++;
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
+               return 0;
+       case check_texture_addr2:
+               cur_seq->unfinished = tex_address;
+               cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
+               cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
+               return 0;
+       case check_texture_addr3:
+               cur_seq->unfinished = tex_address;
+               tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
+               if (tmp == 0 &&
+                   (cmd & HC_HTXnEnPit_MASK)) {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPit_MASK);
+                       cur_seq->tex_npot[cur_seq->texture] = 1;
+               } else {
+                       cur_seq->pitch[cur_seq->texture][tmp] =
+                               (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
+                       cur_seq->tex_npot[cur_seq->texture] = 0;
+                       if (cmd & 0x000FFFFF) {
+                               DRM_ERROR
+                                       ("Unimplemented texture level 0 pitch mode.\n");
+                               return 2;
+                       }
+               }
+               return 0;
+       case check_texture_addr4:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
+               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
+               return 0;
+       case check_texture_addr5:
+       case check_texture_addr6:
+               cur_seq->unfinished = tex_address;
+               /*
+                * Texture width. We don't care since we have the pitch.
+                */
+               return 0;
+       case check_texture_addr7:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+               tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
+               tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
+               tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
+               tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
+               tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
+               tmp_addr[0] = 1 << (cmd & 0x0000000F);
+               return 0;
+       case check_texture_addr8:
+               cur_seq->unfinished = tex_address;
+               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
+               tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
+               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
+               tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
+               tmp_addr[6] = 1 << (cmd & 0x0000000F);
+               return 0;
+       case check_texture_addr_mode:
+               cur_seq->unfinished = tex_address;
+               if (2 == (tmp = cmd & 0x00000003)) {
+                       DRM_ERROR
+                           ("Attempt to fetch texture from system memory.\n");
+                       return 2;
+               }
+               cur_seq->agp_texture = (tmp == 3);
+               cur_seq->tex_palette_size[cur_seq->texture] =
+                   (cmd >> 16) & 0x000000007;
+               return 0;
+       case check_for_vertex_count:
+               cur_seq->vertex_count = cmd & 0x0000FFFF;
+               return 0;
+       case check_number_texunits:
+               cur_seq->multitex = (cmd >> 3) & 1;
+               return 0;
+       default:
+               DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
+               return 2;
+       }
+       return 2;
+}
+
+static __inline__ int
+via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
+                   drm_via_state_t *cur_seq)
+{
+       drm_via_private_t *dev_priv =
+           (drm_via_private_t *) cur_seq->dev->dev_private;
+       uint32_t a_fire, bcmd, dw_count;
+       int ret = 0;
+       int have_fire;
+       const uint32_t *buf = *buffer;
+
+       while (buf < buf_end) {
+               have_fire = 0;
+               if ((buf_end - buf) < 2) {
+                       DRM_ERROR
+                           ("Unexpected termination of primitive list.\n");
+                       ret = 1;
+                       break;
+               }
+               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
+                       break;
+               bcmd = *buf++;
+               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
+                       DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
+                                 *buf);
+                       ret = 1;
+                       break;
+               }
+               a_fire =
+                   *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
+                   HC_HE3Fire_MASK;
+
+               /*
+                * How many dwords per vertex ?
+                */
+
+               if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
+                       DRM_ERROR("Illegal B command vertex data for AGP.\n");
+                       ret = 1;
+                       break;
+               }
+
+               dw_count = 0;
+               if (bcmd & (1 << 7))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 8))
+                       dw_count += (cur_seq->multitex) ? 2 : 1;
+               if (bcmd & (1 << 9))
+                       dw_count++;
+               if (bcmd & (1 << 10))
+                       dw_count++;
+               if (bcmd & (1 << 11))
+                       dw_count++;
+               if (bcmd & (1 << 12))
+                       dw_count++;
+               if (bcmd & (1 << 13))
+                       dw_count++;
+               if (bcmd & (1 << 14))
+                       dw_count++;
+
+               while (buf < buf_end) {
+                       if (*buf == a_fire) {
+                               if (dev_priv->num_fire_offsets >=
+                                   VIA_FIRE_BUF_SIZE) {
+                                       DRM_ERROR("Fire offset buffer full.\n");
+                                       ret = 1;
+                                       break;
+                               }
+                               dev_priv->fire_offsets[dev_priv->
+                                                      num_fire_offsets++] =
+                                   buf;
+                               have_fire = 1;
+                               buf++;
+                               if (buf < buf_end && *buf == a_fire)
+                                       buf++;
+                               break;
+                       }
+                       if ((*buf == HALCYON_HEADER2) ||
+                           ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
+                               DRM_ERROR("Missing Vertex Fire command, "
+                                         "Stray Vertex Fire command  or verifier "
+                                         "lost sync.\n");
+                               ret = 1;
+                               break;
+                       }
+                       if ((ret = eat_words(&buf, buf_end, dw_count)))
+                               break;
+               }
+               if (buf >= buf_end && !have_fire) {
+                       DRM_ERROR("Missing Vertex Fire command or verifier "
+                                 "lost sync.\n");
+                       ret = 1;
+                       break;
+               }
+               if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
+                       DRM_ERROR("AGP Primitive list end misaligned.\n");
+                       ret = 1;
+                       break;
+               }
+       }
+       *buffer = buf;
+       return ret;
+}
+
+static __inline__ verifier_state_t
+via_check_header2(uint32_t const **buffer, const uint32_t *buf_end,
+                 drm_via_state_t *hc_state)
+{
+       uint32_t cmd;
+       int hz_mode;
+       hazard_t hz;
+       const uint32_t *buf = *buffer;
+       const hazard_t *hz_table;
+
+       if ((buf_end - buf) < 2) {
+               DRM_ERROR
+                   ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
+               return state_error;
+       }
+       buf++;
+       cmd = (*buf++ & 0xFFFF0000) >> 16;
+
+       switch (cmd) {
+       case HC_ParaType_CmdVdata:
+               if (via_check_prim_list(&buf, buf_end, hc_state))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case HC_ParaType_NotTex:
+               hz_table = table1;
+               break;
+       case HC_ParaType_Tex:
+               hc_state->texture = 0;
+               hz_table = table2;
+               break;
+       case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
+               hc_state->texture = 1;
+               hz_table = table2;
+               break;
+       case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
+               hz_table = table3;
+               break;
+       case HC_ParaType_Auto:
+               if (eat_words(&buf, buf_end, 2))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
+               if (eat_words(&buf, buf_end, 32))
+                       return state_error;
+               *buffer = buf;
+               return state_command;
+       case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
+       case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
+               DRM_ERROR("Texture palettes are rejected because of "
+                         "lack of info how to determine their size.\n");
+               return state_error;
+       case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
+               DRM_ERROR("Fog factor palettes are rejected because of "
+                         "lack of info how to determine their size.\n");
+               return state_error;
+       default:
+
+               /*
+                * There are some unimplemented HC_ParaTypes here, that
+                * need to be implemented if the Mesa driver is extended.
+                */
+
+               DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
+                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
+                         cmd, *(buf - 2));
+               *buffer = buf;
+               return state_error;
+       }
+
+       while (buf < buf_end) {
+               cmd = *buf++;
+               if ((hz = hz_table[cmd >> 24])) {
+                       if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
+                               if (hz_mode == 1) {
+                                       buf--;
+                                       break;
+                               }
+                               return state_error;
+                       }
+               } else if (hc_state->unfinished &&
+                          finish_current_sequence(hc_state)) {
+                       return state_error;
+               }
+       }
+       if (hc_state->unfinished && finish_current_sequence(hc_state))
+               return state_error;
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
+                 const uint32_t *buf_end, int *fire_count)
+{
+       uint32_t cmd;
+       const uint32_t *buf = *buffer;
+       const uint32_t *next_fire;
+       int burst = 0;
+
+       next_fire = dev_priv->fire_offsets[*fire_count];
+       buf++;
+       cmd = (*buf & 0xFFFF0000) >> 16;
+       via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
+       switch (cmd) {
+       case HC_ParaType_CmdVdata:
+               while ((buf < buf_end) &&
+                      (*fire_count < dev_priv->num_fire_offsets) &&
+                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
+                       while (buf <= next_fire) {
+                               via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                         (burst & 63), *buf++);
+                               burst += 4;
+                       }
+                       if ((buf < buf_end)
+                           && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
+                               buf++;
+
+                       if (++(*fire_count) < dev_priv->num_fire_offsets)
+                               next_fire = dev_priv->fire_offsets[*fire_count];
+               }
+               break;
+       default:
+               while (buf < buf_end) {
+
+                       if (*buf == HC_HEADER2 ||
+                           (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
+                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               break;
+
+                       via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
+                                 (burst & 63), *buf++);
+                       burst += 4;
+               }
+       }
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ int verify_mmio_address(uint32_t address)
+{
+       if ((address > 0x3FF) && (address < 0xC00)) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access 3D- or command burst area.\n");
+               return 1;
+       } else if ((address > 0xCFF) && (address < 0x1300)) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access PCI DMA area.\n");
+               return 1;
+       } else if (address > 0x13FF) {
+               DRM_ERROR("Invalid VIDEO DMA command. "
+                         "Attempt to access VGA registers.\n");
+               return 1;
+       }
+       return 0;
+}
+
+static __inline__ int
+verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
+                 uint32_t dwords)
+{
+       const uint32_t *buf = *buffer;
+
+       if (buf_end - buf < dwords) {
+               DRM_ERROR("Illegal termination of video command.\n");
+               return 1;
+       }
+       while (dwords--) {
+               if (*buf++) {
+                       DRM_ERROR("Illegal video command tail.\n");
+                       return 1;
+               }
+       }
+       *buffer = buf;
+       return 0;
+}
+
+static __inline__ verifier_state_t
+via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
+{
+       uint32_t cmd;
+       const uint32_t *buf = *buffer;
+       verifier_state_t ret = state_command;
+
+       while (buf < buf_end) {
+               cmd = *buf;
+               if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
+                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                               break;
+                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+                                 "Attempt to access 3D- or command burst area.\n");
+                       ret = state_error;
+                       break;
+               } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
+                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                               break;
+                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
+                                 "Attempt to access VGA registers.\n");
+                       ret = state_error;
+                       break;
+               } else {
+                       buf += 2;
+               }
+       }
+       *buffer = buf;
+       return ret;
+}
+
+static __inline__ verifier_state_t
+via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,
+                 const uint32_t *buf_end)
+{
+       register uint32_t cmd;
+       const uint32_t *buf = *buffer;
+
+       while (buf < buf_end) {
+               cmd = *buf;
+               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
+                       break;
+               via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
+               buf++;
+       }
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end)
+{
+       uint32_t data;
+       const uint32_t *buf = *buffer;
+
+       if (buf_end - buf < 4) {
+               DRM_ERROR("Illegal termination of video header5 command\n");
+               return state_error;
+       }
+
+       data = *buf++ & ~VIA_VIDEOMASK;
+       if (verify_mmio_address(data))
+               return state_error;
+
+       data = *buf++;
+       if (*buf++ != 0x00F50000) {
+               DRM_ERROR("Illegal header5 header data\n");
+               return state_error;
+       }
+       if (*buf++ != 0x00000000) {
+               DRM_ERROR("Illegal header5 header data\n");
+               return state_error;
+       }
+       if (eat_words(&buf, buf_end, data))
+               return state_error;
+       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+               return state_error;
+       *buffer = buf;
+       return state_command;
+
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,
+                  const uint32_t *buf_end)
+{
+       uint32_t addr, count, i;
+       const uint32_t *buf = *buffer;
+
+       addr = *buf++ & ~VIA_VIDEOMASK;
+       i = count = *buf;
+       buf += 3;
+       while (i--)
+               via_write(dev_priv, addr, *buf++);
+       if (count & 3)
+               buf += 4 - (count & 3);
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
+{
+       uint32_t data;
+       const uint32_t *buf = *buffer;
+       uint32_t i;
+
+       if (buf_end - buf < 4) {
+               DRM_ERROR("Illegal termination of video header6 command\n");
+               return state_error;
+       }
+       buf++;
+       data = *buf++;
+       if (*buf++ != 0x00F60000) {
+               DRM_ERROR("Illegal header6 header data\n");
+               return state_error;
+       }
+       if (*buf++ != 0x00000000) {
+               DRM_ERROR("Illegal header6 header data\n");
+               return state_error;
+       }
+       if ((buf_end - buf) < (data << 1)) {
+               DRM_ERROR("Illegal termination of video header6 command\n");
+               return state_error;
+       }
+       for (i = 0; i < data; ++i) {
+               if (verify_mmio_address(*buf++))
+                       return state_error;
+               buf++;
+       }
+       data <<= 1;
+       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
+               return state_error;
+       *buffer = buf;
+       return state_command;
+}
+
+static __inline__ verifier_state_t
+via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer,
+                  const uint32_t *buf_end)
+{
+
+       uint32_t addr, count, i;
+       const uint32_t *buf = *buffer;
+
+       i = count = *++buf;
+       buf += 3;
+       while (i--) {
+               addr = *buf++;
+               via_write(dev_priv, addr, *buf++);
+       }
+       count <<= 1;
+       if (count & 3)
+               buf += 4 - (count & 3);
+       *buffer = buf;
+       return state_command;
+}
+
+static int
+via_verify_command_stream(const uint32_t * buf, unsigned int size,
+                         struct drm_device * dev, int agp)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_state_t *hc_state = &dev_priv->hc_state;
+       drm_via_state_t saved_state = *hc_state;
+       uint32_t cmd;
+       const uint32_t *buf_end = buf + (size >> 2);
+       verifier_state_t state = state_command;
+       int cme_video;
+       int supported_3d;
+
+       cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
+                    dev_priv->chipset == VIA_DX9_0);
+
+       supported_3d = dev_priv->chipset != VIA_DX9_0;
+
+       hc_state->dev = dev;
+       hc_state->unfinished = no_sequence;
+       hc_state->map_cache = NULL;
+       hc_state->agp = agp;
+       hc_state->buf_start = buf;
+       dev_priv->num_fire_offsets = 0;
+
+       while (buf < buf_end) {
+
+               switch (state) {
+               case state_header2:
+                       state = via_check_header2(&buf, buf_end, hc_state);
+                       break;
+               case state_header1:
+                       state = via_check_header1(&buf, buf_end);
+                       break;
+               case state_vheader5:
+                       state = via_check_vheader5(&buf, buf_end);
+                       break;
+               case state_vheader6:
+                       state = via_check_vheader6(&buf, buf_end);
+                       break;
+               case state_command:
+                       cmd = *buf;
+                       if ((cmd == HALCYON_HEADER2) && supported_3d)
+                               state = state_header2;
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                               state = state_header1;
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                               state = state_vheader5;
+                       else if (cme_video
+                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               state = state_vheader6;
+                       else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
+                               DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
+                               state = state_error;
+                       } else {
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
+                               state = state_error;
+                       }
+                       break;
+               case state_error:
+               default:
+                       *hc_state = saved_state;
+                       return -EINVAL;
+               }
+       }
+       if (state == state_error) {
+               *hc_state = saved_state;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int
+via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
+                        unsigned int size)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       uint32_t cmd;
+       const uint32_t *buf_end = buf + (size >> 2);
+       verifier_state_t state = state_command;
+       int fire_count = 0;
+
+       while (buf < buf_end) {
+
+               switch (state) {
+               case state_header2:
+                       state =
+                           via_parse_header2(dev_priv, &buf, buf_end,
+                                             &fire_count);
+                       break;
+               case state_header1:
+                       state = via_parse_header1(dev_priv, &buf, buf_end);
+                       break;
+               case state_vheader5:
+                       state = via_parse_vheader5(dev_priv, &buf, buf_end);
+                       break;
+               case state_vheader6:
+                       state = via_parse_vheader6(dev_priv, &buf, buf_end);
+                       break;
+               case state_command:
+                       cmd = *buf;
+                       if (cmd == HALCYON_HEADER2)
+                               state = state_header2;
+                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
+                               state = state_header1;
+                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
+                               state = state_vheader5;
+                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
+                               state = state_vheader6;
+                       else {
+                               DRM_ERROR
+                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
+                                    cmd);
+                               state = state_error;
+                       }
+                       break;
+               case state_error:
+               default:
+                       return -EINVAL;
+               }
+       }
+       if (state == state_error)
+               return -EINVAL;
+       return 0;
+}
+
+static void
+setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
+{
+       int i;
+
+       for (i = 0; i < 256; ++i)
+               table[i] = forbidden_command;
+
+       for (i = 0; i < size; ++i)
+               table[init_table[i].code] = init_table[i].hz;
+}
+
+static void via_init_command_verifier(void)
+{
+       setup_hazard_table(init_table1, table1, ARRAY_SIZE(init_table1));
+       setup_hazard_table(init_table2, table2, ARRAY_SIZE(init_table2));
+       setup_hazard_table(init_table3, table3, ARRAY_SIZE(init_table3));
+}
+/*
+ * Unmap a DMA mapping.
+ */
+static void
+via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+       int num_desc = vsg->num_desc;
+       unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page;
+       unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page;
+       drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+               descriptor_this_page;
+       dma_addr_t next = vsg->chain_start;
+
+       while (num_desc--) {
+               if (descriptor_this_page-- == 0) {
+                       cur_descriptor_page--;
+                       descriptor_this_page = vsg->descriptors_per_page - 1;
+                       desc_ptr = vsg->desc_pages[cur_descriptor_page] +
+                               descriptor_this_page;
+               }
+               dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE);
+               dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction);
+               next = (dma_addr_t) desc_ptr->next;
+               desc_ptr--;
+       }
+}
+
+/*
+ * If mode = 0, count how many descriptors are needed.
+ * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors.
+ * Descriptors are run in reverse order by the hardware because we are not allowed to update the
+ * 'next' field without syncing calls when the descriptor is already mapped.
+ */
+static void
+via_map_blit_for_device(struct pci_dev *pdev,
+                  const drm_via_dmablit_t *xfer,
+                  drm_via_sg_info_t *vsg,
+                  int mode)
+{
+       unsigned cur_descriptor_page = 0;
+       unsigned num_descriptors_this_page = 0;
+       unsigned char *mem_addr = xfer->mem_addr;
+       unsigned char *cur_mem;
+       unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr);
+       uint32_t fb_addr = xfer->fb_addr;
+       uint32_t cur_fb;
+       unsigned long line_len;
+       unsigned remaining_len;
+       int num_desc = 0;
+       int cur_line;
+       dma_addr_t next = 0 | VIA_DMA_DPR_EC;
+       drm_via_descriptor_t *desc_ptr = NULL;
+
+       if (mode == 1)
+               desc_ptr = vsg->desc_pages[cur_descriptor_page];
+
+       for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) {
+
+               line_len = xfer->line_length;
+               cur_fb = fb_addr;
+               cur_mem = mem_addr;
+
+               while (line_len > 0) {
+
+                       remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len);
+                       line_len -= remaining_len;
+
+                       if (mode == 1) {
+                               desc_ptr->mem_addr =
+                                       dma_map_page(&pdev->dev,
+                                                    vsg->pages[VIA_PFN(cur_mem) -
+                                                               VIA_PFN(first_addr)],
+                                                    VIA_PGOFF(cur_mem), remaining_len,
+                                                    vsg->direction);
+                               desc_ptr->dev_addr = cur_fb;
+
+                               desc_ptr->size = remaining_len;
+                               desc_ptr->next = (uint32_t) next;
+                               next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr),
+                                                     DMA_TO_DEVICE);
+                               desc_ptr++;
+                               if (++num_descriptors_this_page >= vsg->descriptors_per_page) {
+                                       num_descriptors_this_page = 0;
+                                       desc_ptr = vsg->desc_pages[++cur_descriptor_page];
+                               }
+                       }
+
+                       num_desc++;
+                       cur_mem += remaining_len;
+                       cur_fb += remaining_len;
+               }
+
+               mem_addr += xfer->mem_stride;
+               fb_addr += xfer->fb_stride;
+       }
+
+       if (mode == 1) {
+               vsg->chain_start = next;
+               vsg->state = dr_via_device_mapped;
+       }
+       vsg->num_desc = num_desc;
+}
+
+/*
+ * Function that frees up all resources for a blit. It is usable even if the
+ * blit info has only been partially built as long as the status enum is consistent
+ * with the actual status of the used resources.
+ */
+static void
+via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg)
+{
+       int i;
+
+       switch (vsg->state) {
+       case dr_via_device_mapped:
+               via_unmap_blit_from_device(pdev, vsg);
+               fallthrough;
+       case dr_via_desc_pages_alloc:
+               for (i = 0; i < vsg->num_desc_pages; ++i) {
+                       if (vsg->desc_pages[i] != NULL)
+                               free_page((unsigned long)vsg->desc_pages[i]);
+               }
+               kfree(vsg->desc_pages);
+               fallthrough;
+       case dr_via_pages_locked:
+               unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages,
+                                          (vsg->direction == DMA_FROM_DEVICE));
+               fallthrough;
+       case dr_via_pages_alloc:
+               vfree(vsg->pages);
+               fallthrough;
+       default:
+               vsg->state = dr_via_sg_init;
+       }
+       vfree(vsg->bounce_buffer);
+       vsg->bounce_buffer = NULL;
+       vsg->free_on_sequence = 0;
+}
+
+/*
+ * Fire a blit engine.
+ */
+static void
+via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD |
+                 VIA_DMA_CSR_DE);
+       via_write(dev_priv, VIA_PCI_DMA_MR0  + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE);
+       via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0);
+       via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start);
+       wmb();
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS);
+       via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04);
+}
+
+/*
+ * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will
+ * occur here if the calling user does not have access to the submitted address.
+ */
+static int
+via_lock_all_dma_pages(drm_via_sg_info_t *vsg,  drm_via_dmablit_t *xfer)
+{
+       int ret;
+       unsigned long first_pfn = VIA_PFN(xfer->mem_addr);
+       vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) -
+               first_pfn + 1;
+
+       vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages));
+       if (NULL == vsg->pages)
+               return -ENOMEM;
+       ret = pin_user_pages_fast((unsigned long)xfer->mem_addr,
+                       vsg->num_pages,
+                       vsg->direction == DMA_FROM_DEVICE ? FOLL_WRITE : 0,
+                       vsg->pages);
+       if (ret != vsg->num_pages) {
+               if (ret < 0)
+                       return ret;
+               vsg->state = dr_via_pages_locked;
+               return -EINVAL;
+       }
+       vsg->state = dr_via_pages_locked;
+       DRM_DEBUG("DMA pages locked\n");
+       return 0;
+}
+
+/*
+ * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the
+ * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be
+ * quite large for some blits, and pages don't need to be contiguous.
+ */
+static int
+via_alloc_desc_pages(drm_via_sg_info_t *vsg)
+{
+       int i;
+
+       vsg->descriptors_per_page = PAGE_SIZE / sizeof(drm_via_descriptor_t);
+       vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) /
+               vsg->descriptors_per_page;
+
+       if (NULL ==  (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL)))
+               return -ENOMEM;
+
+       vsg->state = dr_via_desc_pages_alloc;
+       for (i = 0; i < vsg->num_desc_pages; ++i) {
+               if (NULL == (vsg->desc_pages[i] =
+                            (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL)))
+                       return -ENOMEM;
+       }
+       DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages,
+                 vsg->num_desc);
+       return 0;
+}
+
+static void
+via_abort_dmablit(struct drm_device *dev, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA);
+}
+
+static void
+via_dmablit_engine_off(struct drm_device *dev, int engine)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+
+       via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD);
+}
+
+/*
+ * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here.
+ * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue
+ * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while
+ * the workqueue task takes care of processing associated with the old blit.
+ */
+static void
+via_dmablit_handler(struct drm_device *dev, int engine, int from_irq)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+       int cur;
+       int done_transfer;
+       unsigned long irqsave = 0;
+       uint32_t status = 0;
+
+       DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n",
+                 engine, from_irq, (unsigned long) blitq);
+
+       if (from_irq)
+               spin_lock(&blitq->blit_lock);
+       else
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       done_transfer = blitq->is_active &&
+         ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD);
+       done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE));
+
+       cur = blitq->cur;
+       if (done_transfer) {
+
+               blitq->blits[cur]->aborted = blitq->aborting;
+               blitq->done_blit_handle++;
+               wake_up(blitq->blit_queue + cur);
+
+               cur++;
+               if (cur >= VIA_NUM_BLIT_SLOTS)
+                       cur = 0;
+               blitq->cur = cur;
+
+               /*
+                * Clear transfer done flag.
+                */
+
+               via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04,  VIA_DMA_CSR_TD);
+
+               blitq->is_active = 0;
+               blitq->aborting = 0;
+               schedule_work(&blitq->wq);
+
+       } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) {
+
+               /*
+                * Abort transfer after one second.
+                */
+
+               via_abort_dmablit(dev, engine);
+               blitq->aborting = 1;
+               blitq->end = jiffies + HZ;
+       }
+
+       if (!blitq->is_active) {
+               if (blitq->num_outstanding) {
+                       via_fire_dmablit(dev, blitq->blits[cur], engine);
+                       blitq->is_active = 1;
+                       blitq->cur = cur;
+                       blitq->num_outstanding--;
+                       blitq->end = jiffies + HZ;
+                       if (!timer_pending(&blitq->poll_timer))
+                               mod_timer(&blitq->poll_timer, jiffies + 1);
+               } else {
+                       if (timer_pending(&blitq->poll_timer))
+                               del_timer(&blitq->poll_timer);
+                       via_dmablit_engine_off(dev, engine);
+               }
+       }
+
+       if (from_irq)
+               spin_unlock(&blitq->blit_lock);
+       else
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+}
+
+/*
+ * Check whether this blit is still active, performing necessary locking.
+ */
+static int
+via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue)
+{
+       unsigned long irqsave;
+       uint32_t slot;
+       int active;
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       /*
+        * Allow for handle wraparounds.
+        */
+
+       active = ((blitq->done_blit_handle - handle) > (1 << 23)) &&
+               ((blitq->cur_blit_handle - handle) <= (1 << 23));
+
+       if (queue && active) {
+               slot = handle - blitq->done_blit_handle + blitq->cur - 1;
+               if (slot >= VIA_NUM_BLIT_SLOTS)
+                       slot -= VIA_NUM_BLIT_SLOTS;
+               *queue = blitq->blit_queue + slot;
+       }
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+       return active;
+}
+
+/*
+ * Sync. Wait for at least three seconds for the blit to be performed.
+ */
+static int
+via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine)
+{
+
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_blitq_t *blitq = dev_priv->blit_queues + engine;
+       wait_queue_head_t *queue;
+       int ret = 0;
+
+       if (via_dmablit_active(blitq, engine, handle, &queue)) {
+               VIA_WAIT_ON(ret, *queue, 3 * HZ,
+                           !via_dmablit_active(blitq, engine, handle, NULL));
+       }
+       DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n",
+                 handle, engine, ret);
+
+       return ret;
+}
+
+/*
+ * A timer that regularly polls the blit engine in cases where we don't have interrupts:
+ * a) Broken hardware (typically those that don't have any video capture facility).
+ * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted.
+ * The timer and hardware IRQ's can and do work in parallel. If the hardware has
+ * irqs, it will shorten the latency somewhat.
+ */
+static void
+via_dmablit_timer(struct timer_list *t)
+{
+       drm_via_blitq_t *blitq = from_timer(blitq, t, poll_timer);
+       struct drm_device *dev = blitq->dev;
+       int engine = (int)
+               (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues);
+
+       DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine,
+                 (unsigned long) jiffies);
+
+       via_dmablit_handler(dev, engine, 0);
+
+       if (!timer_pending(&blitq->poll_timer)) {
+               mod_timer(&blitq->poll_timer, jiffies + 1);
+
+              /*
+               * Rerun handler to delete timer if engines are off, and
+               * to shorten abort latency. This is a little nasty.
+               */
+
+              via_dmablit_handler(dev, engine, 0);
+
+       }
+}
+
+/*
+ * Workqueue task that frees data and mappings associated with a blit.
+ * Also wakes up waiting processes. Each of these tasks handles one
+ * blit engine only and may not be called on each interrupt.
+ */
+static void
+via_dmablit_workqueue(struct work_struct *work)
+{
+       drm_via_blitq_t *blitq = container_of(work, drm_via_blitq_t, wq);
+       struct drm_device *dev = blitq->dev;
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       unsigned long irqsave;
+       drm_via_sg_info_t *cur_sg;
+       int cur_released;
+
+
+       DRM_DEBUG("Workqueue task called for blit engine %ld\n", (unsigned long)
+                 (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues));
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       while (blitq->serviced != blitq->cur) {
+
+               cur_released = blitq->serviced++;
+
+               DRM_DEBUG("Releasing blit slot %d\n", cur_released);
+
+               if (blitq->serviced >= VIA_NUM_BLIT_SLOTS)
+                       blitq->serviced = 0;
+
+               cur_sg = blitq->blits[cur_released];
+               blitq->num_free++;
+
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+               wake_up(&blitq->busy_queue);
+
+               via_free_sg_info(pdev, cur_sg);
+               kfree(cur_sg);
+
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       }
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+}
+
+/*
+ * Init all blit engines. Currently we use two, but some hardware have 4.
+ */
+static void
+via_init_dmablit(struct drm_device *dev)
+{
+       int i, j;
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       drm_via_blitq_t *blitq;
+
+       pci_set_master(pdev);
+
+       for (i = 0; i < VIA_NUM_BLIT_ENGINES; ++i) {
+               blitq = dev_priv->blit_queues + i;
+               blitq->dev = dev;
+               blitq->cur_blit_handle = 0;
+               blitq->done_blit_handle = 0;
+               blitq->head = 0;
+               blitq->cur = 0;
+               blitq->serviced = 0;
+               blitq->num_free = VIA_NUM_BLIT_SLOTS - 1;
+               blitq->num_outstanding = 0;
+               blitq->is_active = 0;
+               blitq->aborting = 0;
+               spin_lock_init(&blitq->blit_lock);
+               for (j = 0; j < VIA_NUM_BLIT_SLOTS; ++j)
+                       init_waitqueue_head(blitq->blit_queue + j);
+               init_waitqueue_head(&blitq->busy_queue);
+               INIT_WORK(&blitq->wq, via_dmablit_workqueue);
+               timer_setup(&blitq->poll_timer, via_dmablit_timer, 0);
+       }
+}
+
+/*
+ * Build all info and do all mappings required for a blit.
+ */
+static int
+via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
+{
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       int draw = xfer->to_fb;
+       int ret = 0;
+
+       vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       vsg->bounce_buffer = NULL;
+
+       vsg->state = dr_via_sg_init;
+
+       if (xfer->num_lines <= 0 || xfer->line_length <= 0) {
+               DRM_ERROR("Zero size bitblt.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Below check is a driver limitation, not a hardware one. We
+        * don't want to lock unused pages, and don't want to incoporate the
+        * extra logic of avoiding them. Make sure there are no.
+        * (Not a big limitation anyway.)
+        */
+
+       if ((xfer->mem_stride - xfer->line_length) > 2*PAGE_SIZE) {
+               DRM_ERROR("Too large system memory stride. Stride: %d, "
+                         "Length: %d\n", xfer->mem_stride, xfer->line_length);
+               return -EINVAL;
+       }
+
+       if ((xfer->mem_stride == xfer->line_length) &&
+          (xfer->fb_stride == xfer->line_length)) {
+               xfer->mem_stride *= xfer->num_lines;
+               xfer->line_length = xfer->mem_stride;
+               xfer->fb_stride = xfer->mem_stride;
+               xfer->num_lines = 1;
+       }
+
+       /*
+        * Don't lock an arbitrary large number of pages, since that causes a
+        * DOS security hole.
+        */
+
+       if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) {
+               DRM_ERROR("Too large PCI DMA bitblt.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * we allow a negative fb stride to allow flipping of images in
+        * transfer.
+        */
+
+       if (xfer->mem_stride < xfer->line_length ||
+               abs(xfer->fb_stride) < xfer->line_length) {
+               DRM_ERROR("Invalid frame-buffer / memory stride.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * A hardware bug seems to be worked around if system memory addresses start on
+        * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted
+        * about this. Meanwhile, impose the following restrictions:
+        */
+
+#ifdef VIA_BUGFREE
+       if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) ||
+           ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) {
+               DRM_ERROR("Invalid DRM bitblt alignment.\n");
+               return -EINVAL;
+       }
+#else
+       if ((((unsigned long)xfer->mem_addr & 15) ||
+             ((unsigned long)xfer->fb_addr & 3)) ||
+          ((xfer->num_lines > 1) &&
+          ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) {
+               DRM_ERROR("Invalid DRM bitblt alignment.\n");
+               return -EINVAL;
+       }
+#endif
+
+       if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) {
+               DRM_ERROR("Could not lock DMA pages.\n");
+               via_free_sg_info(pdev, vsg);
+               return ret;
+       }
+
+       via_map_blit_for_device(pdev, xfer, vsg, 0);
+       if (0 != (ret = via_alloc_desc_pages(vsg))) {
+               DRM_ERROR("Could not allocate DMA descriptor pages.\n");
+               via_free_sg_info(pdev, vsg);
+               return ret;
+       }
+       via_map_blit_for_device(pdev, xfer, vsg, 1);
+
+       return 0;
+}
+
+/*
+ * Reserve one free slot in the blit queue. Will wait for one second for one
+ * to become available. Otherwise -EBUSY is returned.
+ */
+static int
+via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine)
+{
+       int ret = 0;
+       unsigned long irqsave;
+
+       DRM_DEBUG("Num free is %d\n", blitq->num_free);
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       while (blitq->num_free == 0) {
+               spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+               VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0);
+               if (ret)
+                       return (-EINTR == ret) ? -EAGAIN : ret;
+
+               spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       }
+
+       blitq->num_free--;
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+
+       return 0;
+}
+
+/*
+ * Hand back a free slot if we changed our mind.
+ */
+static void
+via_dmablit_release_slot(drm_via_blitq_t *blitq)
+{
+       unsigned long irqsave;
+
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+       blitq->num_free++;
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+       wake_up(&blitq->busy_queue);
+}
+
+/*
+ * Grab a free slot. Build blit info and queue a blit.
+ */
+static int
+via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private;
+       drm_via_sg_info_t *vsg;
+       drm_via_blitq_t *blitq;
+       int ret;
+       int engine;
+       unsigned long irqsave;
+
+       if (dev_priv == NULL) {
+               DRM_ERROR("Called without initialization.\n");
+               return -EINVAL;
+       }
+
+       engine = (xfer->to_fb) ? 0 : 1;
+       blitq = dev_priv->blit_queues + engine;
+       if (0 != (ret = via_dmablit_grab_slot(blitq, engine)))
+               return ret;
+       if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) {
+               via_dmablit_release_slot(blitq);
+               return -ENOMEM;
+       }
+       if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) {
+               via_dmablit_release_slot(blitq);
+               kfree(vsg);
+               return ret;
+       }
+       spin_lock_irqsave(&blitq->blit_lock, irqsave);
+
+       blitq->blits[blitq->head++] = vsg;
+       if (blitq->head >= VIA_NUM_BLIT_SLOTS)
+               blitq->head = 0;
+       blitq->num_outstanding++;
+       xfer->sync.sync_handle = ++blitq->cur_blit_handle;
+
+       spin_unlock_irqrestore(&blitq->blit_lock, irqsave);
+       xfer->sync.engine = engine;
+
+       via_dmablit_handler(dev, engine, 0);
+
+       return 0;
+}
+
+/*
+ * Sync on a previously submitted blit. Note that the X server use signals extensively, and
+ * that there is a very big probability that this IOCTL will be interrupted by a signal. In that
+ * case it returns with -EAGAIN for the signal to be delivered.
+ * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock().
+ */
+static int
+via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_blitsync_t *sync = data;
+       int err;
+
+       if (sync->engine >= VIA_NUM_BLIT_ENGINES)
+               return -EINVAL;
+
+       err = via_dmablit_sync(dev, sync->sync_handle, sync->engine);
+
+       if (-EINTR == err)
+               err = -EAGAIN;
+
+       return err;
+}
+
+/*
+ * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal
+ * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should
+ * be reissued. See the above IOCTL code.
+ */
+static int
+via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_dmablit_t *xfer = data;
+       int err;
+
+       err = via_dmablit(dev, xfer);
+
+       return err;
+}
+
+static u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       if (pipe != 0)
+               return 0;
+
+       return atomic_read(&dev_priv->vbl_received);
+}
+
+static irqreturn_t via_driver_irq_handler(int irq, void *arg)
+{
+       struct drm_device *dev = (struct drm_device *) arg;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+       int handled = 0;
+       ktime_t cur_vblank;
+       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       int i;
+
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       if (status & VIA_IRQ_VBLANK_PENDING) {
+               atomic_inc(&dev_priv->vbl_received);
+               if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
+                       cur_vblank = ktime_get();
+                       if (dev_priv->last_vblank_valid) {
+                               dev_priv->nsec_per_vblank =
+                                       ktime_sub(cur_vblank,
+                                               dev_priv->last_vblank) >> 4;
+                       }
+                       dev_priv->last_vblank = cur_vblank;
+                       dev_priv->last_vblank_valid = 1;
+               }
+               if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
+                       DRM_DEBUG("nsec per vblank is: %llu\n",
+                                 ktime_to_ns(dev_priv->nsec_per_vblank));
+               }
+               drm_handle_vblank(dev, 0);
+               handled = 1;
+       }
+
+       for (i = 0; i < dev_priv->num_irqs; ++i) {
+               if (status & cur_irq->pending_mask) {
+                       atomic_inc(&cur_irq->irq_received);
+                       wake_up(&cur_irq->irq_queue);
+                       handled = 1;
+                       if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
+                               via_dmablit_handler(dev, 0, 1);
+                       else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i)
+                               via_dmablit_handler(dev, 1, 1);
+               }
+               cur_irq++;
+       }
+
+       /* Acknowledge interrupts */
+       via_write(dev_priv, VIA_REG_INTERRUPT, status);
+
+
+       if (handled)
+               return IRQ_HANDLED;
+       else
+               return IRQ_NONE;
+}
+
+static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
+{
+       u32 status;
+
+       if (dev_priv) {
+               /* Acknowledge interrupts */
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status |
+                         dev_priv->irq_pending_mask);
+       }
+}
+
+static int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
+
+       if (pipe != 0) {
+               DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
+               return -EINVAL;
+       }
+
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
+
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
+
+       return 0;
+}
+
+static void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       u32 status;
+
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
+
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
+
+       if (pipe != 0)
+               DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
+}
+
+static int
+via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence,
+                   unsigned int *sequence)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       unsigned int cur_irq_sequence;
+       drm_via_irq_t *cur_irq;
+       int ret = 0;
+       maskarray_t *masks;
+       int real_irq;
+
+       DRM_DEBUG("\n");
+
+       if (!dev_priv) {
+               DRM_ERROR("called with no initialization\n");
+               return -EINVAL;
+       }
+
+       if (irq >= drm_via_irq_num) {
+               DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
+               return -EINVAL;
+       }
+
+       real_irq = dev_priv->irq_map[irq];
+
+       if (real_irq < 0) {
+               DRM_ERROR("Video IRQ %d not available on this hardware.\n",
+                         irq);
+               return -EINVAL;
+       }
+
+       masks = dev_priv->irq_masks;
+       cur_irq = dev_priv->via_irqs + real_irq;
+
+       if (masks[real_irq][2] && !force_sequence) {
+               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
+                           ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) ==
+                            masks[irq][4]));
+               cur_irq_sequence = atomic_read(&cur_irq->irq_received);
+       } else {
+               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
+                           (((cur_irq_sequence =
+                              atomic_read(&cur_irq->irq_received)) -
+                             *sequence) <= (1 << 23)));
+       }
+       *sequence = cur_irq_sequence;
+       return ret;
+}
+
+
+/*
+ * drm_dma.h hooks
+ */
+
+static void via_driver_irq_preinstall(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+       drm_via_irq_t *cur_irq;
+       int i;
+
+       DRM_DEBUG("dev_priv: %p\n", dev_priv);
+       if (dev_priv) {
+               cur_irq = dev_priv->via_irqs;
+
+               dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
+               dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
+
+               if (dev_priv->chipset == VIA_PRO_GROUP_A ||
+                   dev_priv->chipset == VIA_DX9_0) {
+                       dev_priv->irq_masks = via_pro_group_a_irqs;
+                       dev_priv->num_irqs = via_num_pro_group_a;
+                       dev_priv->irq_map = via_irqmap_pro_group_a;
+               } else {
+                       dev_priv->irq_masks = via_unichrome_irqs;
+                       dev_priv->num_irqs = via_num_unichrome;
+                       dev_priv->irq_map = via_irqmap_unichrome;
+               }
+
+               for (i = 0; i < dev_priv->num_irqs; ++i) {
+                       atomic_set(&cur_irq->irq_received, 0);
+                       cur_irq->enable_mask = dev_priv->irq_masks[i][0];
+                       cur_irq->pending_mask = dev_priv->irq_masks[i][1];
+                       init_waitqueue_head(&cur_irq->irq_queue);
+                       dev_priv->irq_enable_mask |= cur_irq->enable_mask;
+                       dev_priv->irq_pending_mask |= cur_irq->pending_mask;
+                       cur_irq++;
+
+                       DRM_DEBUG("Initializing IRQ %d\n", i);
+               }
+
+               dev_priv->last_vblank_valid = 0;
+
+               /* Clear VSync interrupt regs */
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status &
+                         ~(dev_priv->irq_enable_mask));
+
+               /* Clear bits if they're already high */
+               viadrv_acknowledge_irqs(dev_priv);
+       }
+}
+
+static int via_driver_irq_postinstall(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("fun: %s\n", __func__);
+       if (!dev_priv)
+               return -EINVAL;
+
+       status = via_read(dev_priv, VIA_REG_INTERRUPT);
+       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
+                 | dev_priv->irq_enable_mask);
+
+       /* Some magic, oh for some data sheets ! */
+       via_write8(dev_priv, 0x83d4, 0x11);
+       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
+
+       return 0;
+}
+
+static void via_driver_irq_uninstall(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       u32 status;
+
+       DRM_DEBUG("\n");
+       if (dev_priv) {
+
+               /* Some more magic, oh for some data sheets ! */
+
+               via_write8(dev_priv, 0x83d4, 0x11);
+               via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
+
+               status = via_read(dev_priv, VIA_REG_INTERRUPT);
+               via_write(dev_priv, VIA_REG_INTERRUPT, status &
+                         ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
+       }
+}
+
+static int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_irqwait_t *irqwait = data;
+       struct timespec64 now;
+       int ret = 0;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       int force_sequence;
+
+       if (irqwait->request.irq >= dev_priv->num_irqs) {
+               DRM_ERROR("Trying to wait on unknown irq %d\n",
+                         irqwait->request.irq);
+               return -EINVAL;
+       }
+
+       cur_irq += irqwait->request.irq;
+
+       switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
+       case VIA_IRQ_RELATIVE:
+               irqwait->request.sequence +=
+                       atomic_read(&cur_irq->irq_received);
+               irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
+               break;
+       case VIA_IRQ_ABSOLUTE:
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (irqwait->request.type & VIA_IRQ_SIGNAL) {
+               DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
+               return -EINVAL;
+       }
+
+       force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
+
+       ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
+                                 &irqwait->request.sequence);
+       ktime_get_ts64(&now);
+       irqwait->reply.tval_sec = now.tv_sec;
+       irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
+
+       return ret;
+}
+
+static void via_init_futex(drm_via_private_t *dev_priv)
+{
+       unsigned int i;
+
+       DRM_DEBUG("\n");
+
+       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+               init_waitqueue_head(&(dev_priv->decoder_queue[i]));
+               XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
+       }
+}
+
+static void via_cleanup_futex(drm_via_private_t *dev_priv)
+{
+}
+
+static void via_release_futex(drm_via_private_t *dev_priv, int context)
+{
+       unsigned int i;
+       volatile int *lock;
+
+       if (!dev_priv->sarea_priv)
+               return;
+
+       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
+               lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
+               if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
+                       if (_DRM_LOCK_IS_HELD(*lock)
+                           && (*lock & _DRM_LOCK_CONT)) {
+                               wake_up(&(dev_priv->decoder_queue[i]));
+                       }
+                       *lock = 0;
+               }
+       }
+}
+
+static int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_futex_t *fx = data;
+       volatile int *lock;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
+       int ret = 0;
+
+       DRM_DEBUG("\n");
+
+       if (fx->lock >= VIA_NR_XVMC_LOCKS)
+               return -EFAULT;
+
+       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
+
+       switch (fx->func) {
+       case VIA_FUTEX_WAIT:
+               VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
+                           (fx->ms / 10) * (HZ / 100), *lock != fx->val);
+               return ret;
+       case VIA_FUTEX_WAKE:
+               wake_up(&(dev_priv->decoder_queue[fx->lock]));
+               return 0;
+       }
+       return 0;
+}
+
+static int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_agp_t *agp = data;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT);
+
+       dev_priv->agp_initialized = 1;
+       dev_priv->agp_offset = agp->offset;
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
+       return 0;
+}
+
+static int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_fb_t *fb = data;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       mutex_lock(&dev->struct_mutex);
+       drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT);
+
+       dev_priv->vram_initialized = 1;
+       dev_priv->vram_offset = fb->offset;
+
+       mutex_unlock(&dev->struct_mutex);
+       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
+
+       return 0;
+
+}
+
+static int via_final_context(struct drm_device *dev, int context)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       via_release_futex(dev_priv, context);
+
+       /* Linux specific until context tracking code gets ported to BSD */
+       /* Last context, perform cleanup */
+       if (list_is_singular(&dev->ctxlist)) {
+               DRM_DEBUG("Last Context\n");
+               drm_legacy_irq_uninstall(dev);
+               via_cleanup_futex(dev_priv);
+               via_do_cleanup_map(dev);
+       }
+       return 1;
+}
+
+static void via_lastclose(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (!dev_priv)
+               return;
+
+       mutex_lock(&dev->struct_mutex);
+       if (dev_priv->vram_initialized) {
+               drm_mm_takedown(&dev_priv->vram_mm);
+               dev_priv->vram_initialized = 0;
+       }
+       if (dev_priv->agp_initialized) {
+               drm_mm_takedown(&dev_priv->agp_mm);
+               dev_priv->agp_initialized = 0;
+       }
+       mutex_unlock(&dev->struct_mutex);
+}
+
+static int via_mem_alloc(struct drm_device *dev, void *data,
+                 struct drm_file *file)
+{
+       drm_via_mem_t *mem = data;
+       int retval = 0, user_key;
+       struct via_memblock *item;
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       struct via_file_private *file_priv = file->driver_priv;
+       unsigned long tmpSize;
+
+       if (mem->type > VIA_MEM_AGP) {
+               DRM_ERROR("Unknown memory type allocation\n");
+               return -EINVAL;
+       }
+       mutex_lock(&dev->struct_mutex);
+       if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
+                     dev_priv->agp_initialized)) {
+               mutex_unlock(&dev->struct_mutex);
+               DRM_ERROR
+                   ("Attempt to allocate from uninitialized memory manager.\n");
+               return -EINVAL;
+       }
+
+       item = kzalloc(sizeof(*item), GFP_KERNEL);
+       if (!item) {
+               retval = -ENOMEM;
+               goto fail_alloc;
+       }
+
+       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
+       if (mem->type == VIA_MEM_AGP)
+               retval = drm_mm_insert_node(&dev_priv->agp_mm,
+                                           &item->mm_node,
+                                           tmpSize);
+       else
+               retval = drm_mm_insert_node(&dev_priv->vram_mm,
+                                           &item->mm_node,
+                                           tmpSize);
+       if (retval)
+               goto fail_alloc;
+
+       retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
+       if (retval < 0)
+               goto fail_idr;
+       user_key = retval;
+
+       list_add(&item->owner_list, &file_priv->obj_list);
+       mutex_unlock(&dev->struct_mutex);
+
+       mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
+                     dev_priv->vram_offset : dev_priv->agp_offset) +
+           ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT);
+       mem->index = user_key;
+
+       return 0;
+
+fail_idr:
+       drm_mm_remove_node(&item->mm_node);
+fail_alloc:
+       kfree(item);
+       mutex_unlock(&dev->struct_mutex);
+
+       mem->offset = 0;
+       mem->size = 0;
+       mem->index = 0;
+       DRM_DEBUG("Video memory allocation failed\n");
+
+       return retval;
+}
+
+static int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       drm_via_mem_t *mem = data;
+       struct via_memblock *obj;
+
+       mutex_lock(&dev->struct_mutex);
+       obj = idr_find(&dev_priv->object_idr, mem->index);
+       if (obj == NULL) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EINVAL;
+       }
+
+       idr_remove(&dev_priv->object_idr, mem->index);
+       list_del(&obj->owner_list);
+       drm_mm_remove_node(&obj->mm_node);
+       kfree(obj);
+       mutex_unlock(&dev->struct_mutex);
+
+       DRM_DEBUG("free = 0x%lx\n", mem->index);
+
+       return 0;
+}
+
+
+static void via_reclaim_buffers_locked(struct drm_device *dev,
+                               struct drm_file *file)
+{
+       struct via_file_private *file_priv = file->driver_priv;
+       struct via_memblock *entry, *next;
+
+       if (!(dev->master && file->master->lock.hw_lock))
+               return;
+
+       drm_legacy_idlelock_take(&file->master->lock);
+
+       mutex_lock(&dev->struct_mutex);
+       if (list_empty(&file_priv->obj_list)) {
+               mutex_unlock(&dev->struct_mutex);
+               drm_legacy_idlelock_release(&file->master->lock);
+
+               return;
+       }
+
+       via_driver_dma_quiescent(dev);
+
+       list_for_each_entry_safe(entry, next, &file_priv->obj_list,
+                                owner_list) {
+               list_del(&entry->owner_list);
+               drm_mm_remove_node(&entry->mm_node);
+               kfree(entry);
+       }
+       mutex_unlock(&dev->struct_mutex);
+
+       drm_legacy_idlelock_release(&file->master->lock);
+
+       return;
+}
+
+static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       DRM_DEBUG("\n");
+
+       dev_priv->sarea = drm_legacy_getsarea(dev);
+       if (!dev_priv->sarea) {
+               DRM_ERROR("could not find sarea!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset);
+       if (!dev_priv->fb) {
+               DRM_ERROR("could not find framebuffer!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+       dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset);
+       if (!dev_priv->mmio) {
+               DRM_ERROR("could not find mmio region!\n");
+               dev->dev_private = (void *)dev_priv;
+               via_do_cleanup_map(dev);
+               return -EINVAL;
+       }
+
+       dev_priv->sarea_priv =
+           (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
+                                init->sarea_priv_offset);
+
+       dev_priv->agpAddr = init->agpAddr;
+
+       via_init_futex(dev_priv);
+
+       via_init_dmablit(dev);
+
+       dev->dev_private = (void *)dev_priv;
+       return 0;
+}
+
+int via_do_cleanup_map(struct drm_device *dev)
+{
+       via_dma_cleanup(dev);
+
+       return 0;
+}
+
+static int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_init_t *init = data;
+
+       DRM_DEBUG("\n");
+
+       switch (init->func) {
+       case VIA_INIT_MAP:
+               return via_do_init_map(dev, init);
+       case VIA_CLEANUP_MAP:
+               return via_do_cleanup_map(dev);
+       }
+
+       return -EINVAL;
+}
+
+static int via_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       drm_via_private_t *dev_priv;
+       int ret = 0;
+
+       dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL);
+       if (dev_priv == NULL)
+               return -ENOMEM;
+
+       idr_init_base(&dev_priv->object_idr, 1);
+       dev->dev_private = (void *)dev_priv;
+
+       dev_priv->chipset = chipset;
+
+       pci_set_master(pdev);
+
+       ret = drm_vblank_init(dev, 1);
+       if (ret) {
+               kfree(dev_priv);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void via_driver_unload(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       idr_destroy(&dev_priv->object_idr);
+
+       kfree(dev_priv);
+}
+
+static void via_cmdbuf_start(drm_via_private_t *dev_priv);
+static void via_cmdbuf_pause(drm_via_private_t *dev_priv);
+static void via_cmdbuf_reset(drm_via_private_t *dev_priv);
+static void via_cmdbuf_rewind(drm_via_private_t *dev_priv);
+static int via_wait_idle(drm_via_private_t *dev_priv);
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
+
+/*
+ * Free space in command buffer.
+ */
+
+static uint32_t via_cmdbuf_space(drm_via_private_t *dev_priv)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+       return ((hw_addr <= dev_priv->dma_low) ?
+               (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
+               (hw_addr - dev_priv->dma_low));
+}
+
+/*
+ * How much does the command regulator lag behind?
+ */
+
+static uint32_t via_cmdbuf_lag(drm_via_private_t *dev_priv)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
+
+       return ((hw_addr <= dev_priv->dma_low) ?
+               (dev_priv->dma_low - hw_addr) :
+               (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
+}
+
+/*
+ * Check that the given size fits in the buffer, otherwise wait.
+ */
+
+static inline int
+via_cmdbuf_wait(drm_via_private_t *dev_priv, unsigned int size)
+{
+       uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       uint32_t cur_addr, hw_addr, next_addr;
+       volatile uint32_t *hw_addr_ptr;
+       uint32_t count;
+       hw_addr_ptr = dev_priv->hw_addr_ptr;
+       cur_addr = dev_priv->dma_low;
+       next_addr = cur_addr + size + 512 * 1024;
+       count = 1000000;
+       do {
+               hw_addr = *hw_addr_ptr - agp_base;
+               if (count-- == 0) {
+                       DRM_ERROR
+                           ("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
+                            hw_addr, cur_addr, next_addr);
+                       return -1;
+               }
+               if  ((cur_addr < hw_addr) && (next_addr >= hw_addr))
+                       msleep(1);
+       } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
+       return 0;
+}
+
+/*
+ * Checks whether buffer head has reach the end. Rewind the ring buffer
+ * when necessary.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+
+static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
+                                     unsigned int size)
+{
+       if ((dev_priv->dma_low + size + 4 * CMDBUF_ALIGNMENT_SIZE) >
+           dev_priv->dma_high) {
+               via_cmdbuf_rewind(dev_priv);
+       }
+       if (via_cmdbuf_wait(dev_priv, size) != 0)
+               return NULL;
+
+       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+int via_dma_cleanup(struct drm_device *dev)
+{
+       if (dev->dev_private) {
+               drm_via_private_t *dev_priv =
+                   (drm_via_private_t *) dev->dev_private;
+
+               if (dev_priv->ring.virtual_start) {
+                       via_cmdbuf_reset(dev_priv);
+
+                       drm_legacy_ioremapfree(&dev_priv->ring.map, dev);
+                       dev_priv->ring.virtual_start = NULL;
+               }
+
+       }
+
+       return 0;
+}
+
+static int via_initialize(struct drm_device *dev,
+                         drm_via_private_t *dev_priv,
+                         drm_via_dma_init_t *init)
+{
+       if (!dev_priv || !dev_priv->mmio) {
+               DRM_ERROR("via_dma_init called before via_map_init\n");
+               return -EFAULT;
+       }
+
+       if (dev_priv->ring.virtual_start != NULL) {
+               DRM_ERROR("called again without calling cleanup\n");
+               return -EFAULT;
+       }
+
+       if (!dev->agp || !dev->agp->base) {
+               DRM_ERROR("called with no agp memory available\n");
+               return -EFAULT;
+       }
+
+       if (dev_priv->chipset == VIA_DX9_0) {
+               DRM_ERROR("AGP DMA is not supported on this chip\n");
+               return -EINVAL;
+       }
+
+       dev_priv->ring.map.offset = dev->agp->base + init->offset;
+       dev_priv->ring.map.size = init->size;
+       dev_priv->ring.map.type = 0;
+       dev_priv->ring.map.flags = 0;
+       dev_priv->ring.map.mtrr = 0;
+
+       drm_legacy_ioremap(&dev_priv->ring.map, dev);
+
+       if (dev_priv->ring.map.handle == NULL) {
+               via_dma_cleanup(dev);
+               DRM_ERROR("can not ioremap virtual address for"
+                         " ring buffer\n");
+               return -ENOMEM;
+       }
+
+       dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
+
+       dev_priv->dma_ptr = dev_priv->ring.virtual_start;
+       dev_priv->dma_low = 0;
+       dev_priv->dma_high = init->size;
+       dev_priv->dma_wrap = init->size;
+       dev_priv->dma_offset = init->offset;
+       dev_priv->last_pause_ptr = NULL;
+       dev_priv->hw_addr_ptr =
+               (volatile uint32_t *)((char *)dev_priv->mmio->handle +
+               init->reg_pause_addr);
+
+       via_cmdbuf_start(dev_priv);
+
+       return 0;
+}
+
+static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
+       drm_via_dma_init_t *init = data;
+       int retcode = 0;
+
+       switch (init->func) {
+       case VIA_INIT_DMA:
+               if (!capable(CAP_SYS_ADMIN))
+                       retcode = -EPERM;
+               else
+                       retcode = via_initialize(dev, dev_priv, init);
+               break;
+       case VIA_CLEANUP_DMA:
+               if (!capable(CAP_SYS_ADMIN))
+                       retcode = -EPERM;
+               else
+                       retcode = via_dma_cleanup(dev);
+               break;
+       case VIA_DMA_INITIALIZED:
+               retcode = (dev_priv->ring.virtual_start != NULL) ?
+                       0 : -EFAULT;
+               break;
+       default:
+               retcode = -EINVAL;
+               break;
+       }
+
+       return retcode;
+}
+
+static int via_dispatch_cmdbuffer(struct drm_device *dev, drm_via_cmdbuffer_t *cmd)
+{
+       drm_via_private_t *dev_priv;
+       uint32_t *vb;
+       int ret;
+
+       dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               DRM_ERROR("called without initializing AGP ring buffer.\n");
+               return -EFAULT;
+       }
+
+       if (cmd->size > VIA_PCI_BUF_SIZE)
+               return -ENOMEM;
+
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return -EFAULT;
+
+       /*
+        * Running this function on AGP memory is dead slow. Therefore
+        * we run it on a temporary cacheable system memory buffer and
+        * copy it to AGP memory when ready.
+        */
+
+       if ((ret =
+            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+                                      cmd->size, dev, 1))) {
+               return ret;
+       }
+
+       vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
+       if (vb == NULL)
+               return -EAGAIN;
+
+       memcpy(vb, dev_priv->pci_buf, cmd->size);
+
+       dev_priv->dma_low += cmd->size;
+
+       /*
+        * Small submissions somehow stalls the CPU. (AGP cache effects?)
+        * pad to greater size.
+        */
+
+       if (cmd->size < 0x100)
+               via_pad_cache(dev_priv, (0x100 - cmd->size) >> 3);
+       via_cmdbuf_pause(dev_priv);
+
+       return 0;
+}
+
+int via_driver_dma_quiescent(struct drm_device *dev)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+
+       if (!via_wait_idle(dev_priv))
+               return -EBUSY;
+       return 0;
+}
+
+static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       return via_driver_dma_quiescent(dev);
+}
+
+static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuffer_t *cmdbuf = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
+
+       ret = via_dispatch_cmdbuffer(dev, cmdbuf);
+       return ret;
+}
+
+static int via_dispatch_pci_cmdbuffer(struct drm_device *dev,
+                                     drm_via_cmdbuffer_t *cmd)
+{
+       drm_via_private_t *dev_priv = dev->dev_private;
+       int ret;
+
+       if (cmd->size > VIA_PCI_BUF_SIZE)
+               return -ENOMEM;
+       if (copy_from_user(dev_priv->pci_buf, cmd->buf, cmd->size))
+               return -EFAULT;
+
+       if ((ret =
+            via_verify_command_stream((uint32_t *) dev_priv->pci_buf,
+                                      cmd->size, dev, 0))) {
+               return ret;
+       }
+
+       ret =
+           via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf,
+                                    cmd->size);
+       return ret;
+}
+
+static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuffer_t *cmdbuf = data;
+       int ret;
+
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       DRM_DEBUG("buf %p size %lu\n", cmdbuf->buf, cmdbuf->size);
+
+       ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf);
+       return ret;
+}
+
+static inline uint32_t *via_align_buffer(drm_via_private_t *dev_priv,
+                                        uint32_t * vb, int qw_count)
+{
+       for (; qw_count > 0; --qw_count)
+               VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
+       return vb;
+}
+
+/*
+ * This function is used internally by ring buffer management code.
+ *
+ * Returns virtual pointer to ring buffer.
+ */
+static inline uint32_t *via_get_dma(drm_via_private_t *dev_priv)
+{
+       return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
+}
+
+/*
+ * Hooks a segment of data into the tail of the ring-buffer by
+ * modifying the pause address stored in the buffer itself. If
+ * the regulator has already paused, restart it.
+ */
+static int via_hook_segment(drm_via_private_t *dev_priv,
+                           uint32_t pause_addr_hi, uint32_t pause_addr_lo,
+                           int no_pci_fire)
+{
+       int paused, count;
+       volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
+       uint32_t reader, ptr;
+       uint32_t diff;
+
+       paused = 0;
+       via_flush_write_combine();
+       (void) *(volatile uint32_t *)(via_get_dma(dev_priv) - 1);
+
+       *paused_at = pause_addr_lo;
+       via_flush_write_combine();
+       (void) *paused_at;
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) +
+               dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
+
+       /*
+        * If there is a possibility that the command reader will
+        * miss the new pause address and pause on the old one,
+        * In that case we need to program the new start address
+        * using PCI.
+        */
+
+       diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+       count = 10000000;
+       while (diff == 0 && count--) {
+               paused = (via_read(dev_priv, 0x41c) & 0x80000000);
+               if (paused)
+                       break;
+               reader = *(dev_priv->hw_addr_ptr);
+               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+       }
+
+       paused = via_read(dev_priv, 0x41c) & 0x80000000;
+
+       if (paused && !no_pci_fire) {
+               reader = *(dev_priv->hw_addr_ptr);
+               diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff;
+               diff &= (dev_priv->dma_high - 1);
+               if (diff != 0 && diff < (dev_priv->dma_high >> 1)) {
+                       DRM_ERROR("Paused at incorrect address. "
+                                 "0x%08x, 0x%08x 0x%08x\n",
+                                 ptr, reader, dev_priv->dma_diff);
+               } else if (diff == 0) {
+                       /*
+                        * There is a concern that these writes may stall the PCI bus
+                        * if the GPU is not idle. However, idling the GPU first
+                        * doesn't make a difference.
+                        */
+
+                       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
+                       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
+                       via_read(dev_priv, VIA_REG_TRANSPACE);
+               }
+       }
+       return paused;
+}
+
+static int via_wait_idle(drm_via_private_t *dev_priv)
+{
+       int count = 10000000;
+
+       while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count)
+               ;
+
+       while (count && (via_read(dev_priv, VIA_REG_STATUS) &
+                          (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
+                           VIA_3D_ENG_BUSY)))
+               --count;
+       return count;
+}
+
+static uint32_t *via_align_cmd(drm_via_private_t *dev_priv, uint32_t cmd_type,
+                              uint32_t addr, uint32_t *cmd_addr_hi,
+                              uint32_t *cmd_addr_lo, int skip_wait)
+{
+       uint32_t agp_base;
+       uint32_t cmd_addr, addr_lo, addr_hi;
+       uint32_t *vb;
+       uint32_t qw_pad_count;
+
+       if (!skip_wait)
+               via_cmdbuf_wait(dev_priv, 2 * CMDBUF_ALIGNMENT_SIZE);
+
+       vb = via_get_dma(dev_priv);
+       VIA_OUT_RING_QW(HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
+                       (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
+       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
+           ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
+
+       cmd_addr = (addr) ? addr :
+           agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
+       addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
+                  (cmd_addr & HC_HAGPBpL_MASK));
+       addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
+
+       vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
+       VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi, *cmd_addr_lo = addr_lo);
+       return vb;
+}
+
+static void via_cmdbuf_start(drm_via_private_t *dev_priv)
+{
+       uint32_t pause_addr_lo, pause_addr_hi;
+       uint32_t start_addr, start_addr_lo;
+       uint32_t end_addr, end_addr_lo;
+       uint32_t command;
+       uint32_t agp_base;
+       uint32_t ptr;
+       uint32_t reader;
+       int count;
+
+       dev_priv->dma_low = 0;
+
+       agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
+       start_addr = agp_base;
+       end_addr = agp_base + dev_priv->dma_high;
+
+       start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
+       end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
+       command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
+                  ((end_addr & 0xff000000) >> 16));
+
+       dev_priv->last_pause_ptr =
+           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
+                         &pause_addr_hi, &pause_addr_lo, 1) - 1;
+
+       via_flush_write_combine();
+       (void) *(volatile uint32_t *)dev_priv->last_pause_ptr;
+
+       via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
+       via_write(dev_priv, VIA_REG_TRANSPACE, command);
+       via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo);
+       via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo);
+
+       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi);
+       via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo);
+       wmb();
+       via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
+       via_read(dev_priv, VIA_REG_TRANSPACE);
+
+       dev_priv->dma_diff = 0;
+
+       count = 10000000;
+       while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--);
+
+       reader = *(dev_priv->hw_addr_ptr);
+       ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
+           dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
+
+       /*
+        * This is the difference between where we tell the
+        * command reader to pause and where it actually pauses.
+        * This differs between hw implementation so we need to
+        * detect it.
+        */
+
+       dev_priv->dma_diff = ptr - reader;
+}
+
+static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
+{
+       uint32_t *vb;
+
+       via_cmdbuf_wait(dev_priv, qwords + 2);
+       vb = via_get_dma(dev_priv);
+       VIA_OUT_RING_QW(HC_HEADER2, HC_ParaType_NotTex << 16);
+       via_align_buffer(dev_priv, vb, qwords);
+}
+
+static inline void via_dummy_bitblt(drm_via_private_t *dev_priv)
+{
+       uint32_t *vb = via_get_dma(dev_priv);
+       SetReg2DAGP(0x0C, (0 | (0 << 16)));
+       SetReg2DAGP(0x10, 0 | (0 << 16));
+       SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
+}
+
+static void via_cmdbuf_jump(drm_via_private_t *dev_priv)
+{
+       uint32_t pause_addr_lo, pause_addr_hi;
+       uint32_t jump_addr_lo, jump_addr_hi;
+       volatile uint32_t *last_pause_ptr;
+       uint32_t dma_low_save1, dma_low_save2;
+
+       via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
+                     &jump_addr_lo, 0);
+
+       dev_priv->dma_wrap = dev_priv->dma_low;
+
+       /*
+        * Wrap command buffer to the beginning.
+        */
+
+       dev_priv->dma_low = 0;
+       if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0)
+               DRM_ERROR("via_cmdbuf_jump failed\n");
+
+       via_dummy_bitblt(dev_priv);
+       via_dummy_bitblt(dev_priv);
+
+       last_pause_ptr =
+           via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                         &pause_addr_lo, 0) - 1;
+       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                     &pause_addr_lo, 0);
+
+       *last_pause_ptr = pause_addr_lo;
+       dma_low_save1 = dev_priv->dma_low;
+
+       /*
+        * Now, set a trap that will pause the regulator if it tries to rerun the old
+        * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
+        * and reissues the jump command over PCI, while the regulator has already taken the jump
+        * and actually paused at the current buffer end).
+        * There appears to be no other way to detect this condition, since the hw_addr_pointer
+        * does not seem to get updated immediately when a jump occurs.
+        */
+
+       last_pause_ptr =
+               via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                             &pause_addr_lo, 0) - 1;
+       via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
+                     &pause_addr_lo, 0);
+       *last_pause_ptr = pause_addr_lo;
+
+       dma_low_save2 = dev_priv->dma_low;
+       dev_priv->dma_low = dma_low_save1;
+       via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0);
+       dev_priv->dma_low = dma_low_save2;
+       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+
+static void via_cmdbuf_rewind(drm_via_private_t *dev_priv)
+{
+       via_cmdbuf_jump(dev_priv);
+}
+
+static void via_cmdbuf_flush(drm_via_private_t *dev_priv, uint32_t cmd_type)
+{
+       uint32_t pause_addr_lo, pause_addr_hi;
+
+       via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
+       via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0);
+}
+
+static void via_cmdbuf_pause(drm_via_private_t *dev_priv)
+{
+       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
+}
+
+static void via_cmdbuf_reset(drm_via_private_t *dev_priv)
+{
+       via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
+       via_wait_idle(dev_priv);
+}
+
+/*
+ * User interface to the space and lag functions.
+ */
+
+static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+       drm_via_cmdbuf_size_t *d_siz = data;
+       int ret = 0;
+       uint32_t tmp_size, count;
+       drm_via_private_t *dev_priv;
+
+       DRM_DEBUG("\n");
+       LOCK_TEST_WITH_RETURN(dev, file_priv);
+
+       dev_priv = (drm_via_private_t *) dev->dev_private;
+
+       if (dev_priv->ring.virtual_start == NULL) {
+               DRM_ERROR("called without initializing AGP ring buffer.\n");
+               return -EFAULT;
+       }
+
+       count = 1000000;
+       tmp_size = d_siz->size;
+       switch (d_siz->func) {
+       case VIA_CMDBUF_SPACE:
+               while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size)
+                      && --count) {
+                       if (!d_siz->wait)
+                               break;
+               }
+               if (!count) {
+                       DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
+                       ret = -EAGAIN;
+               }
+               break;
+       case VIA_CMDBUF_LAG:
+               while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size)
+                      && --count) {
+                       if (!d_siz->wait)
+                               break;
+               }
+               if (!count) {
+                       DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
+                       ret = -EAGAIN;
+               }
+               break;
+       default:
+               ret = -EFAULT;
+       }
+       d_siz->size = tmp_size;
+
+       return ret;
+}
+
+static const struct drm_ioctl_desc via_ioctls[] = {
+       DRM_IOCTL_DEF_DRV(VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_FREEMEM, via_mem_free, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER),
+       DRM_IOCTL_DEF_DRV(VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_DMA_INIT, via_dma_init, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_FLUSH, via_flush_ioctl, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_DMA_BLIT, via_dma_blit, DRM_AUTH),
+       DRM_IOCTL_DEF_DRV(VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH)
+};
+
+static int via_max_ioctl = ARRAY_SIZE(via_ioctls);
+static int via_driver_open(struct drm_device *dev, struct drm_file *file)
+{
+       struct via_file_private *file_priv;
+
+       DRM_DEBUG_DRIVER("\n");
+       file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
+       if (!file_priv)
+               return -ENOMEM;
+
+       file->driver_priv = file_priv;
+
+       INIT_LIST_HEAD(&file_priv->obj_list);
+
+       return 0;
+}
+
+static void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
+{
+       struct via_file_private *file_priv = file->driver_priv;
+
+       kfree(file_priv);
+}
+
+static struct pci_device_id pciidlist[] = {
+       viadrv_PCI_IDS
+};
+
+static const struct file_operations via_driver_fops = {
+       .owner = THIS_MODULE,
+       .open = drm_open,
+       .release = drm_release,
+       .unlocked_ioctl = drm_ioctl,
+       .mmap = drm_legacy_mmap,
+       .poll = drm_poll,
+       .compat_ioctl = drm_compat_ioctl,
+       .llseek = noop_llseek,
+};
+
+static struct drm_driver driver = {
+       .driver_features =
+           DRIVER_USE_AGP | DRIVER_HAVE_IRQ | DRIVER_LEGACY,
+       .load = via_driver_load,
+       .unload = via_driver_unload,
+       .open = via_driver_open,
+       .preclose = via_reclaim_buffers_locked,
+       .postclose = via_driver_postclose,
+       .context_dtor = via_final_context,
+       .get_vblank_counter = via_get_vblank_counter,
+       .enable_vblank = via_enable_vblank,
+       .disable_vblank = via_disable_vblank,
+       .irq_preinstall = via_driver_irq_preinstall,
+       .irq_postinstall = via_driver_irq_postinstall,
+       .irq_uninstall = via_driver_irq_uninstall,
+       .irq_handler = via_driver_irq_handler,
+       .dma_quiescent = via_driver_dma_quiescent,
+       .lastclose = via_lastclose,
+       .ioctls = via_ioctls,
+       .fops = &via_driver_fops,
+       .name = DRIVER_NAME,
+       .desc = DRIVER_DESC,
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
+       .patchlevel = DRIVER_PATCHLEVEL,
+};
+
+static struct pci_driver via_pci_driver = {
+       .name = DRIVER_NAME,
+       .id_table = pciidlist,
+};
+
+static int __init via_init(void)
+{
+       driver.num_ioctls = via_max_ioctl;
+       via_init_command_verifier();
+       return drm_legacy_pci_init(&driver, &via_pci_driver);
+}
+
+static void __exit via_exit(void)
+{
+       drm_legacy_pci_exit(&driver, &via_pci_driver);
+}
+
+module_init(via_init);
+module_exit(via_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
deleted file mode 100644 (file)
index 5da3808..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include <drm/drm_drv.h>
-#include <drm/drm_file.h>
-#include <drm/drm_pciids.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-
-
-static int via_driver_open(struct drm_device *dev, struct drm_file *file)
-{
-       struct via_file_private *file_priv;
-
-       DRM_DEBUG_DRIVER("\n");
-       file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
-       if (!file_priv)
-               return -ENOMEM;
-
-       file->driver_priv = file_priv;
-
-       INIT_LIST_HEAD(&file_priv->obj_list);
-
-       return 0;
-}
-
-static void via_driver_postclose(struct drm_device *dev, struct drm_file *file)
-{
-       struct via_file_private *file_priv = file->driver_priv;
-
-       kfree(file_priv);
-}
-
-static struct pci_device_id pciidlist[] = {
-       viadrv_PCI_IDS
-};
-
-static const struct file_operations via_driver_fops = {
-       .owner = THIS_MODULE,
-       .open = drm_open,
-       .release = drm_release,
-       .unlocked_ioctl = drm_ioctl,
-       .mmap = drm_legacy_mmap,
-       .poll = drm_poll,
-       .compat_ioctl = drm_compat_ioctl,
-       .llseek = noop_llseek,
-};
-
-static struct drm_driver driver = {
-       .driver_features =
-           DRIVER_USE_AGP | DRIVER_HAVE_IRQ | DRIVER_LEGACY,
-       .load = via_driver_load,
-       .unload = via_driver_unload,
-       .open = via_driver_open,
-       .preclose = via_reclaim_buffers_locked,
-       .postclose = via_driver_postclose,
-       .context_dtor = via_final_context,
-       .get_vblank_counter = via_get_vblank_counter,
-       .enable_vblank = via_enable_vblank,
-       .disable_vblank = via_disable_vblank,
-       .irq_preinstall = via_driver_irq_preinstall,
-       .irq_postinstall = via_driver_irq_postinstall,
-       .irq_uninstall = via_driver_irq_uninstall,
-       .irq_handler = via_driver_irq_handler,
-       .dma_quiescent = via_driver_dma_quiescent,
-       .lastclose = via_lastclose,
-       .ioctls = via_ioctls,
-       .fops = &via_driver_fops,
-       .name = DRIVER_NAME,
-       .desc = DRIVER_DESC,
-       .date = DRIVER_DATE,
-       .major = DRIVER_MAJOR,
-       .minor = DRIVER_MINOR,
-       .patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static struct pci_driver via_pci_driver = {
-       .name = DRIVER_NAME,
-       .id_table = pciidlist,
-};
-
-static int __init via_init(void)
-{
-       driver.num_ioctls = via_max_ioctl;
-       via_init_command_verifier();
-       return drm_legacy_pci_init(&driver, &via_pci_driver);
-}
-
-static void __exit via_exit(void)
-{
-       drm_legacy_pci_exit(&driver, &via_pci_driver);
-}
-
-module_init(via_init);
-module_exit(via_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
deleted file mode 100644 (file)
index d5ad1b0..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-#ifndef _VIA_DRV_H_
-#define _VIA_DRV_H_
-
-#include <linux/irqreturn.h>
-#include <linux/jiffies.h>
-#include <linux/sched.h>
-#include <linux/sched/signal.h>
-#include <linux/wait.h>
-
-#include <drm/drm_ioctl.h>
-#include <drm/drm_legacy.h>
-#include <drm/drm_mm.h>
-#include <drm/via_drm.h>
-
-#define DRIVER_AUTHOR  "Various"
-
-#define DRIVER_NAME            "via"
-#define DRIVER_DESC            "VIA Unichrome / Pro"
-#define DRIVER_DATE            "20070202"
-
-#define DRIVER_MAJOR           2
-#define DRIVER_MINOR           11
-#define DRIVER_PATCHLEVEL      1
-
-#include "via_verifier.h"
-
-#include "via_dmablit.h"
-
-#define VIA_PCI_BUF_SIZE 60000
-#define VIA_FIRE_BUF_SIZE  1024
-#define VIA_NUM_IRQS 4
-
-typedef struct drm_via_ring_buffer {
-       drm_local_map_t map;
-       char *virtual_start;
-} drm_via_ring_buffer_t;
-
-typedef uint32_t maskarray_t[5];
-
-typedef struct drm_via_irq {
-       atomic_t irq_received;
-       uint32_t pending_mask;
-       uint32_t enable_mask;
-       wait_queue_head_t irq_queue;
-} drm_via_irq_t;
-
-typedef struct drm_via_private {
-       drm_via_sarea_t *sarea_priv;
-       drm_local_map_t *sarea;
-       drm_local_map_t *fb;
-       drm_local_map_t *mmio;
-       unsigned long agpAddr;
-       wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
-       char *dma_ptr;
-       unsigned int dma_low;
-       unsigned int dma_high;
-       unsigned int dma_offset;
-       uint32_t dma_wrap;
-       volatile uint32_t *last_pause_ptr;
-       volatile uint32_t *hw_addr_ptr;
-       drm_via_ring_buffer_t ring;
-       ktime_t last_vblank;
-       int last_vblank_valid;
-       ktime_t nsec_per_vblank;
-       atomic_t vbl_received;
-       drm_via_state_t hc_state;
-       char pci_buf[VIA_PCI_BUF_SIZE];
-       const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
-       uint32_t num_fire_offsets;
-       int chipset;
-       drm_via_irq_t via_irqs[VIA_NUM_IRQS];
-       unsigned num_irqs;
-       maskarray_t *irq_masks;
-       uint32_t irq_enable_mask;
-       uint32_t irq_pending_mask;
-       int *irq_map;
-       unsigned int idle_fault;
-       int vram_initialized;
-       struct drm_mm vram_mm;
-       int agp_initialized;
-       struct drm_mm agp_mm;
-       /** Mapping of userspace keys to mm objects */
-       struct idr object_idr;
-       unsigned long vram_offset;
-       unsigned long agp_offset;
-       drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
-       uint32_t dma_diff;
-} drm_via_private_t;
-
-struct via_file_private {
-       struct list_head obj_list;
-};
-
-enum via_family {
-  VIA_OTHER = 0,     /* Baseline */
-  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
-  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
-};
-
-/* VIA MMIO register access */
-static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg)
-{
-       return readl((void __iomem *)(dev_priv->mmio->handle + reg));
-}
-
-static inline void via_write(struct drm_via_private *dev_priv, u32 reg,
-                            u32 val)
-{
-       writel(val, (void __iomem *)(dev_priv->mmio->handle + reg));
-}
-
-static inline void via_write8(struct drm_via_private *dev_priv, u32 reg,
-                             u32 val)
-{
-       writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg));
-}
-
-static inline void via_write8_mask(struct drm_via_private *dev_priv,
-                                  u32 reg, u32 mask, u32 val)
-{
-       u32 tmp;
-
-       tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg));
-       tmp = (tmp & ~mask) | (val & mask);
-       writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg));
-}
-
-/*
- * Poll in a loop waiting for 'contidition' to be true.
- * Note: A direct replacement with wait_event_interruptible_timeout()
- *       will not work unless driver is updated to emit wake_up()
- *       in relevant places that can impact the 'condition'
- *
- * Returns:
- *   ret keeps current value if 'condition' becomes true
- *   ret = -BUSY if timeout happens
- *   ret = -EINTR if a signal interrupted the waiting period
- */
-#define VIA_WAIT_ON( ret, queue, timeout, condition )          \
-do {                                                           \
-       DECLARE_WAITQUEUE(entry, current);                      \
-       unsigned long end = jiffies + (timeout);                \
-       add_wait_queue(&(queue), &entry);                       \
-                                                               \
-       for (;;) {                                              \
-               __set_current_state(TASK_INTERRUPTIBLE);        \
-               if (condition)                                  \
-                       break;                                  \
-               if (time_after_eq(jiffies, end)) {              \
-                       ret = -EBUSY;                           \
-                       break;                                  \
-               }                                               \
-               schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);    \
-               if (signal_pending(current)) {                  \
-                       ret = -EINTR;                           \
-                       break;                                  \
-               }                                               \
-       }                                                       \
-       __set_current_state(TASK_RUNNING);                      \
-       remove_wait_queue(&(queue), &entry);                    \
-} while (0)
-
-extern const struct drm_ioctl_desc via_ioctls[];
-extern int via_max_ioctl;
-
-extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv);
-extern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv);
-
-extern int via_driver_load(struct drm_device *dev, unsigned long chipset);
-extern void via_driver_unload(struct drm_device *dev);
-
-extern int via_init_context(struct drm_device *dev, int context);
-extern int via_final_context(struct drm_device *dev, int context);
-
-extern int via_do_cleanup_map(struct drm_device *dev);
-extern u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
-extern int via_enable_vblank(struct drm_device *dev, unsigned int pipe);
-extern void via_disable_vblank(struct drm_device *dev, unsigned int pipe);
-
-extern irqreturn_t via_driver_irq_handler(int irq, void *arg);
-extern void via_driver_irq_preinstall(struct drm_device *dev);
-extern int via_driver_irq_postinstall(struct drm_device *dev);
-extern void via_driver_irq_uninstall(struct drm_device *dev);
-
-extern int via_dma_cleanup(struct drm_device *dev);
-extern void via_init_command_verifier(void);
-extern int via_driver_dma_quiescent(struct drm_device *dev);
-extern void via_init_futex(drm_via_private_t *dev_priv);
-extern void via_cleanup_futex(drm_via_private_t *dev_priv);
-extern void via_release_futex(drm_via_private_t *dev_priv, int context);
-
-extern void via_reclaim_buffers_locked(struct drm_device *dev,
-                                      struct drm_file *file_priv);
-extern void via_lastclose(struct drm_device *dev);
-
-extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
-extern void via_init_dmablit(struct drm_device *dev);
-
-#endif
diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c
deleted file mode 100644 (file)
index faeae5d..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-/* via_irq.c
- *
- * Copyright 2004 BEAM Ltd.
- * Copyright 2002 Tungsten Graphics, Inc.
- * Copyright 2005 Thomas Hellstrom.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BEAM LTD, TUNGSTEN GRAPHICS  AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Terry Barnaby <terry1@beam.ltd.uk>
- *    Keith Whitwell <keith@tungstengraphics.com>
- *    Thomas Hellstrom <unichrome@shipmail.org>
- *
- * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
- * interrupt, as well as an infrastructure to handle other interrupts of the chip.
- * The refresh rate is also calculated for video playback sync purposes.
- */
-
-#include <drm/drm_device.h>
-#include <drm/drm_vblank.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-
-#define VIA_REG_INTERRUPT       0x200
-
-/* VIA_REG_INTERRUPT */
-#define VIA_IRQ_GLOBAL   (1 << 31)
-#define VIA_IRQ_VBLANK_ENABLE   (1 << 19)
-#define VIA_IRQ_VBLANK_PENDING  (1 << 3)
-#define VIA_IRQ_HQV0_ENABLE     (1 << 11)
-#define VIA_IRQ_HQV1_ENABLE     (1 << 25)
-#define VIA_IRQ_HQV0_PENDING    (1 << 9)
-#define VIA_IRQ_HQV1_PENDING    (1 << 10)
-#define VIA_IRQ_DMA0_DD_ENABLE  (1 << 20)
-#define VIA_IRQ_DMA0_TD_ENABLE  (1 << 21)
-#define VIA_IRQ_DMA1_DD_ENABLE  (1 << 22)
-#define VIA_IRQ_DMA1_TD_ENABLE  (1 << 23)
-#define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
-#define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
-#define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
-#define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
-
-
-/*
- * Device-specific IRQs go here. This type might need to be extended with
- * the register if there are multiple IRQ control registers.
- * Currently we activate the HQV interrupts of  Unichrome Pro group A.
- */
-
-static maskarray_t via_pro_group_a_irqs[] = {
-       {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
-        0x00000000 },
-       {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
-        0x00000000 },
-       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-};
-static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
-static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
-
-static maskarray_t via_unichrome_irqs[] = {
-       {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
-       {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
-        VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
-};
-static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
-static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
-
-
-u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       if (pipe != 0)
-               return 0;
-
-       return atomic_read(&dev_priv->vbl_received);
-}
-
-irqreturn_t via_driver_irq_handler(int irq, void *arg)
-{
-       struct drm_device *dev = (struct drm_device *) arg;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-       int handled = 0;
-       ktime_t cur_vblank;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
-       int i;
-
-       status = via_read(dev_priv, VIA_REG_INTERRUPT);
-       if (status & VIA_IRQ_VBLANK_PENDING) {
-               atomic_inc(&dev_priv->vbl_received);
-               if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
-                       cur_vblank = ktime_get();
-                       if (dev_priv->last_vblank_valid) {
-                               dev_priv->nsec_per_vblank =
-                                       ktime_sub(cur_vblank,
-                                               dev_priv->last_vblank) >> 4;
-                       }
-                       dev_priv->last_vblank = cur_vblank;
-                       dev_priv->last_vblank_valid = 1;
-               }
-               if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
-                       DRM_DEBUG("nsec per vblank is: %llu\n",
-                                 ktime_to_ns(dev_priv->nsec_per_vblank));
-               }
-               drm_handle_vblank(dev, 0);
-               handled = 1;
-       }
-
-       for (i = 0; i < dev_priv->num_irqs; ++i) {
-               if (status & cur_irq->pending_mask) {
-                       atomic_inc(&cur_irq->irq_received);
-                       wake_up(&cur_irq->irq_queue);
-                       handled = 1;
-                       if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
-                               via_dmablit_handler(dev, 0, 1);
-                       else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i)
-                               via_dmablit_handler(dev, 1, 1);
-               }
-               cur_irq++;
-       }
-
-       /* Acknowledge interrupts */
-       via_write(dev_priv, VIA_REG_INTERRUPT, status);
-
-
-       if (handled)
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
-}
-
-static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
-{
-       u32 status;
-
-       if (dev_priv) {
-               /* Acknowledge interrupts */
-               status = via_read(dev_priv, VIA_REG_INTERRUPT);
-               via_write(dev_priv, VIA_REG_INTERRUPT, status |
-                         dev_priv->irq_pending_mask);
-       }
-}
-
-int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       u32 status;
-
-       if (pipe != 0) {
-               DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
-               return -EINVAL;
-       }
-
-       status = via_read(dev_priv, VIA_REG_INTERRUPT);
-       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
-
-       via_write8(dev_priv, 0x83d4, 0x11);
-       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
-
-       return 0;
-}
-
-void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       u32 status;
-
-       status = via_read(dev_priv, VIA_REG_INTERRUPT);
-       via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
-
-       via_write8(dev_priv, 0x83d4, 0x11);
-       via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
-
-       if (pipe != 0)
-               DRM_ERROR("%s:  bad crtc %u\n", __func__, pipe);
-}
-
-static int
-via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence,
-                   unsigned int *sequence)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       unsigned int cur_irq_sequence;
-       drm_via_irq_t *cur_irq;
-       int ret = 0;
-       maskarray_t *masks;
-       int real_irq;
-
-       DRM_DEBUG("\n");
-
-       if (!dev_priv) {
-               DRM_ERROR("called with no initialization\n");
-               return -EINVAL;
-       }
-
-       if (irq >= drm_via_irq_num) {
-               DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
-               return -EINVAL;
-       }
-
-       real_irq = dev_priv->irq_map[irq];
-
-       if (real_irq < 0) {
-               DRM_ERROR("Video IRQ %d not available on this hardware.\n",
-                         irq);
-               return -EINVAL;
-       }
-
-       masks = dev_priv->irq_masks;
-       cur_irq = dev_priv->via_irqs + real_irq;
-
-       if (masks[real_irq][2] && !force_sequence) {
-               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
-                           ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) ==
-                            masks[irq][4]));
-               cur_irq_sequence = atomic_read(&cur_irq->irq_received);
-       } else {
-               VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
-                           (((cur_irq_sequence =
-                              atomic_read(&cur_irq->irq_received)) -
-                             *sequence) <= (1 << 23)));
-       }
-       *sequence = cur_irq_sequence;
-       return ret;
-}
-
-
-/*
- * drm_dma.h hooks
- */
-
-void via_driver_irq_preinstall(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-       drm_via_irq_t *cur_irq;
-       int i;
-
-       DRM_DEBUG("dev_priv: %p\n", dev_priv);
-       if (dev_priv) {
-               cur_irq = dev_priv->via_irqs;
-
-               dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
-               dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
-
-               if (dev_priv->chipset == VIA_PRO_GROUP_A ||
-                   dev_priv->chipset == VIA_DX9_0) {
-                       dev_priv->irq_masks = via_pro_group_a_irqs;
-                       dev_priv->num_irqs = via_num_pro_group_a;
-                       dev_priv->irq_map = via_irqmap_pro_group_a;
-               } else {
-                       dev_priv->irq_masks = via_unichrome_irqs;
-                       dev_priv->num_irqs = via_num_unichrome;
-                       dev_priv->irq_map = via_irqmap_unichrome;
-               }
-
-               for (i = 0; i < dev_priv->num_irqs; ++i) {
-                       atomic_set(&cur_irq->irq_received, 0);
-                       cur_irq->enable_mask = dev_priv->irq_masks[i][0];
-                       cur_irq->pending_mask = dev_priv->irq_masks[i][1];
-                       init_waitqueue_head(&cur_irq->irq_queue);
-                       dev_priv->irq_enable_mask |= cur_irq->enable_mask;
-                       dev_priv->irq_pending_mask |= cur_irq->pending_mask;
-                       cur_irq++;
-
-                       DRM_DEBUG("Initializing IRQ %d\n", i);
-               }
-
-               dev_priv->last_vblank_valid = 0;
-
-               /* Clear VSync interrupt regs */
-               status = via_read(dev_priv, VIA_REG_INTERRUPT);
-               via_write(dev_priv, VIA_REG_INTERRUPT, status &
-                         ~(dev_priv->irq_enable_mask));
-
-               /* Clear bits if they're already high */
-               viadrv_acknowledge_irqs(dev_priv);
-       }
-}
-
-int via_driver_irq_postinstall(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-
-       DRM_DEBUG("fun: %s\n", __func__);
-       if (!dev_priv)
-               return -EINVAL;
-
-       status = via_read(dev_priv, VIA_REG_INTERRUPT);
-       via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
-                 | dev_priv->irq_enable_mask);
-
-       /* Some magic, oh for some data sheets ! */
-       via_write8(dev_priv, 0x83d4, 0x11);
-       via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
-
-       return 0;
-}
-
-void via_driver_irq_uninstall(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       u32 status;
-
-       DRM_DEBUG("\n");
-       if (dev_priv) {
-
-               /* Some more magic, oh for some data sheets ! */
-
-               via_write8(dev_priv, 0x83d4, 0x11);
-               via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
-
-               status = via_read(dev_priv, VIA_REG_INTERRUPT);
-               via_write(dev_priv, VIA_REG_INTERRUPT, status &
-                         ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
-       }
-}
-
-int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_irqwait_t *irqwait = data;
-       struct timespec64 now;
-       int ret = 0;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
-       int force_sequence;
-
-       if (irqwait->request.irq >= dev_priv->num_irqs) {
-               DRM_ERROR("Trying to wait on unknown irq %d\n",
-                         irqwait->request.irq);
-               return -EINVAL;
-       }
-
-       cur_irq += irqwait->request.irq;
-
-       switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
-       case VIA_IRQ_RELATIVE:
-               irqwait->request.sequence +=
-                       atomic_read(&cur_irq->irq_received);
-               irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
-               break;
-       case VIA_IRQ_ABSOLUTE:
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (irqwait->request.type & VIA_IRQ_SIGNAL) {
-               DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
-               return -EINVAL;
-       }
-
-       force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
-
-       ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
-                                 &irqwait->request.sequence);
-       ktime_get_ts64(&now);
-       irqwait->reply.tval_sec = now.tv_sec;
-       irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
-
-       return ret;
-}
diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c
deleted file mode 100644 (file)
index a9f6b0c..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
- * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include <linux/pci.h>
-
-#include <drm/drm_device.h>
-#include <drm/drm_vblank.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-
-static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       DRM_DEBUG("\n");
-
-       dev_priv->sarea = drm_legacy_getsarea(dev);
-       if (!dev_priv->sarea) {
-               DRM_ERROR("could not find sarea!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->fb = drm_legacy_findmap(dev, init->fb_offset);
-       if (!dev_priv->fb) {
-               DRM_ERROR("could not find framebuffer!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-       dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset);
-       if (!dev_priv->mmio) {
-               DRM_ERROR("could not find mmio region!\n");
-               dev->dev_private = (void *)dev_priv;
-               via_do_cleanup_map(dev);
-               return -EINVAL;
-       }
-
-       dev_priv->sarea_priv =
-           (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
-                                init->sarea_priv_offset);
-
-       dev_priv->agpAddr = init->agpAddr;
-
-       via_init_futex(dev_priv);
-
-       via_init_dmablit(dev);
-
-       dev->dev_private = (void *)dev_priv;
-       return 0;
-}
-
-int via_do_cleanup_map(struct drm_device *dev)
-{
-       via_dma_cleanup(dev);
-
-       return 0;
-}
-
-int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_init_t *init = data;
-
-       DRM_DEBUG("\n");
-
-       switch (init->func) {
-       case VIA_INIT_MAP:
-               return via_do_init_map(dev, init);
-       case VIA_CLEANUP_MAP:
-               return via_do_cleanup_map(dev);
-       }
-
-       return -EINVAL;
-}
-
-int via_driver_load(struct drm_device *dev, unsigned long chipset)
-{
-       struct pci_dev *pdev = to_pci_dev(dev->dev);
-       drm_via_private_t *dev_priv;
-       int ret = 0;
-
-       dev_priv = kzalloc(sizeof(drm_via_private_t), GFP_KERNEL);
-       if (dev_priv == NULL)
-               return -ENOMEM;
-
-       idr_init(&dev_priv->object_idr);
-       dev->dev_private = (void *)dev_priv;
-
-       dev_priv->chipset = chipset;
-
-       pci_set_master(pdev);
-
-       ret = drm_vblank_init(dev, 1);
-       if (ret) {
-               kfree(dev_priv);
-               return ret;
-       }
-
-       return 0;
-}
-
-void via_driver_unload(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-
-       idr_destroy(&dev_priv->object_idr);
-
-       kfree(dev_priv);
-}
diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c
deleted file mode 100644 (file)
index c9afa1a..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2006 Tungsten Graphics Inc., Bismarck, ND., USA.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-/*
- * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include <linux/slab.h>
-
-#include <drm/drm_device.h>
-#include <drm/drm_file.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-
-#define VIA_MM_ALIGN_SHIFT 4
-#define VIA_MM_ALIGN_MASK ((1 << VIA_MM_ALIGN_SHIFT) - 1)
-
-struct via_memblock {
-       struct drm_mm_node mm_node;
-       struct list_head owner_list;
-};
-
-int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_agp_t *agp = data;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       drm_mm_init(&dev_priv->agp_mm, 0, agp->size >> VIA_MM_ALIGN_SHIFT);
-
-       dev_priv->agp_initialized = 1;
-       dev_priv->agp_offset = agp->offset;
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("offset = %u, size = %u\n", agp->offset, agp->size);
-       return 0;
-}
-
-int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_fb_t *fb = data;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       mutex_lock(&dev->struct_mutex);
-       drm_mm_init(&dev_priv->vram_mm, 0, fb->size >> VIA_MM_ALIGN_SHIFT);
-
-       dev_priv->vram_initialized = 1;
-       dev_priv->vram_offset = fb->offset;
-
-       mutex_unlock(&dev->struct_mutex);
-       DRM_DEBUG("offset = %u, size = %u\n", fb->offset, fb->size);
-
-       return 0;
-
-}
-
-int via_final_context(struct drm_device *dev, int context)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       via_release_futex(dev_priv, context);
-
-       /* Linux specific until context tracking code gets ported to BSD */
-       /* Last context, perform cleanup */
-       if (list_is_singular(&dev->ctxlist)) {
-               DRM_DEBUG("Last Context\n");
-               drm_legacy_irq_uninstall(dev);
-               via_cleanup_futex(dev_priv);
-               via_do_cleanup_map(dev);
-       }
-       return 1;
-}
-
-void via_lastclose(struct drm_device *dev)
-{
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-
-       if (!dev_priv)
-               return;
-
-       mutex_lock(&dev->struct_mutex);
-       if (dev_priv->vram_initialized) {
-               drm_mm_takedown(&dev_priv->vram_mm);
-               dev_priv->vram_initialized = 0;
-       }
-       if (dev_priv->agp_initialized) {
-               drm_mm_takedown(&dev_priv->agp_mm);
-               dev_priv->agp_initialized = 0;
-       }
-       mutex_unlock(&dev->struct_mutex);
-}
-
-int via_mem_alloc(struct drm_device *dev, void *data,
-                 struct drm_file *file)
-{
-       drm_via_mem_t *mem = data;
-       int retval = 0, user_key;
-       struct via_memblock *item;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       struct via_file_private *file_priv = file->driver_priv;
-       unsigned long tmpSize;
-
-       if (mem->type > VIA_MEM_AGP) {
-               DRM_ERROR("Unknown memory type allocation\n");
-               return -EINVAL;
-       }
-       mutex_lock(&dev->struct_mutex);
-       if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized :
-                     dev_priv->agp_initialized)) {
-               mutex_unlock(&dev->struct_mutex);
-               DRM_ERROR
-                   ("Attempt to allocate from uninitialized memory manager.\n");
-               return -EINVAL;
-       }
-
-       item = kzalloc(sizeof(*item), GFP_KERNEL);
-       if (!item) {
-               retval = -ENOMEM;
-               goto fail_alloc;
-       }
-
-       tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT;
-       if (mem->type == VIA_MEM_AGP)
-               retval = drm_mm_insert_node(&dev_priv->agp_mm,
-                                           &item->mm_node,
-                                           tmpSize);
-       else
-               retval = drm_mm_insert_node(&dev_priv->vram_mm,
-                                           &item->mm_node,
-                                           tmpSize);
-       if (retval)
-               goto fail_alloc;
-
-       retval = idr_alloc(&dev_priv->object_idr, item, 1, 0, GFP_KERNEL);
-       if (retval < 0)
-               goto fail_idr;
-       user_key = retval;
-
-       list_add(&item->owner_list, &file_priv->obj_list);
-       mutex_unlock(&dev->struct_mutex);
-
-       mem->offset = ((mem->type == VIA_MEM_VIDEO) ?
-                     dev_priv->vram_offset : dev_priv->agp_offset) +
-           ((item->mm_node.start) << VIA_MM_ALIGN_SHIFT);
-       mem->index = user_key;
-
-       return 0;
-
-fail_idr:
-       drm_mm_remove_node(&item->mm_node);
-fail_alloc:
-       kfree(item);
-       mutex_unlock(&dev->struct_mutex);
-
-       mem->offset = 0;
-       mem->size = 0;
-       mem->index = 0;
-       DRM_DEBUG("Video memory allocation failed\n");
-
-       return retval;
-}
-
-int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_private_t *dev_priv = dev->dev_private;
-       drm_via_mem_t *mem = data;
-       struct via_memblock *obj;
-
-       mutex_lock(&dev->struct_mutex);
-       obj = idr_find(&dev_priv->object_idr, mem->index);
-       if (obj == NULL) {
-               mutex_unlock(&dev->struct_mutex);
-               return -EINVAL;
-       }
-
-       idr_remove(&dev_priv->object_idr, mem->index);
-       list_del(&obj->owner_list);
-       drm_mm_remove_node(&obj->mm_node);
-       kfree(obj);
-       mutex_unlock(&dev->struct_mutex);
-
-       DRM_DEBUG("free = 0x%lx\n", mem->index);
-
-       return 0;
-}
-
-
-void via_reclaim_buffers_locked(struct drm_device *dev,
-                               struct drm_file *file)
-{
-       struct via_file_private *file_priv = file->driver_priv;
-       struct via_memblock *entry, *next;
-
-       if (!(dev->master && file->master->lock.hw_lock))
-               return;
-
-       drm_legacy_idlelock_take(&file->master->lock);
-
-       mutex_lock(&dev->struct_mutex);
-       if (list_empty(&file_priv->obj_list)) {
-               mutex_unlock(&dev->struct_mutex);
-               drm_legacy_idlelock_release(&file->master->lock);
-
-               return;
-       }
-
-       via_driver_dma_quiescent(dev);
-
-       list_for_each_entry_safe(entry, next, &file_priv->obj_list,
-                                owner_list) {
-               list_del(&entry->owner_list);
-               drm_mm_remove_node(&entry->mm_node);
-               kfree(entry);
-       }
-       mutex_unlock(&dev->struct_mutex);
-
-       drm_legacy_idlelock_release(&file->master->lock);
-
-       return;
-}
diff --git a/drivers/gpu/drm/via/via_verifier.c b/drivers/gpu/drm/via/via_verifier.c
deleted file mode 100644 (file)
index 3d6e3a7..0000000
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*
- * Copyright 2004 The Unichrome Project. All Rights Reserved.
- * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellstrom 2004, 2005.
- * This code was written using docs obtained under NDA from VIA Inc.
- *
- * Don't run this code directly on an AGP buffer. Due to cache problems it will
- * be very slow.
- */
-
-#include <drm/drm_device.h>
-#include <drm/drm_legacy.h>
-#include <drm/via_drm.h>
-
-#include "via_3d_reg.h"
-#include "via_drv.h"
-#include "via_verifier.h"
-
-typedef enum {
-       state_command,
-       state_header2,
-       state_header1,
-       state_vheader5,
-       state_vheader6,
-       state_error
-} verifier_state_t;
-
-typedef enum {
-       no_check = 0,
-       check_for_header2,
-       check_for_header1,
-       check_for_header2_err,
-       check_for_header1_err,
-       check_for_fire,
-       check_z_buffer_addr0,
-       check_z_buffer_addr1,
-       check_z_buffer_addr_mode,
-       check_destination_addr0,
-       check_destination_addr1,
-       check_destination_addr_mode,
-       check_for_dummy,
-       check_for_dd,
-       check_texture_addr0,
-       check_texture_addr1,
-       check_texture_addr2,
-       check_texture_addr3,
-       check_texture_addr4,
-       check_texture_addr5,
-       check_texture_addr6,
-       check_texture_addr7,
-       check_texture_addr8,
-       check_texture_addr_mode,
-       check_for_vertex_count,
-       check_number_texunits,
-       forbidden_command
-} hazard_t;
-
-/*
- * Associates each hazard above with a possible multi-command
- * sequence. For example an address that is split over multiple
- * commands and that needs to be checked at the first command
- * that does not include any part of the address.
- */
-
-static drm_via_sequence_t seqs[] = {
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       no_sequence,
-       z_address,
-       z_address,
-       z_address,
-       dest_address,
-       dest_address,
-       dest_address,
-       no_sequence,
-       no_sequence,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       tex_address,
-       no_sequence
-};
-
-typedef struct {
-       unsigned int code;
-       hazard_t hz;
-} hz_init_t;
-
-static hz_init_t init_table1[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xee, check_for_fire},
-       {0xcc, check_for_dummy},
-       {0xdd, check_for_dd},
-       {0x00, no_check},
-       {0x10, check_z_buffer_addr0},
-       {0x11, check_z_buffer_addr1},
-       {0x12, check_z_buffer_addr_mode},
-       {0x13, no_check},
-       {0x14, no_check},
-       {0x15, no_check},
-       {0x23, no_check},
-       {0x24, no_check},
-       {0x33, no_check},
-       {0x34, no_check},
-       {0x35, no_check},
-       {0x36, no_check},
-       {0x37, no_check},
-       {0x38, no_check},
-       {0x39, no_check},
-       {0x3A, no_check},
-       {0x3B, no_check},
-       {0x3C, no_check},
-       {0x3D, no_check},
-       {0x3E, no_check},
-       {0x40, check_destination_addr0},
-       {0x41, check_destination_addr1},
-       {0x42, check_destination_addr_mode},
-       {0x43, no_check},
-       {0x44, no_check},
-       {0x50, no_check},
-       {0x51, no_check},
-       {0x52, no_check},
-       {0x53, no_check},
-       {0x54, no_check},
-       {0x55, no_check},
-       {0x56, no_check},
-       {0x57, no_check},
-       {0x58, no_check},
-       {0x70, no_check},
-       {0x71, no_check},
-       {0x78, no_check},
-       {0x79, no_check},
-       {0x7A, no_check},
-       {0x7B, no_check},
-       {0x7C, no_check},
-       {0x7D, check_for_vertex_count}
-};
-
-static hz_init_t init_table2[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xee, check_for_fire},
-       {0xcc, check_for_dummy},
-       {0x00, check_texture_addr0},
-       {0x01, check_texture_addr0},
-       {0x02, check_texture_addr0},
-       {0x03, check_texture_addr0},
-       {0x04, check_texture_addr0},
-       {0x05, check_texture_addr0},
-       {0x06, check_texture_addr0},
-       {0x07, check_texture_addr0},
-       {0x08, check_texture_addr0},
-       {0x09, check_texture_addr0},
-       {0x20, check_texture_addr1},
-       {0x21, check_texture_addr1},
-       {0x22, check_texture_addr1},
-       {0x23, check_texture_addr4},
-       {0x2B, check_texture_addr3},
-       {0x2C, check_texture_addr3},
-       {0x2D, check_texture_addr3},
-       {0x2E, check_texture_addr3},
-       {0x2F, check_texture_addr3},
-       {0x30, check_texture_addr3},
-       {0x31, check_texture_addr3},
-       {0x32, check_texture_addr3},
-       {0x33, check_texture_addr3},
-       {0x34, check_texture_addr3},
-       {0x4B, check_texture_addr5},
-       {0x4C, check_texture_addr6},
-       {0x51, check_texture_addr7},
-       {0x52, check_texture_addr8},
-       {0x77, check_texture_addr2},
-       {0x78, no_check},
-       {0x79, no_check},
-       {0x7A, no_check},
-       {0x7B, check_texture_addr_mode},
-       {0x7C, no_check},
-       {0x7D, no_check},
-       {0x7E, no_check},
-       {0x7F, no_check},
-       {0x80, no_check},
-       {0x81, no_check},
-       {0x82, no_check},
-       {0x83, no_check},
-       {0x85, no_check},
-       {0x86, no_check},
-       {0x87, no_check},
-       {0x88, no_check},
-       {0x89, no_check},
-       {0x8A, no_check},
-       {0x90, no_check},
-       {0x91, no_check},
-       {0x92, no_check},
-       {0x93, no_check}
-};
-
-static hz_init_t init_table3[] = {
-       {0xf2, check_for_header2_err},
-       {0xf0, check_for_header1_err},
-       {0xcc, check_for_dummy},
-       {0x00, check_number_texunits}
-};
-
-static hazard_t table1[256];
-static hazard_t table2[256];
-static hazard_t table3[256];
-
-static __inline__ int
-eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
-{
-       if ((buf_end - *buf) >= num_words) {
-               *buf += num_words;
-               return 0;
-       }
-       DRM_ERROR("Illegal termination of DMA command buffer\n");
-       return 1;
-}
-
-/*
- * Partially stolen from drm_memory.h
- */
-
-static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq,
-                                                   unsigned long offset,
-                                                   unsigned long size,
-                                                   struct drm_device *dev)
-{
-       struct drm_map_list *r_list;
-       drm_local_map_t *map = seq->map_cache;
-
-       if (map && map->offset <= offset
-           && (offset + size) <= (map->offset + map->size)) {
-               return map;
-       }
-
-       list_for_each_entry(r_list, &dev->maplist, head) {
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (map->offset <= offset
-                   && (offset + size) <= (map->offset + map->size)
-                   && !(map->flags & _DRM_RESTRICTED)
-                   && (map->type == _DRM_AGP)) {
-                       seq->map_cache = map;
-                       return map;
-               }
-       }
-       return NULL;
-}
-
-/*
- * Require that all AGP texture levels reside in the same AGP map which should
- * be mappable by the client. This is not a big restriction.
- * FIXME: To actually enforce this security policy strictly, drm_rmmap
- * would have to wait for dma quiescent before removing an AGP map.
- * The via_drm_lookup_agp_map call in reality seems to take
- * very little CPU time.
- */
-
-static __inline__ int finish_current_sequence(drm_via_state_t * cur_seq)
-{
-       switch (cur_seq->unfinished) {
-       case z_address:
-               DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
-               break;
-       case dest_address:
-               DRM_DEBUG("Destination start address is 0x%x\n",
-                         cur_seq->d_addr);
-               break;
-       case tex_address:
-               if (cur_seq->agp_texture) {
-                       unsigned start =
-                           cur_seq->tex_level_lo[cur_seq->texture];
-                       unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
-                       unsigned long lo = ~0, hi = 0, tmp;
-                       uint32_t *addr, *pitch, *height, tex;
-                       unsigned i;
-                       int npot;
-
-                       if (end > 9)
-                               end = 9;
-                       if (start > 9)
-                               start = 9;
-
-                       addr =
-                           &(cur_seq->t_addr[tex = cur_seq->texture][start]);
-                       pitch = &(cur_seq->pitch[tex][start]);
-                       height = &(cur_seq->height[tex][start]);
-                       npot = cur_seq->tex_npot[tex];
-                       for (i = start; i <= end; ++i) {
-                               tmp = *addr++;
-                               if (tmp < lo)
-                                       lo = tmp;
-                               if (i == 0 && npot)
-                                       tmp += (*height++ * *pitch++);
-                               else
-                                       tmp += (*height++ << *pitch++);
-                               if (tmp > hi)
-                                       hi = tmp;
-                       }
-
-                       if (!via_drm_lookup_agp_map
-                           (cur_seq, lo, hi - lo, cur_seq->dev)) {
-                               DRM_ERROR
-                                   ("AGP texture is not in allowed map\n");
-                               return 2;
-                       }
-               }
-               break;
-       default:
-               break;
-       }
-       cur_seq->unfinished = no_sequence;
-       return 0;
-}
-
-static __inline__ int
-investigate_hazard(uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
-{
-       register uint32_t tmp, *tmp_addr;
-
-       if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
-               int ret;
-               if ((ret = finish_current_sequence(cur_seq)))
-                       return ret;
-       }
-
-       switch (hz) {
-       case check_for_header2:
-               if (cmd == HALCYON_HEADER2)
-                       return 1;
-               return 0;
-       case check_for_header1:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                       return 1;
-               return 0;
-       case check_for_header2_err:
-               if (cmd == HALCYON_HEADER2)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
-               break;
-       case check_for_header1_err:
-               if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
-               break;
-       case check_for_fire:
-               if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD)
-                       return 1;
-               DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
-               break;
-       case check_for_dummy:
-               if (HC_DUMMY == cmd)
-                       return 0;
-               DRM_ERROR("Illegal DMA HC_DUMMY command\n");
-               break;
-       case check_for_dd:
-               if (0xdddddddd == cmd)
-                       return 0;
-               DRM_ERROR("Illegal DMA 0xdddddddd command\n");
-               break;
-       case check_z_buffer_addr0:
-               cur_seq->unfinished = z_address;
-               cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
-                   (cmd & 0x00FFFFFF);
-               return 0;
-       case check_z_buffer_addr1:
-               cur_seq->unfinished = z_address;
-               cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
-                   ((cmd & 0xFF) << 24);
-               return 0;
-       case check_z_buffer_addr_mode:
-               cur_seq->unfinished = z_address;
-               if ((cmd & 0x0000C000) == 0)
-                       return 0;
-               DRM_ERROR("Attempt to place Z buffer in system memory\n");
-               return 2;
-       case check_destination_addr0:
-               cur_seq->unfinished = dest_address;
-               cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
-                   (cmd & 0x00FFFFFF);
-               return 0;
-       case check_destination_addr1:
-               cur_seq->unfinished = dest_address;
-               cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
-                   ((cmd & 0xFF) << 24);
-               return 0;
-       case check_destination_addr_mode:
-               cur_seq->unfinished = dest_address;
-               if ((cmd & 0x0000C000) == 0)
-                       return 0;
-               DRM_ERROR
-                   ("Attempt to place 3D drawing buffer in system memory\n");
-               return 2;
-       case check_texture_addr0:
-               cur_seq->unfinished = tex_address;
-               tmp = (cmd >> 24);
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
-               *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
-               return 0;
-       case check_texture_addr1:
-               cur_seq->unfinished = tex_address;
-               tmp = ((cmd >> 24) - 0x20);
-               tmp += tmp << 1;
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
-               tmp_addr++;
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
-               tmp_addr++;
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
-               return 0;
-       case check_texture_addr2:
-               cur_seq->unfinished = tex_address;
-               cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
-               cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
-               return 0;
-       case check_texture_addr3:
-               cur_seq->unfinished = tex_address;
-               tmp = ((cmd >> 24) - HC_SubA_HTXnL0Pit);
-               if (tmp == 0 &&
-                   (cmd & HC_HTXnEnPit_MASK)) {
-                       cur_seq->pitch[cur_seq->texture][tmp] =
-                               (cmd & HC_HTXnLnPit_MASK);
-                       cur_seq->tex_npot[cur_seq->texture] = 1;
-               } else {
-                       cur_seq->pitch[cur_seq->texture][tmp] =
-                               (cmd & HC_HTXnLnPitE_MASK) >> HC_HTXnLnPitE_SHIFT;
-                       cur_seq->tex_npot[cur_seq->texture] = 0;
-                       if (cmd & 0x000FFFFF) {
-                               DRM_ERROR
-                                       ("Unimplemented texture level 0 pitch mode.\n");
-                               return 2;
-                       }
-               }
-               return 0;
-       case check_texture_addr4:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
-               *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
-               return 0;
-       case check_texture_addr5:
-       case check_texture_addr6:
-               cur_seq->unfinished = tex_address;
-               /*
-                * Texture width. We don't care since we have the pitch.
-                */
-               return 0;
-       case check_texture_addr7:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
-               tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
-               tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
-               tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
-               tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
-               tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
-               tmp_addr[0] = 1 << (cmd & 0x0000000F);
-               return 0;
-       case check_texture_addr8:
-               cur_seq->unfinished = tex_address;
-               tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
-               tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
-               tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
-               tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
-               tmp_addr[6] = 1 << (cmd & 0x0000000F);
-               return 0;
-       case check_texture_addr_mode:
-               cur_seq->unfinished = tex_address;
-               if (2 == (tmp = cmd & 0x00000003)) {
-                       DRM_ERROR
-                           ("Attempt to fetch texture from system memory.\n");
-                       return 2;
-               }
-               cur_seq->agp_texture = (tmp == 3);
-               cur_seq->tex_palette_size[cur_seq->texture] =
-                   (cmd >> 16) & 0x000000007;
-               return 0;
-       case check_for_vertex_count:
-               cur_seq->vertex_count = cmd & 0x0000FFFF;
-               return 0;
-       case check_number_texunits:
-               cur_seq->multitex = (cmd >> 3) & 1;
-               return 0;
-       default:
-               DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
-               return 2;
-       }
-       return 2;
-}
-
-static __inline__ int
-via_check_prim_list(uint32_t const **buffer, const uint32_t * buf_end,
-                   drm_via_state_t *cur_seq)
-{
-       drm_via_private_t *dev_priv =
-           (drm_via_private_t *) cur_seq->dev->dev_private;
-       uint32_t a_fire, bcmd, dw_count;
-       int ret = 0;
-       int have_fire;
-       const uint32_t *buf = *buffer;
-
-       while (buf < buf_end) {
-               have_fire = 0;
-               if ((buf_end - buf) < 2) {
-                       DRM_ERROR
-                           ("Unexpected termination of primitive list.\n");
-                       ret = 1;
-                       break;
-               }
-               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB)
-                       break;
-               bcmd = *buf++;
-               if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
-                       DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
-                                 *buf);
-                       ret = 1;
-                       break;
-               }
-               a_fire =
-                   *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK |
-                   HC_HE3Fire_MASK;
-
-               /*
-                * How many dwords per vertex ?
-                */
-
-               if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
-                       DRM_ERROR("Illegal B command vertex data for AGP.\n");
-                       ret = 1;
-                       break;
-               }
-
-               dw_count = 0;
-               if (bcmd & (1 << 7))
-                       dw_count += (cur_seq->multitex) ? 2 : 1;
-               if (bcmd & (1 << 8))
-                       dw_count += (cur_seq->multitex) ? 2 : 1;
-               if (bcmd & (1 << 9))
-                       dw_count++;
-               if (bcmd & (1 << 10))
-                       dw_count++;
-               if (bcmd & (1 << 11))
-                       dw_count++;
-               if (bcmd & (1 << 12))
-                       dw_count++;
-               if (bcmd & (1 << 13))
-                       dw_count++;
-               if (bcmd & (1 << 14))
-                       dw_count++;
-
-               while (buf < buf_end) {
-                       if (*buf == a_fire) {
-                               if (dev_priv->num_fire_offsets >=
-                                   VIA_FIRE_BUF_SIZE) {
-                                       DRM_ERROR("Fire offset buffer full.\n");
-                                       ret = 1;
-                                       break;
-                               }
-                               dev_priv->fire_offsets[dev_priv->
-                                                      num_fire_offsets++] =
-                                   buf;
-                               have_fire = 1;
-                               buf++;
-                               if (buf < buf_end && *buf == a_fire)
-                                       buf++;
-                               break;
-                       }
-                       if ((*buf == HALCYON_HEADER2) ||
-                           ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
-                               DRM_ERROR("Missing Vertex Fire command, "
-                                         "Stray Vertex Fire command  or verifier "
-                                         "lost sync.\n");
-                               ret = 1;
-                               break;
-                       }
-                       if ((ret = eat_words(&buf, buf_end, dw_count)))
-                               break;
-               }
-               if (buf >= buf_end && !have_fire) {
-                       DRM_ERROR("Missing Vertex Fire command or verifier "
-                                 "lost sync.\n");
-                       ret = 1;
-                       break;
-               }
-               if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
-                       DRM_ERROR("AGP Primitive list end misaligned.\n");
-                       ret = 1;
-                       break;
-               }
-       }
-       *buffer = buf;
-       return ret;
-}
-
-static __inline__ verifier_state_t
-via_check_header2(uint32_t const **buffer, const uint32_t *buf_end,
-                 drm_via_state_t *hc_state)
-{
-       uint32_t cmd;
-       int hz_mode;
-       hazard_t hz;
-       const uint32_t *buf = *buffer;
-       const hazard_t *hz_table;
-
-       if ((buf_end - buf) < 2) {
-               DRM_ERROR
-                   ("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
-               return state_error;
-       }
-       buf++;
-       cmd = (*buf++ & 0xFFFF0000) >> 16;
-
-       switch (cmd) {
-       case HC_ParaType_CmdVdata:
-               if (via_check_prim_list(&buf, buf_end, hc_state))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case HC_ParaType_NotTex:
-               hz_table = table1;
-               break;
-       case HC_ParaType_Tex:
-               hc_state->texture = 0;
-               hz_table = table2;
-               break;
-       case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
-               hc_state->texture = 1;
-               hz_table = table2;
-               break;
-       case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
-               hz_table = table3;
-               break;
-       case HC_ParaType_Auto:
-               if (eat_words(&buf, buf_end, 2))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
-               if (eat_words(&buf, buf_end, 32))
-                       return state_error;
-               *buffer = buf;
-               return state_command;
-       case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
-       case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
-               DRM_ERROR("Texture palettes are rejected because of "
-                         "lack of info how to determine their size.\n");
-               return state_error;
-       case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
-               DRM_ERROR("Fog factor palettes are rejected because of "
-                         "lack of info how to determine their size.\n");
-               return state_error;
-       default:
-
-               /*
-                * There are some unimplemented HC_ParaTypes here, that
-                * need to be implemented if the Mesa driver is extended.
-                */
-
-               DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
-                         "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
-                         cmd, *(buf - 2));
-               *buffer = buf;
-               return state_error;
-       }
-
-       while (buf < buf_end) {
-               cmd = *buf++;
-               if ((hz = hz_table[cmd >> 24])) {
-                       if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
-                               if (hz_mode == 1) {
-                                       buf--;
-                                       break;
-                               }
-                               return state_error;
-                       }
-               } else if (hc_state->unfinished &&
-                          finish_current_sequence(hc_state)) {
-                       return state_error;
-               }
-       }
-       if (hc_state->unfinished && finish_current_sequence(hc_state))
-               return state_error;
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer,
-                 const uint32_t *buf_end, int *fire_count)
-{
-       uint32_t cmd;
-       const uint32_t *buf = *buffer;
-       const uint32_t *next_fire;
-       int burst = 0;
-
-       next_fire = dev_priv->fire_offsets[*fire_count];
-       buf++;
-       cmd = (*buf & 0xFFFF0000) >> 16;
-       via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
-       switch (cmd) {
-       case HC_ParaType_CmdVdata:
-               while ((buf < buf_end) &&
-                      (*fire_count < dev_priv->num_fire_offsets) &&
-                      (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) {
-                       while (buf <= next_fire) {
-                               via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
-                                         (burst & 63), *buf++);
-                               burst += 4;
-                       }
-                       if ((buf < buf_end)
-                           && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
-                               buf++;
-
-                       if (++(*fire_count) < dev_priv->num_fire_offsets)
-                               next_fire = dev_priv->fire_offsets[*fire_count];
-               }
-               break;
-       default:
-               while (buf < buf_end) {
-
-                       if (*buf == HC_HEADER2 ||
-                           (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
-                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
-                           (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               break;
-
-                       via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE +
-                                 (burst & 63), *buf++);
-                       burst += 4;
-               }
-       }
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ int verify_mmio_address(uint32_t address)
-{
-       if ((address > 0x3FF) && (address < 0xC00)) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access 3D- or command burst area.\n");
-               return 1;
-       } else if ((address > 0xCFF) && (address < 0x1300)) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access PCI DMA area.\n");
-               return 1;
-       } else if (address > 0x13FF) {
-               DRM_ERROR("Invalid VIDEO DMA command. "
-                         "Attempt to access VGA registers.\n");
-               return 1;
-       }
-       return 0;
-}
-
-static __inline__ int
-verify_video_tail(uint32_t const **buffer, const uint32_t * buf_end,
-                 uint32_t dwords)
-{
-       const uint32_t *buf = *buffer;
-
-       if (buf_end - buf < dwords) {
-               DRM_ERROR("Illegal termination of video command.\n");
-               return 1;
-       }
-       while (dwords--) {
-               if (*buf++) {
-                       DRM_ERROR("Illegal video command tail.\n");
-                       return 1;
-               }
-       }
-       *buffer = buf;
-       return 0;
-}
-
-static __inline__ verifier_state_t
-via_check_header1(uint32_t const **buffer, const uint32_t * buf_end)
-{
-       uint32_t cmd;
-       const uint32_t *buf = *buffer;
-       verifier_state_t ret = state_command;
-
-       while (buf < buf_end) {
-               cmd = *buf;
-               if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
-                   (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                               break;
-                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
-                                 "Attempt to access 3D- or command burst area.\n");
-                       ret = state_error;
-                       break;
-               } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
-                       if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                               break;
-                       DRM_ERROR("Invalid HALCYON_HEADER1 command. "
-                                 "Attempt to access VGA registers.\n");
-                       ret = state_error;
-                       break;
-               } else {
-                       buf += 2;
-               }
-       }
-       *buffer = buf;
-       return ret;
-}
-
-static __inline__ verifier_state_t
-via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer,
-                 const uint32_t *buf_end)
-{
-       register uint32_t cmd;
-       const uint32_t *buf = *buffer;
-
-       while (buf < buf_end) {
-               cmd = *buf;
-               if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
-                       break;
-               via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
-               buf++;
-       }
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_check_vheader5(uint32_t const **buffer, const uint32_t *buf_end)
-{
-       uint32_t data;
-       const uint32_t *buf = *buffer;
-
-       if (buf_end - buf < 4) {
-               DRM_ERROR("Illegal termination of video header5 command\n");
-               return state_error;
-       }
-
-       data = *buf++ & ~VIA_VIDEOMASK;
-       if (verify_mmio_address(data))
-               return state_error;
-
-       data = *buf++;
-       if (*buf++ != 0x00F50000) {
-               DRM_ERROR("Illegal header5 header data\n");
-               return state_error;
-       }
-       if (*buf++ != 0x00000000) {
-               DRM_ERROR("Illegal header5 header data\n");
-               return state_error;
-       }
-       if (eat_words(&buf, buf_end, data))
-               return state_error;
-       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
-               return state_error;
-       *buffer = buf;
-       return state_command;
-
-}
-
-static __inline__ verifier_state_t
-via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer,
-                  const uint32_t *buf_end)
-{
-       uint32_t addr, count, i;
-       const uint32_t *buf = *buffer;
-
-       addr = *buf++ & ~VIA_VIDEOMASK;
-       i = count = *buf;
-       buf += 3;
-       while (i--)
-               via_write(dev_priv, addr, *buf++);
-       if (count & 3)
-               buf += 4 - (count & 3);
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_check_vheader6(uint32_t const **buffer, const uint32_t * buf_end)
-{
-       uint32_t data;
-       const uint32_t *buf = *buffer;
-       uint32_t i;
-
-       if (buf_end - buf < 4) {
-               DRM_ERROR("Illegal termination of video header6 command\n");
-               return state_error;
-       }
-       buf++;
-       data = *buf++;
-       if (*buf++ != 0x00F60000) {
-               DRM_ERROR("Illegal header6 header data\n");
-               return state_error;
-       }
-       if (*buf++ != 0x00000000) {
-               DRM_ERROR("Illegal header6 header data\n");
-               return state_error;
-       }
-       if ((buf_end - buf) < (data << 1)) {
-               DRM_ERROR("Illegal termination of video header6 command\n");
-               return state_error;
-       }
-       for (i = 0; i < data; ++i) {
-               if (verify_mmio_address(*buf++))
-                       return state_error;
-               buf++;
-       }
-       data <<= 1;
-       if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
-               return state_error;
-       *buffer = buf;
-       return state_command;
-}
-
-static __inline__ verifier_state_t
-via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer,
-                  const uint32_t *buf_end)
-{
-
-       uint32_t addr, count, i;
-       const uint32_t *buf = *buffer;
-
-       i = count = *++buf;
-       buf += 3;
-       while (i--) {
-               addr = *buf++;
-               via_write(dev_priv, addr, *buf++);
-       }
-       count <<= 1;
-       if (count & 3)
-               buf += 4 - (count & 3);
-       *buffer = buf;
-       return state_command;
-}
-
-int
-via_verify_command_stream(const uint32_t * buf, unsigned int size,
-                         struct drm_device * dev, int agp)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_state_t *hc_state = &dev_priv->hc_state;
-       drm_via_state_t saved_state = *hc_state;
-       uint32_t cmd;
-       const uint32_t *buf_end = buf + (size >> 2);
-       verifier_state_t state = state_command;
-       int cme_video;
-       int supported_3d;
-
-       cme_video = (dev_priv->chipset == VIA_PRO_GROUP_A ||
-                    dev_priv->chipset == VIA_DX9_0);
-
-       supported_3d = dev_priv->chipset != VIA_DX9_0;
-
-       hc_state->dev = dev;
-       hc_state->unfinished = no_sequence;
-       hc_state->map_cache = NULL;
-       hc_state->agp = agp;
-       hc_state->buf_start = buf;
-       dev_priv->num_fire_offsets = 0;
-
-       while (buf < buf_end) {
-
-               switch (state) {
-               case state_header2:
-                       state = via_check_header2(&buf, buf_end, hc_state);
-                       break;
-               case state_header1:
-                       state = via_check_header1(&buf, buf_end);
-                       break;
-               case state_vheader5:
-                       state = via_check_vheader5(&buf, buf_end);
-                       break;
-               case state_vheader6:
-                       state = via_check_vheader6(&buf, buf_end);
-                       break;
-               case state_command:
-                       cmd = *buf;
-                       if ((cmd == HALCYON_HEADER2) && supported_3d)
-                               state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                               state = state_header1;
-                       else if (cme_video
-                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
-                               state = state_vheader5;
-                       else if (cme_video
-                                && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               state = state_vheader6;
-                       else if ((cmd == HALCYON_HEADER2) && !supported_3d) {
-                               DRM_ERROR("Accelerated 3D is not supported on this chipset yet.\n");
-                               state = state_error;
-                       } else {
-                               DRM_ERROR
-                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                    cmd);
-                               state = state_error;
-                       }
-                       break;
-               case state_error:
-               default:
-                       *hc_state = saved_state;
-                       return -EINVAL;
-               }
-       }
-       if (state == state_error) {
-               *hc_state = saved_state;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-int
-via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
-                        unsigned int size)
-{
-
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       uint32_t cmd;
-       const uint32_t *buf_end = buf + (size >> 2);
-       verifier_state_t state = state_command;
-       int fire_count = 0;
-
-       while (buf < buf_end) {
-
-               switch (state) {
-               case state_header2:
-                       state =
-                           via_parse_header2(dev_priv, &buf, buf_end,
-                                             &fire_count);
-                       break;
-               case state_header1:
-                       state = via_parse_header1(dev_priv, &buf, buf_end);
-                       break;
-               case state_vheader5:
-                       state = via_parse_vheader5(dev_priv, &buf, buf_end);
-                       break;
-               case state_vheader6:
-                       state = via_parse_vheader6(dev_priv, &buf, buf_end);
-                       break;
-               case state_command:
-                       cmd = *buf;
-                       if (cmd == HALCYON_HEADER2)
-                               state = state_header2;
-                       else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
-                               state = state_header1;
-                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
-                               state = state_vheader5;
-                       else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
-                               state = state_vheader6;
-                       else {
-                               DRM_ERROR
-                                   ("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
-                                    cmd);
-                               state = state_error;
-                       }
-                       break;
-               case state_error:
-               default:
-                       return -EINVAL;
-               }
-       }
-       if (state == state_error)
-               return -EINVAL;
-       return 0;
-}
-
-static void
-setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
-{
-       int i;
-
-       for (i = 0; i < 256; ++i)
-               table[i] = forbidden_command;
-
-       for (i = 0; i < size; ++i)
-               table[init_table[i].code] = init_table[i].hz;
-}
-
-void via_init_command_verifier(void)
-{
-       setup_hazard_table(init_table1, table1, ARRAY_SIZE(init_table1));
-       setup_hazard_table(init_table2, table2, ARRAY_SIZE(init_table2));
-       setup_hazard_table(init_table3, table3, ARRAY_SIZE(init_table3));
-}
diff --git a/drivers/gpu/drm/via/via_verifier.h b/drivers/gpu/drm/via/via_verifier.h
deleted file mode 100644 (file)
index 26b6d36..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2004 The Unichrome Project. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellström 2004.
- */
-
-#ifndef _VIA_VERIFIER_H_
-#define _VIA_VERIFIER_H_
-
-typedef enum {
-       no_sequence = 0,
-       z_address,
-       dest_address,
-       tex_address
-} drm_via_sequence_t;
-
-typedef struct {
-       unsigned texture;
-       uint32_t z_addr;
-       uint32_t d_addr;
-       uint32_t t_addr[2][10];
-       uint32_t pitch[2][10];
-       uint32_t height[2][10];
-       uint32_t tex_level_lo[2];
-       uint32_t tex_level_hi[2];
-       uint32_t tex_palette_size[2];
-       uint32_t tex_npot[2];
-       drm_via_sequence_t unfinished;
-       int agp_texture;
-       int multitex;
-       struct drm_device *dev;
-       drm_local_map_t *map_cache;
-       uint32_t vertex_count;
-       int agp;
-       const uint32_t *buf_start;
-} drm_via_state_t;
-
-extern int via_verify_command_stream(const uint32_t *buf, unsigned int size,
-                                    struct drm_device *dev, int agp);
-extern int via_parse_command_stream(struct drm_device *dev, const uint32_t *buf,
-                                   unsigned int size);
-
-#endif
diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c
deleted file mode 100644 (file)
index 53b1f58..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Thomas Hellstrom 2005.
- *
- * Video and XvMC related functions.
- */
-
-#include <drm/drm_device.h>
-#include <drm/via_drm.h>
-
-#include "via_drv.h"
-
-void via_init_futex(drm_via_private_t *dev_priv)
-{
-       unsigned int i;
-
-       DRM_DEBUG("\n");
-
-       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               init_waitqueue_head(&(dev_priv->decoder_queue[i]));
-               XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
-       }
-}
-
-void via_cleanup_futex(drm_via_private_t *dev_priv)
-{
-}
-
-void via_release_futex(drm_via_private_t *dev_priv, int context)
-{
-       unsigned int i;
-       volatile int *lock;
-
-       if (!dev_priv->sarea_priv)
-               return;
-
-       for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
-               lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i);
-               if ((_DRM_LOCKING_CONTEXT(*lock) == context)) {
-                       if (_DRM_LOCK_IS_HELD(*lock)
-                           && (*lock & _DRM_LOCK_CONT)) {
-                               wake_up(&(dev_priv->decoder_queue[i]));
-                       }
-                       *lock = 0;
-               }
-       }
-}
-
-int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv)
-{
-       drm_via_futex_t *fx = data;
-       volatile int *lock;
-       drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
-       drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
-       int ret = 0;
-
-       DRM_DEBUG("\n");
-
-       if (fx->lock >= VIA_NR_XVMC_LOCKS)
-               return -EFAULT;
-
-       lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock);
-
-       switch (fx->func) {
-       case VIA_FUTEX_WAIT:
-               VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock],
-                           (fx->ms / 10) * (HZ / 100), *lock != fx->val);
-               return ret;
-       case VIA_FUTEX_WAKE:
-               wake_up(&(dev_priv->decoder_queue[fx->lock]));
-               return 0;
-       }
-       return 0;
-}
index 5f25a8d15464ce91574bf4f78cdd173e41d4f8e0..0035affc3e590f1f10dc2e6574acaeeaed311dad 100644 (file)
@@ -46,12 +46,11 @@ static int virtio_gpu_modeset = -1;
 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
 module_param_named(modeset, virtio_gpu_modeset, int, 0400);
 
-static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vdev)
+static int virtio_gpu_pci_quirk(struct drm_device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
        const char *pname = dev_name(&pdev->dev);
        bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
-       char unique[20];
        int ret;
 
        DRM_INFO("pci: %s detected at %s\n",
@@ -63,39 +62,7 @@ static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vd
                        return ret;
        }
 
-       /*
-        * Normally the drm_dev_set_unique() call is done by core DRM.
-        * The following comment covers, why virtio cannot rely on it.
-        *
-        * Unlike the other virtual GPU drivers, virtio abstracts the
-        * underlying bus type by using struct virtio_device.
-        *
-        * Hence the dev_is_pci() check, used in core DRM, will fail
-        * and the unique returned will be the virtio_device "virtio0",
-        * while a "pci:..." one is required.
-        *
-        * A few other ideas were considered:
-        * - Extend the dev_is_pci() check [in drm_set_busid] to
-        *   consider virtio.
-        *   Seems like a bigger hack than what we have already.
-        *
-        * - Point drm_device::dev to the parent of the virtio_device
-        *   Semantic changes:
-        *   * Using the wrong device for i2c, framebuffer_alloc and
-        *     prime import.
-        *   Visual changes:
-        *   * Helpers such as DRM_DEV_ERROR, dev_info, drm_printer,
-        *     will print the wrong information.
-        *
-        * We could address the latter issues, by introducing
-        * drm_device::bus_dev, ... which would be used solely for this.
-        *
-        * So for the moment keep things as-is, with a bulky comment
-        * for the next person who feels like removing this
-        * drm_dev_set_unique() quirk.
-        */
-       snprintf(unique, sizeof(unique), "pci:%s", pname);
-       return drm_dev_set_unique(dev, unique);
+       return 0;
 }
 
 static int virtio_gpu_probe(struct virtio_device *vdev)
@@ -109,18 +76,24 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
        if (virtio_gpu_modeset == 0)
                return -EINVAL;
 
-       dev = drm_dev_alloc(&driver, &vdev->dev);
+       /*
+        * The virtio-gpu device is a virtual device that doesn't have DMA
+        * ops assigned to it, nor DMA mask set and etc. Its parent device
+        * is actual GPU device we want to use it for the DRM's device in
+        * order to benefit from using generic DRM APIs.
+        */
+       dev = drm_dev_alloc(&driver, vdev->dev.parent);
        if (IS_ERR(dev))
                return PTR_ERR(dev);
        vdev->priv = dev;
 
-       if (!strcmp(vdev->dev.parent->bus->name, "pci")) {
-               ret = virtio_gpu_pci_quirk(dev, vdev);
+       if (dev_is_pci(vdev->dev.parent)) {
+               ret = virtio_gpu_pci_quirk(dev);
                if (ret)
                        goto err_free;
        }
 
-       ret = virtio_gpu_init(dev);
+       ret = virtio_gpu_init(vdev, dev);
        if (ret)
                goto err_free;
 
index f80664cf98d0d6ab311d55a0d1c731af50127b4d..9b98470593b0607324dca739f994fa4ca04bb158 100644 (file)
@@ -101,8 +101,6 @@ struct virtio_gpu_object {
 
 struct virtio_gpu_object_shmem {
        struct virtio_gpu_object base;
-       struct sg_table *pages;
-       uint32_t mapped;
 };
 
 struct virtio_gpu_object_vram {
@@ -215,7 +213,6 @@ struct virtio_gpu_drv_cap_cache {
 };
 
 struct virtio_gpu_device {
-       struct device *dev;
        struct drm_device *ddev;
 
        struct virtio_device *vdev;
@@ -283,7 +280,7 @@ extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file);
 
 /* virtgpu_kms.c */
-int virtio_gpu_init(struct drm_device *dev);
+int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev);
 void virtio_gpu_deinit(struct drm_device *dev);
 void virtio_gpu_release(struct drm_device *dev);
 int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file);
index 580a788098361faeb0ac17cbfdbfbc35a22cb7a0..7db48d17ee3a8a9c638a8c6f9e58f35bd004b453 100644 (file)
@@ -228,8 +228,10 @@ int virtio_gpu_array_lock_resv(struct virtio_gpu_object_array *objs)
 
        for (i = 0; i < objs->nents; ++i) {
                ret = dma_resv_reserve_fences(objs->objs[i]->resv, 1);
-               if (ret)
+               if (ret) {
+                       virtio_gpu_array_unlock_resv(objs);
                        return ret;
+               }
        }
        return ret;
 }
index 3313b92db53190cb640ea5660b3b6975ddf77ce7..27b7f14dae89a167d5cdc824888eb0c1caeab14b 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/virtio_ring.h>
 
 #include <drm/drm_file.h>
+#include <drm/drm_managed.h>
 
 #include "virtgpu_drv.h"
 
@@ -66,10 +67,11 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
 {
        int i, ret;
        bool invalid_capset_id = false;
+       struct drm_device *drm = vgdev->ddev;
 
-       vgdev->capsets = kcalloc(num_capsets,
-                                sizeof(struct virtio_gpu_drv_capset),
-                                GFP_KERNEL);
+       vgdev->capsets = drmm_kcalloc(drm, num_capsets,
+                                     sizeof(struct virtio_gpu_drv_capset),
+                                     GFP_KERNEL);
        if (!vgdev->capsets) {
                DRM_ERROR("failed to allocate cap sets\n");
                return;
@@ -94,7 +96,7 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
 
                if (ret == 0 || invalid_capset_id) {
                        spin_lock(&vgdev->display_info_lock);
-                       kfree(vgdev->capsets);
+                       drmm_kfree(drm, vgdev->capsets);
                        vgdev->capsets = NULL;
                        spin_unlock(&vgdev->display_info_lock);
                        return;
@@ -110,7 +112,7 @@ static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
        vgdev->num_capsets = num_capsets;
 }
 
-int virtio_gpu_init(struct drm_device *dev)
+int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
 {
        static vq_callback_t *callbacks[] = {
                virtio_gpu_ctrl_ack, virtio_gpu_cursor_ack
@@ -123,17 +125,16 @@ int virtio_gpu_init(struct drm_device *dev)
        u32 num_scanouts, num_capsets;
        int ret = 0;
 
-       if (!virtio_has_feature(dev_to_virtio(dev->dev), VIRTIO_F_VERSION_1))
+       if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
                return -ENODEV;
 
-       vgdev = kzalloc(sizeof(struct virtio_gpu_device), GFP_KERNEL);
+       vgdev = drmm_kzalloc(dev, sizeof(struct virtio_gpu_device), GFP_KERNEL);
        if (!vgdev)
                return -ENOMEM;
 
        vgdev->ddev = dev;
        dev->dev_private = vgdev;
-       vgdev->vdev = dev_to_virtio(dev->dev);
-       vgdev->dev = dev->dev;
+       vgdev->vdev = vdev;
 
        spin_lock_init(&vgdev->display_info_lock);
        spin_lock_init(&vgdev->resource_export_lock);
@@ -257,7 +258,6 @@ err_vbufs:
        vgdev->vdev->config->del_vqs(vgdev->vdev);
 err_vqs:
        dev->dev_private = NULL;
-       kfree(vgdev);
        return ret;
 }
 
@@ -296,9 +296,6 @@ void virtio_gpu_release(struct drm_device *dev)
 
        if (vgdev->has_host_visible)
                drm_mm_takedown(&vgdev->host_visible_mm);
-
-       kfree(vgdev->capsets);
-       kfree(vgdev);
 }
 
 int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
index 1cc8f3fc8e4ba2951c093f813fab4bdf02aeae7d..8d7728181de0167d2fc5df344af4e0f154f9aec8 100644 (file)
@@ -67,21 +67,6 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
 
        virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
        if (virtio_gpu_is_shmem(bo)) {
-               struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
-
-               if (shmem->pages) {
-                       if (shmem->mapped) {
-                               dma_unmap_sgtable(vgdev->vdev->dev.parent,
-                                            shmem->pages, DMA_TO_DEVICE, 0);
-                               shmem->mapped = 0;
-                       }
-
-                       sg_free_table(shmem->pages);
-                       kfree(shmem->pages);
-                       shmem->pages = NULL;
-                       drm_gem_shmem_unpin(&bo->base);
-               }
-
                drm_gem_shmem_free(&bo->base);
        } else if (virtio_gpu_is_vram(bo)) {
                struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
@@ -153,35 +138,18 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
                                        unsigned int *nents)
 {
        bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
-       struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
        struct scatterlist *sg;
-       int si, ret;
+       struct sg_table *pages;
+       int si;
 
-       ret = drm_gem_shmem_pin(&bo->base);
-       if (ret < 0)
-               return -EINVAL;
-
-       /*
-        * virtio_gpu uses drm_gem_shmem_get_sg_table instead of
-        * drm_gem_shmem_get_pages_sgt because virtio has it's own set of
-        * dma-ops. This is discouraged for other drivers, but should be fine
-        * since virtio_gpu doesn't support dma-buf import from other devices.
-        */
-       shmem->pages = drm_gem_shmem_get_sg_table(&bo->base);
-       if (IS_ERR(shmem->pages)) {
-               drm_gem_shmem_unpin(&bo->base);
-               return PTR_ERR(shmem->pages);
-       }
+       pages = drm_gem_shmem_get_pages_sgt(&bo->base);
+       if (IS_ERR(pages))
+               return PTR_ERR(pages);
 
-       if (use_dma_api) {
-               ret = dma_map_sgtable(vgdev->vdev->dev.parent,
-                                     shmem->pages, DMA_TO_DEVICE, 0);
-               if (ret)
-                       return ret;
-               *nents = shmem->mapped = shmem->pages->nents;
-       } else {
-               *nents = shmem->pages->orig_nents;
-       }
+       if (use_dma_api)
+               *nents = pages->nents;
+       else
+               *nents = pages->orig_nents;
 
        *ents = kvmalloc_array(*nents,
                               sizeof(struct virtio_gpu_mem_entry),
@@ -192,13 +160,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev,
        }
 
        if (use_dma_api) {
-               for_each_sgtable_dma_sg(shmem->pages, sg, si) {
+               for_each_sgtable_dma_sg(pages, sg, si) {
                        (*ents)[si].addr = cpu_to_le64(sg_dma_address(sg));
                        (*ents)[si].length = cpu_to_le32(sg_dma_len(sg));
                        (*ents)[si].padding = 0;
                }
        } else {
-               for_each_sgtable_sg(shmem->pages, sg, si) {
+               for_each_sgtable_sg(pages, sg, si) {
                        (*ents)[si].addr = cpu_to_le64(sg_phys(sg));
                        (*ents)[si].length = cpu_to_le32(sg->length);
                        (*ents)[si].padding = 0;
@@ -234,6 +202,10 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
 
        bo->dumb = params->dumb;
 
+       ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents);
+       if (ret != 0)
+               goto err_put_id;
+
        if (fence) {
                ret = -ENOMEM;
                objs = virtio_gpu_array_alloc(1);
@@ -246,13 +218,6 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
                        goto err_put_objs;
        }
 
-       ret = virtio_gpu_object_shmem_init(vgdev, bo, &ents, &nents);
-       if (ret != 0) {
-               virtio_gpu_array_put_free(objs);
-               virtio_gpu_free_object(&shmem_obj->base);
-               return ret;
-       }
-
        if (params->blob) {
                if (params->blob_mem == VIRTGPU_BLOB_MEM_GUEST)
                        bo->guest_blob = true;
index 6d3cc9e238a4ad2348215933190a293d819a617e..4c09e313bebcd8e7d89c843a571b9b7096bde150 100644 (file)
@@ -26,7 +26,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 
 #include "virtgpu_drv.h"
 
@@ -67,16 +66,9 @@ uint32_t virtio_gpu_translate_format(uint32_t drm_fourcc)
        return format;
 }
 
-static void virtio_gpu_plane_destroy(struct drm_plane *plane)
-{
-       drm_plane_cleanup(plane);
-       kfree(plane);
-}
-
 static const struct drm_plane_funcs virtio_gpu_plane_funcs = {
        .update_plane           = drm_atomic_helper_update_plane,
        .disable_plane          = drm_atomic_helper_disable_plane,
-       .destroy                = virtio_gpu_plane_destroy,
        .reset                  = drm_atomic_helper_plane_reset,
        .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
        .atomic_destroy_state   = drm_atomic_helper_plane_destroy_state,
@@ -100,8 +92,8 @@ static int virtio_gpu_plane_atomic_check(struct drm_plane *plane,
                 return PTR_ERR(crtc_state);
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  is_cursor, true);
        return ret;
 }
@@ -266,14 +258,14 @@ static int virtio_gpu_plane_prepare_fb(struct drm_plane *plane,
 }
 
 static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane,
-                                       struct drm_plane_state *old_state)
+                                       struct drm_plane_state *state)
 {
        struct virtio_gpu_framebuffer *vgfb;
 
-       if (!plane->state->fb)
+       if (!state->fb)
                return;
 
-       vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
+       vgfb = to_virtio_gpu_framebuffer(state->fb);
        if (vgfb->fence) {
                dma_fence_put(&vgfb->fence->f);
                vgfb->fence = NULL;
@@ -379,11 +371,7 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
        const struct drm_plane_helper_funcs *funcs;
        struct drm_plane *plane;
        const uint32_t *formats;
-       int ret, nformats;
-
-       plane = kzalloc(sizeof(*plane), GFP_KERNEL);
-       if (!plane)
-               return ERR_PTR(-ENOMEM);
+       int nformats;
 
        if (type == DRM_PLANE_TYPE_CURSOR) {
                formats = virtio_gpu_cursor_formats;
@@ -394,17 +382,13 @@ struct drm_plane *virtio_gpu_plane_init(struct virtio_gpu_device *vgdev,
                nformats = ARRAY_SIZE(virtio_gpu_formats);
                funcs = &virtio_gpu_primary_helper_funcs;
        }
-       ret = drm_universal_plane_init(dev, plane, 1 << index,
-                                      &virtio_gpu_plane_funcs,
-                                      formats, nformats,
-                                      NULL, type, NULL);
-       if (ret)
-               goto err_plane_init;
+
+       plane = drmm_universal_plane_alloc(dev, struct drm_plane, dev,
+                                          1 << index, &virtio_gpu_plane_funcs,
+                                          formats, nformats, NULL, type, NULL);
+       if (IS_ERR(plane))
+               return plane;
 
        drm_plane_helper_add(plane, funcs);
        return plane;
-
-err_plane_init:
-       kfree(plane);
-       return ERR_PTR(ret);
 }
index b7529b2b9883260bf93ab5cb4f7777d06079e288..9ff8660b50ade507e9d357c10ecdf61d10cfbede 100644 (file)
@@ -322,7 +322,7 @@ static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev,
                if (fence && vbuf->objs)
                        virtio_gpu_array_unlock_resv(vbuf->objs);
                free_vbuf(vgdev, vbuf);
-               return -1;
+               return -ENODEV;
        }
 
        if (vgdev->has_indirect)
@@ -386,7 +386,7 @@ static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
                        if (!sgt) {
                                if (fence && vbuf->objs)
                                        virtio_gpu_array_unlock_resv(vbuf->objs);
-                               return -1;
+                               return -ENOMEM;
                        }
 
                        elemcnt += sg_ents;
@@ -595,11 +595,10 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
        struct virtio_gpu_transfer_to_host_2d *cmd_p;
        struct virtio_gpu_vbuffer *vbuf;
        bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
-       struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
 
-       if (use_dma_api)
-               dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
-                                           shmem->pages, DMA_TO_DEVICE);
+       if (virtio_gpu_is_shmem(bo) && use_dma_api)
+               dma_sync_sgtable_for_device(&vgdev->vdev->dev,
+                                           bo->base.sgt, DMA_TO_DEVICE);
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
@@ -721,7 +720,7 @@ static int virtio_get_edid_block(void *data, u8 *buf,
        size_t start = block * EDID_LENGTH;
 
        if (start + len > le32_to_cpu(resp->size))
-               return -1;
+               return -EINVAL;
        memcpy(buf, resp->edid + start, len);
        return 0;
 }
@@ -1019,11 +1018,9 @@ void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
        struct virtio_gpu_vbuffer *vbuf;
        bool use_dma_api = !virtio_has_dma_quirk(vgdev->vdev);
 
-       if (virtio_gpu_is_shmem(bo) && use_dma_api) {
-               struct virtio_gpu_object_shmem *shmem = to_virtio_gpu_shmem(bo);
-               dma_sync_sgtable_for_device(vgdev->vdev->dev.parent,
-                                           shmem->pages, DMA_TO_DEVICE);
-       }
+       if (virtio_gpu_is_shmem(bo) && use_dma_api)
+               dma_sync_sgtable_for_device(&vgdev->vdev->dev,
+                                           bo->base.sgt, DMA_TO_DEVICE);
 
        cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
        memset(cmd_p, 0, sizeof(*cmd_p));
index d8eb674b49a6c4815532cace06a1b741f3e60b3c..8a810bfa12642644e19b3aeb6b4f2b691cb15818 100644 (file)
@@ -7,7 +7,6 @@
 #include <drm/drm_fourcc.h>
 #include <drm/drm_gem_atomic_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_plane_helper.h>
 
 #include "vkms_drv.h"
 
@@ -139,8 +138,8 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
                can_position = true;
 
        ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  can_position, true);
        if (ret != 0)
                return ret;
index 1f6e3bbc660596bda3d036f9865bee24a5cf9285..f84376718086a7a435e3d5ab5fe2dff682d9d20d 100644 (file)
@@ -121,7 +121,7 @@ typedef __attribute__((aligned(32))) struct MKSGuestStatInfoEntry {
  *
  * Since the MKSGuestStatInfoEntry structures contain userlevel
  * pointers, the InstanceDescriptor also contains pointers to the
- * begining of these sections allowing the host side code to correctly
+ * beginning of these sections allowing the host side code to correctly
  * interpret the pointers.
  *
  * Because the host side code never acknowledges anything back to the
index 4c8700027c6de1e970f5fce08cef236ebc59eed6..1a2fa0f83f5f910779398b3cfefd93bb6f2bfcda 100644 (file)
@@ -96,7 +96,7 @@ struct ttm_object_device;
  *
  * This struct is intended to be used as a base struct for objects that
  * are visible to user-space. It provides a global name, race-safe
- * access and refcounting, minimal access contol and hooks for unref actions.
+ * access and refcounting, minimal access control and hooks for unref actions.
  */
 
 struct ttm_base_object {
@@ -138,7 +138,7 @@ struct ttm_prime_object {
  *
  * @tfile: Pointer to a struct ttm_object_file.
  * @base: The struct ttm_base_object to initialize.
- * @shareable: This object is shareable with other applcations.
+ * @shareable: This object is shareable with other applications.
  * (different @tfile pointers.)
  * @type: The object type.
  * @refcount_release: See the struct ttm_base_object description.
index 85a66014c2b6ca2f4354024cf0e674f8d1b4811d..822251aaab0a14235d45e7cb4f718b06df644a59 100644 (file)
@@ -429,9 +429,9 @@ int vmw_bo_create_kernel(struct vmw_private *dev_priv, unsigned long size,
 
        drm_gem_private_object_init(vdev, &bo->base, size);
 
-       ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, size,
-                                  ttm_bo_type_kernel, placement, 0,
-                                  &ctx, NULL, NULL, vmw_bo_default_destroy);
+       ret = ttm_bo_init_reserved(&dev_priv->bdev, bo, ttm_bo_type_kernel,
+                                  placement, 0, &ctx, NULL, NULL,
+                                  vmw_bo_default_destroy);
        if (unlikely(ret))
                goto error_free;
 
@@ -512,10 +512,8 @@ int vmw_bo_init(struct vmw_private *dev_priv,
        size = ALIGN(size, PAGE_SIZE);
        drm_gem_private_object_init(vdev, &vmw_bo->base.base, size);
 
-       ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, size,
-                                  ttm_bo_type_device,
-                                  placement,
-                                  0, &ctx, NULL, NULL, bo_free);
+       ret = ttm_bo_init_reserved(bdev, &vmw_bo->base, ttm_bo_type_device,
+                                  placement, 0, &ctx, NULL, NULL, bo_free);
        if (unlikely(ret)) {
                return ret;
        }
@@ -729,7 +727,7 @@ int vmw_user_bo_lookup(struct drm_file *filp,
  * Any persistent usage of the object requires a refcount to be taken using
  * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
  * needs to be paired with vmw_user_bo_noref_release() and no sleeping-
- * or scheduling functions may be called inbetween these function calls.
+ * or scheduling functions may be called in between these function calls.
  *
  * Return: A struct vmw_buffer_object pointer if successful or negative
  * error pointer on failure.
index 415774fde7963206177895a148707088e7e64337..82ef58ccdd428af689c332e89144bbd39a8a0180 100644 (file)
@@ -36,7 +36,7 @@
  * @res: Refcounted pointer to a struct vmw_resource.
  * @hash: Hash entry for the manager hash table.
  * @head: List head used either by the staging list or the manager list
- * of commited resources.
+ * of committed resources.
  * @state: Staging state of this resource entry.
  * @man: Pointer to a resource manager for this entry.
  */
@@ -51,9 +51,9 @@ struct vmw_cmdbuf_res {
 /**
  * struct vmw_cmdbuf_res_manager - Command buffer resource manager.
  *
- * @resources: Hash table containing staged and commited command buffer
+ * @resources: Hash table containing staged and committed command buffer
  * resources
- * @list: List of commited command buffer resources.
+ * @list: List of committed command buffer resources.
  * @dev_priv: Pointer to a device private structure.
  *
  * @resources and @list are protected by the cmdbuf mutex for now.
@@ -118,7 +118,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
  * This function commits a list of command buffer resource
  * additions or removals.
  * It is typically called when the execbuf ioctl call triggering these
- * actions has commited the fifo contents to the device.
+ * actions has committed the fifo contents to the device.
  */
 void vmw_cmdbuf_res_commit(struct list_head *list)
 {
index 01a5b47e95f9deb81b737bb924d0e40cbe39ff8e..d7bd5eb1d3acd993fa4c628e0a797bb64af82ec9 100644 (file)
@@ -1398,18 +1398,6 @@ static void vmw_debugfs_resource_managers_init(struct vmw_private *vmw)
                                            root, "system_mob_ttm");
 }
 
-static unsigned long
-vmw_get_unmapped_area(struct file *file, unsigned long uaddr,
-                     unsigned long len, unsigned long pgoff,
-                     unsigned long flags)
-{
-       struct drm_file *file_priv = file->private_data;
-       struct vmw_private *dev_priv = vmw_priv(file_priv->minor->dev);
-
-       return drm_get_unmapped_area(file, uaddr, len, pgoff, flags,
-                                    dev_priv->drm.vma_offset_manager);
-}
-
 static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
                              void *ptr)
 {
@@ -1576,7 +1564,6 @@ static const struct file_operations vmwgfx_driver_fops = {
        .compat_ioctl = vmw_compat_ioctl,
 #endif
        .llseek = noop_llseek,
-       .get_unmapped_area = vmw_get_unmapped_area,
 };
 
 static const struct drm_driver driver = {
index d49de4905efa485c8288b876e074a862e39f5326..f085dbd4736d5bdb127c2892121e32b8945066d7 100644 (file)
@@ -1172,7 +1172,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
 
        vmw_validation_preload_bo(sw_context->ctx);
        vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);
-       if (IS_ERR_OR_NULL(vmw_bo)) {
+       if (IS_ERR(vmw_bo)) {
                VMW_DEBUG_USER("Could not find or use MOB buffer.\n");
                return PTR_ERR(vmw_bo);
        }
@@ -1226,7 +1226,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
 
        vmw_validation_preload_bo(sw_context->ctx);
        vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);
-       if (IS_ERR_OR_NULL(vmw_bo)) {
+       if (IS_ERR(vmw_bo)) {
                VMW_DEBUG_USER("Could not find or use GMR region.\n");
                return PTR_ERR(vmw_bo);
        }
index ff2f735bbe7a08df1951e21759d56da8a8fa658f..214829c32ed87bd0a9e1c1335861fd0ed8065135 100644 (file)
@@ -29,7 +29,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_rect.h>
 #include <drm/drm_sysfs.h>
 #include <drm/drm_vblank.h>
@@ -720,8 +719,8 @@ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
                                                           new_state->crtc);
 
        ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  false, true);
 
        if (!ret && new_fb) {
@@ -762,8 +761,8 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
                                                           new_state->crtc);
 
        ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
-                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
+                                                 DRM_PLANE_NO_SCALING,
                                                  true, true);
        if (ret)
                return ret;
@@ -2257,7 +2256,7 @@ out_fini:
        drm_modeset_drop_locks(&ctx);
        drm_modeset_acquire_fini(&ctx);
        mutex_unlock(&dev->mode_config.mutex);
+
        return 0;
 }
 
index 7046dfd0d1c6187a9c3f6cbd815c8b5ae730fe8f..85f86faa324392bc196f7633387e326f84aba980 100644 (file)
@@ -70,7 +70,7 @@ struct vmw_du_update_plane {
         *
         * Some surface resource or buffer object need some extra cmd submission
         * like update GB image for proxy surface and define a GMRFB for screen
-        * object. That should should be done here as this callback will be
+        * object. That should be done here as this callback will be
         * called after FIFO allocation with the address of command buufer.
         *
         * This callback is optional.
index e4347faccee05959b9c35f275763957687f95096..b8761f16dd78509b81a3067479e1eef6a1da5bd2 100644 (file)
@@ -28,7 +28,6 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "vmwgfx_kms.h"
index a7d62a4eb47b152350d575e1f85a172de858d080..f66caa540e1460534b2d417d0dbab267577afffe 100644 (file)
@@ -525,7 +525,7 @@ void vmw_resource_unreserve(struct vmw_resource *res,
  *                             for a resource and in that case, allocate
  *                             one, reserve and validate it.
  *
- * @ticket:         The ww aqcquire context to use, or NULL if trylocking.
+ * @ticket:         The ww acquire context to use, or NULL if trylocking.
  * @res:            The resource for which to allocate a backup buffer.
  * @interruptible:  Whether any sleeps during allocation should be
  *                  performed while interruptible.
@@ -686,7 +686,7 @@ out_no_unbind:
  * @intr: Perform waits interruptible if possible.
  * @dirtying: Pending GPU operation will dirty the resource
  *
- * On succesful return, any backup DMA buffer pointed to by @res->backup will
+ * On successful return, any backup DMA buffer pointed to by @res->backup will
  * be reserved and validated.
  * On hardware resource shortage, this function will repeatedly evict
  * resources of the same type until the validation succeeds.
@@ -804,7 +804,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo)
  * @dx_query_mob: Buffer containing the DX query MOB
  *
  * Read back cached states from the device if they exist.  This function
- * assumings binding_mutex is held.
+ * assumes binding_mutex is held.
  */
 int vmw_query_readback_all(struct vmw_buffer_object *dx_query_mob)
 {
@@ -1125,7 +1125,7 @@ int vmw_resources_clean(struct vmw_buffer_object *vbo, pgoff_t start,
        }
 
        /*
-        * In order of increasing backup_offset, clean dirty resorces
+        * In order of increasing backup_offset, clean dirty resources
         * intersecting the range.
         */
        while (found) {
index c89ad3a2d141c77d716298e3fc8d5668b425702d..ecd3c2fc978b2362d9fbff20d22f0d1e8da032a8 100644 (file)
@@ -29,7 +29,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "vmwgfx_kms.h"
@@ -1383,6 +1382,6 @@ out_revert:
        vmw_validation_revert(&val_ctx);
 out_unref:
        vmw_validation_unref_lists(&val_ctx);
-       
+
        return ret;
 }
index 483ad544ea54f350d23a8df22d8f6c0101716473..0d51b45422699b429901f5b7581cbf4850ac7fa7 100644 (file)
@@ -196,7 +196,7 @@ out_ret:
  * type.
  *
  * Returns: Refcounted pointer to the embedded struct vmw_resource if
- * successfule. Error pointer otherwise.
+ * successful. Error pointer otherwise.
  */
 struct vmw_resource *
 vmw_simple_resource_lookup(struct ttm_object_file *tfile,
index eb014b97d156adfce25246cb9dce2a98190ed682..8650c3aea8f0a9bc6bdb3794826b74ba3d9719f8 100644 (file)
@@ -29,7 +29,6 @@
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_damage_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include "vmwgfx_kms.h"
index f9cf93c9e7e3022fe8464f673cf6f83fc69ade32..68ee897de9d758848fe1632d44a3fba566f97a13 100644 (file)
@@ -8,7 +8,7 @@ config DRM_ZYNQMP_DPSUB
        select DMA_ENGINE
        select DRM_DISPLAY_DP_HELPER
        select DRM_DISPLAY_HELPER
-       select DRM_GEM_CMA_HELPER
+       select DRM_GEM_DMA_HELPER
        select DRM_KMS_HELPER
        select GENERIC_PHY
        help
index cc32aa89cf8f74cf71a49693e4b80ec7f7863954..bbb365f2d0874f0fb156398c9cb48701e46a0975 100644 (file)
 #include <drm/drm_blend.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_device.h>
-#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_dma_helper.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_plane.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_vblank.h>
 
 #include <linux/clk.h>
@@ -1099,14 +1098,14 @@ static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
                unsigned int height = state->crtc_h / (i ? info->vsub : 1);
                struct zynqmp_disp_layer_dma *dma = &layer->dmas[i];
                struct dma_async_tx_descriptor *desc;
-               dma_addr_t paddr;
+               dma_addr_t dma_addr;
 
-               paddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
+               dma_addr = drm_fb_dma_get_gem_addr(state->fb, state, i);
 
                dma->xt.numf = height;
                dma->sgl.size = width * info->cpp[i];
                dma->sgl.icg = state->fb->pitches[i] - dma->sgl.size;
-               dma->xt.src_start = paddr;
+               dma->xt.src_start = dma_addr;
                dma->xt.frame_size = 1;
                dma->xt.dir = DMA_MEM_TO_DEV;
                dma->xt.src_sgl = true;
@@ -1151,8 +1150,8 @@ zynqmp_disp_plane_atomic_check(struct drm_plane *plane,
 
        return drm_atomic_helper_check_plane_state(new_plane_state,
                                                   crtc_state,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
-                                                  DRM_PLANE_HELPER_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
+                                                  DRM_PLANE_NO_SCALING,
                                                   false, false);
 }
 
index 824b510e337b7ea072a5b830a112747e3b18a2ad..1de2d927c32b07fc774b9e27575fcf28e3594791 100644 (file)
@@ -21,7 +21,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_fourcc.h>
-#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_dma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_managed.h>
 #include <drm/drm_mode_config.h>
@@ -47,7 +47,7 @@ static int zynqmp_dpsub_dumb_create(struct drm_file *file_priv,
        /* Enforce the alignment constraints of the DMA engine. */
        args->pitch = ALIGN(pitch, dpsub->dma_align);
 
-       return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
+       return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
 }
 
 static struct drm_framebuffer *
@@ -75,13 +75,13 @@ static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = {
  * DRM/KMS Driver
  */
 
-DEFINE_DRM_GEM_CMA_FOPS(zynqmp_dpsub_drm_fops);
+DEFINE_DRM_GEM_DMA_FOPS(zynqmp_dpsub_drm_fops);
 
 static const struct drm_driver zynqmp_dpsub_drm_driver = {
        .driver_features                = DRIVER_MODESET | DRIVER_GEM |
                                          DRIVER_ATOMIC,
 
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create),
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create),
 
        .fops                           = &zynqmp_dpsub_drm_fops,
 
index dbd1159a2ef0a468b7aced121a3f1df4aca98649..ce04c38f6afd0fba33565c31b23bfae4fd32f019 100644 (file)
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/aperture.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -987,22 +988,16 @@ release_fb:
 
 static int lynxfb_kick_out_firmware_fb(struct pci_dev *pdev)
 {
-       struct apertures_struct *ap;
+       resource_size_t base = pci_resource_start(pdev, 0);
+       resource_size_t size = pci_resource_len(pdev, 0);
        bool primary = false;
 
-       ap = alloc_apertures(1);
-       if (!ap)
-               return -ENOMEM;
-
-       ap->ranges[0].base = pci_resource_start(pdev, 0);
-       ap->ranges[0].size = pci_resource_len(pdev, 0);
 #ifdef CONFIG_X86
        primary = pdev->resource[PCI_ROM_RESOURCE].flags &
                                        IORESOURCE_ROM_SHADOW;
 #endif
-       remove_conflicting_framebuffers(ap, "sm750_fb1", primary);
-       kfree(ap);
-       return 0;
+
+       return aperture_remove_conflicting_devices(base, size, primary, "sm750_fb1");
 }
 
 static int lynxfb_pci_probe(struct pci_dev *pdev,
index 538f2d40acdacaadb41bfaae1e73a859e253b803..9e6bcc03a1a4a51121f49cca5c894d7dfc772bb0 100644 (file)
@@ -2,15 +2,17 @@
 
 #include <linux/aperture.h>
 #include <linux/device.h>
-#include <linux/fb.h> /* for old fbdev helpers */
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/sysfb.h>
 #include <linux/types.h>
 #include <linux/vgaarb.h>
 
+#include <video/vga.h>
+
 /**
  * DOC: overview
  *
@@ -283,26 +285,27 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size)
 int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size,
                                        bool primary, const char *name)
 {
-#if IS_REACHABLE(CONFIG_FB)
-       struct apertures_struct *a;
-       int ret;
-
-       a = alloc_apertures(1);
-       if (!a)
-               return -ENOMEM;
-
-       a->ranges[0].base = base;
-       a->ranges[0].size = size;
-
-       ret = remove_conflicting_framebuffers(a, name, primary);
-       kfree(a);
-
-       if (ret)
-               return ret;
-#endif
+       /*
+        * If a driver asked to unregister a platform device registered by
+        * sysfb, then can be assumed that this is a driver for a display
+        * that is set up by the system firmware and has a generic driver.
+        *
+        * Drivers for devices that don't have a generic driver will never
+        * ask for this, so let's assume that a real driver for the display
+        * was already probed and prevent sysfb to register devices later.
+        */
+       sysfb_disable();
 
        aperture_detach_devices(base, size);
 
+       /*
+        * If this is the primary adapter, there could be a VGA device
+        * that consumes the VGA framebuffer I/O range. Remove this device
+        * as well.
+        */
+       if (primary)
+               aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE);
+
        return 0;
 }
 EXPORT_SYMBOL(aperture_remove_conflicting_devices);
@@ -321,30 +324,36 @@ EXPORT_SYMBOL(aperture_remove_conflicting_devices);
  */
 int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name)
 {
+       bool primary = false;
        resource_size_t base, size;
        int bar, ret;
 
-       /*
-        * WARNING: Apparently we must kick fbdev drivers before vgacon,
-        * otherwise the vga fbdev driver falls over.
-        */
-#if IS_REACHABLE(CONFIG_FB)
-       ret = remove_conflicting_pci_framebuffers(pdev, name);
-       if (ret)
-               return ret;
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
 #endif
-       ret = vga_remove_vgacon(pdev);
-       if (ret)
-               return ret;
 
        for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) {
                if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
                        continue;
+
                base = pci_resource_start(pdev, bar);
                size = pci_resource_len(pdev, bar);
-               aperture_detach_devices(base, size);
+               ret = aperture_remove_conflicting_devices(base, size, primary, name);
+               if (ret)
+                       break;
        }
 
+       if (ret)
+               return ret;
+
+       /*
+        * WARNING: Apparently we must kick fbdev drivers before vgacon,
+        * otherwise the vga fbdev driver falls over.
+        */
+       ret = vga_remove_vgacon(pdev);
+       if (ret)
+               return ret;
+
        return 0;
 
 }
index a2a381631628efa28e97638da147b06455e58861..a317d9fe1d67de4864af27bc928126335e547e68 100644 (file)
@@ -11,6 +11,7 @@
  *  Code is based on s3fb
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -956,6 +957,10 @@ static int ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        int rc;
        u8 regval;
 
+       rc = aperture_remove_conflicting_pci_devices(dev, "arkfb");
+       if (rc < 0)
+               return rc;
+
        /* Ignore secondary VGA device because there is no VGA arbitration */
        if (! svga_primary_device(dev)) {
                dev_info(&(dev->dev), "ignoring secondary device\n");
index f8ef62542f7f590f73c52551f3fbf2248667b3e3..3818437a8f6917e8f17538d04c21270cdbd6aca5 100644 (file)
@@ -29,6 +29,7 @@
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -545,6 +546,10 @@ static int asiliantfb_pci_init(struct pci_dev *dp,
        struct fb_info *p;
        int err;
 
+       err = aperture_remove_conflicting_pci_devices(dp, "asiliantfb");
+       if (err)
+               return err;
+
        if ((dp->resource[0].flags & IORESOURCE_MEM) == 0)
                return -ENODEV;
        addr = pci_resource_start(dp, 0);
index b26c81233b6b7c4ff3a570435486cb4c353611fd..57e398fe7a81c2ab22d955705bd275f083463f6f 100644 (file)
@@ -23,7 +23,7 @@
  *                     - Convert to new framebuffer API,
  *                       fix colormap setting at 16 bits/pixel (565)
  *
- *               Paul Mundt 
+ *               Paul Mundt
  *                     - PCI hotplug
  *
  *               Jon Smirl <jonsmirl@yahoo.com>
@@ -47,6 +47,7 @@
  */
 
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -520,13 +521,13 @@ static const struct fb_ops aty128fb_ops = {
      * - endian conversions may possibly be avoided by
      *    using the other register aperture. TODO.
      */
-static inline u32 _aty_ld_le32(volatile unsigned int regindex, 
+static inline u32 _aty_ld_le32(volatile unsigned int regindex,
                               const struct aty128fb_par *par)
 {
        return readl (par->regbase + regindex);
 }
 
-static inline void _aty_st_le32(volatile unsigned int regindex, u32 val, 
+static inline void _aty_st_le32(volatile unsigned int regindex, u32 val,
                                const struct aty128fb_par *par)
 {
        writel (val, par->regbase + regindex);
@@ -559,12 +560,12 @@ static inline void _aty_st_8(unsigned int regindex, u8 val,
 
 static u32 _aty_ld_pll(unsigned int pll_index,
                       const struct aty128fb_par *par)
-{       
+{
        aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x3F);
        return aty_ld_le32(CLOCK_CNTL_DATA);
 }
 
-    
+
 static void _aty_st_pll(unsigned int pll_index, u32 val,
                        const struct aty128fb_par *par)
 {
@@ -619,7 +620,7 @@ static int register_test(const struct aty128fb_par *par)
                aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
 
                if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
-                       flag = 1; 
+                       flag = 1;
        }
 
        aty_st_le32(BIOS_0_SCRATCH, val);       // restore value
@@ -901,7 +902,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par,
 
        bios_hdr = BIOS_IN16(0x48);
        bios_pll = BIOS_IN16(bios_hdr + 0x30);
-       
+
        par->constants.ppll_max = BIOS_IN32(bios_pll + 0x16);
        par->constants.ppll_min = BIOS_IN32(bios_pll + 0x12);
        par->constants.xclk = BIOS_IN16(bios_pll + 0x08);
@@ -913,7 +914,7 @@ static void aty128_get_pllinfo(struct aty128fb_par *par,
                        par->constants.xclk, par->constants.ref_divider,
                        par->constants.ref_clk);
 
-}           
+}
 
 #ifdef CONFIG_X86
 static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
@@ -925,7 +926,7 @@ static void __iomem *aty128_find_mem_vbios(struct aty128fb_par *par)
         */
         u32  segstart;
         unsigned char __iomem *rom_base = NULL;
-                                                
+
         for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
                 rom_base = ioremap(segstart, 0x10000);
                if (rom_base == NULL)
@@ -1118,12 +1119,12 @@ static int aty128_var_to_crtc(const struct fb_var_screeninfo *var,
                v_sync_wid = 1;
        else if (v_sync_wid > 0x1f)        /* 0x1f = max vwidth */
                v_sync_wid = 0x1f;
-    
+
        v_sync_strt = v_disp + lower;
 
        h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
        v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-    
+
        c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
 
        crtc->gen_cntl = 0x3000000L | c_sync | (dst << 8);
@@ -1301,11 +1302,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
                aty_st_le32(LVDS_GEN_CNTL, reg);
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
                aty128_bl_set_power(info, FB_BLANK_UNBLANK);
-#endif 
+#endif
        } else {
 #ifdef CONFIG_FB_ATY128_BACKLIGHT
                aty128_bl_set_power(info, FB_BLANK_POWERDOWN);
-#endif 
+#endif
                reg = aty_ld_le32(LVDS_GEN_CNTL);
                reg |= LVDS_DISPLAY_DIS;
                aty_st_le32(LVDS_GEN_CNTL, reg);
@@ -1481,7 +1482,7 @@ static int aty128_ddafifo(struct aty128_ddafifo *dsp,
  * This actually sets the video mode.
  */
 static int aty128fb_set_par(struct fb_info *info)
-{ 
+{
        struct aty128fb_par *par = info->par;
        u32 config;
        int err;
@@ -1595,7 +1596,7 @@ static int aty128_encode_var(struct fb_var_screeninfo *var,
        var->accel_flags = par->accel_flags;
 
        return 0;
-}           
+}
 
 
 static int aty128fb_check_var(struct fb_var_screeninfo *var,
@@ -1979,12 +1980,12 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
                        /* PowerBook Titanium */
                        if (of_machine_is_compatible("PowerBook3,2"))
                                default_vmode = VMODE_1152_768_60;
-       
-                       if (default_cmode > 16) 
+
+                       if (default_cmode > 16)
                                default_cmode = CMODE_32;
-                       else if (default_cmode > 8) 
+                       else if (default_cmode > 8)
                                default_cmode = CMODE_16;
-                       else 
+                       else
                                default_cmode = CMODE_8;
 
                        if (mac_vmode_to_var(default_vmode, default_cmode, &var))
@@ -1994,7 +1995,7 @@ static int aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif /* CONFIG_PPC_PMAC */
        {
                if (mode_option)
-                       if (fb_find_mode(&var, info, mode_option, NULL, 
+                       if (fb_find_mode(&var, info, mode_option, NULL,
                                         0, &defaultmode, 8) == 0)
                                var = default_var;
        }
@@ -2055,6 +2056,10 @@ static int aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *bios = NULL;
 #endif
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "aty128fb");
+       if (err)
+               return err;
+
        /* Enable device in PCI config */
        if ((err = pci_enable_device(pdev))) {
                printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
@@ -2301,7 +2306,7 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
        struct aty128fb_par *par = info->par;
        u32 value;
        int rc;
-    
+
        switch (cmd) {
        case FBIO_ATY128_SET_MIRROR:
                if (par->chip_gen != rage_M3)
@@ -2313,8 +2318,8 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
                par->crt_on = (value & 0x02) != 0;
                if (!par->crt_on && !par->lcd_on)
                        par->lcd_on = 1;
-               aty128_set_crt_enable(par, par->crt_on);        
-               aty128_set_lcd_enable(par, par->lcd_on);        
+               aty128_set_crt_enable(par, par->crt_on);
+               aty128_set_lcd_enable(par, par->lcd_on);
                return 0;
        case FBIO_ATY128_GET_MIRROR:
                if (par->chip_gen != rage_M3)
@@ -2331,7 +2336,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
 
        if (!par->pdev->pm_cap)
                return;
-               
+
        /* Set the chip into the appropriate suspend mode (we use D2,
         * D3 would require a complete re-initialisation of the chip,
         * including PCI config registers, clocks, AGP configuration, ...)
@@ -2376,12 +2381,12 @@ static int aty128_pci_suspend_late(struct device *dev, pm_message_t state)
         */
        return 0;
 #endif /* CONFIG_PPC_PMAC */
-        
+
        if (state.event == pdev->dev.power.power_state.event)
                return 0;
 
        printk(KERN_DEBUG "aty128fb: suspending...\n");
-       
+
        console_lock();
 
        fb_set_suspend(info, 1);
index a3e6faed7745a4b2c5ab877b152ecce97a777091..4804b6e9f3f4873c4dd2dd1b9d892e95aad64964 100644 (file)
@@ -48,6 +48,7 @@
 
 ******************************************************************************/
 
+#include <linux/aperture.h>
 #include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
@@ -3533,7 +3534,11 @@ static int atyfb_pci_probe(struct pci_dev *pdev,
        struct fb_info *info;
        struct resource *rp;
        struct atyfb_par *par;
-       int rc = -ENOMEM;
+       int rc;
+
+       rc = aperture_remove_conflicting_pci_devices(pdev, "atyfb");
+       if (rc)
+               return rc;
 
        /* Enable device in PCI config */
        if (pci_enable_device(pdev)) {
index 6851f47613e17e52e950ad0fd551d8d8b540a5b8..0a8199985d52faaf1b452934e7b3593551eaa128 100644 (file)
@@ -7,7 +7,7 @@
  *     Copyright 2000  Ani Joshi <ajoshi@kernel.crashing.org>
  *
  *     i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net>
- *     
+ *
  *     Special thanks to ATI DevRel team for their hardware donations.
  *
  *     ...Insert GPL boilerplate here...
@@ -54,6 +54,7 @@
 
 #include "radeonfb.h"
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -110,7 +111,7 @@ static const struct pci_device_id radeonfb_pci_table[] = {
        /* Radeon IGP320M (U1) */
        CHIP_DEF(PCI_CHIP_RS100_4336,   RS100,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
        /* Radeon IGP320 (A3) */
-       CHIP_DEF(PCI_CHIP_RS100_4136,   RS100,  CHIP_HAS_CRTC2 | CHIP_IS_IGP), 
+       CHIP_DEF(PCI_CHIP_RS100_4136,   RS100,  CHIP_HAS_CRTC2 | CHIP_IS_IGP),
        /* IGP330M/340M/350M (U2) */
        CHIP_DEF(PCI_CHIP_RS200_4337,   RS200,  CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY),
        /* IGP330/340/350 (A4) */
@@ -240,7 +241,7 @@ typedef struct {
  * interfere with anything
  */
 static reg_val common_regs[] = {
-       { OVR_CLR, 0 }, 
+       { OVR_CLR, 0 },
        { OVR_WID_LEFT_RIGHT, 0 },
        { OVR_WID_TOP_BOTTOM, 0 },
        { OV0_SCALE_CNTL, 0 },
@@ -255,7 +256,7 @@ static reg_val common_regs[] = {
 /*
  * globals
  */
-        
+
 static char *mode_option;
 static char *monitor_layout;
 static bool noaccel = 0;
@@ -422,7 +423,7 @@ static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
         * ROM somewhere in the first meg. We will just ignore the copy
         * and use the ROM directly.
         */
-    
+
        /* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */
        unsigned int temp;
        temp = INREG(MPP_TB_CONFIG);
@@ -430,14 +431,14 @@ static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
        temp |= 0x04 << 24;
        OUTREG(MPP_TB_CONFIG, temp);
        temp = INREG(MPP_TB_CONFIG);
-                                                                                                          
+
        rom = pci_map_rom(dev, &rom_size);
        if (!rom) {
                printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
                       pci_name(rinfo->pdev));
                return -ENOMEM;
        }
-       
+
        rinfo->bios_seg = rom;
 
        /* Very simple test to make sure it appeared */
@@ -515,7 +516,7 @@ static int  radeon_find_mem_vbios(struct radeonfb_info *rinfo)
         */
         u32  segstart;
        void __iomem *rom_base = NULL;
-                                                
+
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
                 rom_base = ioremap(segstart, 0x10000);
                if (rom_base == NULL)
@@ -605,16 +606,16 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
        for(i=0; i<1000000; i++)
                if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0)
                        break;
-       
+
        stop_time = ktime_get();
-       
+
        local_irq_enable();
 
        total_usecs = ktime_us_delta(stop_time, start_time);
        if (total_usecs >= 10 * USEC_PER_SEC || total_usecs == 0)
                return -1;
        hz = USEC_PER_SEC/(u32)total_usecs;
+
        hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8;
        vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1);
        vclk = (long long)hTotal * (long long)vTotal * hz;
@@ -662,7 +663,7 @@ static int radeon_probe_pll_params(struct radeonfb_info *rinfo)
                denom *= 3;
                break;
        case 6:
-               denom *= 6;   
+               denom *= 6;
                break;
        case 7:
                denom *= 12;
@@ -878,7 +879,7 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
                         v.green.length = 6;
                         v.blue.length = 5;
                         v.transp.offset = v.transp.length = 0;
-                        break;                          
+                        break;
                 case 24:
                         nom = 4;
                         den = 1;
@@ -908,7 +909,7 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
                v.yres_virtual = v.yres;
        if (v.xres_virtual < v.xres)
                v.xres_virtual = v.xres;
-                
+
 
        /* XXX I'm adjusting xres_virtual to the pitch, that may help XFree
         * with some panels, though I don't quite like this solution
@@ -929,14 +930,14 @@ static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *in
 
         if (v.xoffset > v.xres_virtual - v.xres)
                 v.xoffset = v.xres_virtual - v.xres - 1;
-                        
+
         if (v.yoffset > v.yres_virtual - v.yres)
                 v.yoffset = v.yres_virtual - v.yres - 1;
-         
+
         v.red.msb_right = v.green.msb_right = v.blue.msb_right =
                           v.transp.offset = v.transp.length =
                           v.transp.msb_right = 0;
-       
+
         memcpy(var, &v, sizeof(v));
 
         return 0;
@@ -951,7 +952,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var,
        if ((var->xoffset + info->var.xres > info->var.xres_virtual)
            || (var->yoffset + info->var.yres > info->var.yres_virtual))
                return -EINVAL;
-                
+
         if (rinfo->asleep)
                return 0;
 
@@ -1151,7 +1152,7 @@ static int radeonfb_blank (int blank, struct fb_info *info)
 
        if (rinfo->asleep)
                return 0;
-               
+
        return radeon_screen_blank(rinfo, blank, 0);
 }
 
@@ -1401,7 +1402,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
                } else {
                        /* R300 uses ref_div_acc field as real ref divider */
                        OUTPLLP(PPLL_REF_DIV,
-                               (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), 
+                               (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
                                ~R300_PPLL_REF_DIV_ACC_MASK);
                }
        } else
@@ -1423,7 +1424,7 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg
           workaround shouldn't have any effect on them. */
        for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
                ;
-       
+
        OUTPLL(HTOTAL_CNTL, 0);
 
        /* Clear reset & atomic update */
@@ -1510,7 +1511,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
 
        radeon_fifo_wait(2);
        OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl);
-       
+
        return;
 }
 
@@ -1735,7 +1736,7 @@ static int radeonfb_set_par(struct fb_info *info)
        /* Clear auto-center etc... */
        newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl;
        newmode->crtc_more_cntl &= 0xfffffff0;
-       
+
        if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
                newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
                if (mirror)
@@ -1793,7 +1794,7 @@ static int radeonfb_set_par(struct fb_info *info)
                        newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;
                        newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP;
                        break;
-               case 24:        
+               case 24:
                case 32:
                        newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;
                        newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP;
@@ -2028,7 +2029,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
        }
        save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
        save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
-       
+
        OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS);
        OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
        mdelay(100);
@@ -2038,7 +2039,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
 
 #ifdef SET_MC_FB_FROM_APERTURE
        /* Set framebuffer to be at the same address as set in PCI BAR */
-       OUTREG(MC_FB_LOCATION, 
+       OUTREG(MC_FB_LOCATION,
                ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16));
        rinfo->fb_local_base = aper_base;
 #else
@@ -2079,7 +2080,7 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo)
        OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl);
        OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl);
        if (rinfo->has_CRTC2)
-               OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);    
+               OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl);
 
        pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n",
                aper_base,
@@ -2239,20 +2240,10 @@ static const struct bin_attribute edid2_attr = {
 
 static int radeon_kick_out_firmware_fb(struct pci_dev *pdev)
 {
-       struct apertures_struct *ap;
-
-       ap = alloc_apertures(1);
-       if (!ap)
-               return -ENOMEM;
-
-       ap->ranges[0].base = pci_resource_start(pdev, 0);
-       ap->ranges[0].size = pci_resource_len(pdev, 0);
+       resource_size_t base = pci_resource_start(pdev, 0);
+       resource_size_t size = pci_resource_len(pdev, 0);
 
-       remove_conflicting_framebuffers(ap, KBUILD_MODNAME, false);
-
-       kfree(ap);
-
-       return 0;
+       return aperture_remove_conflicting_devices(base, size, false, KBUILD_MODNAME);
 }
 
 static int radeonfb_pci_register(struct pci_dev *pdev,
@@ -2265,7 +2256,7 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
        int err = 0;
 
        pr_debug("radeonfb_pci_register BEGIN\n");
-       
+
        /* Enable device in PCI config */
        ret = pci_enable_device(pdev);
        if (ret < 0) {
@@ -2280,9 +2271,9 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
                goto err_disable;
        }
        rinfo = info->par;
-       rinfo->info = info;     
+       rinfo->info = info;
        rinfo->pdev = pdev;
-       
+
        spin_lock_init(&rinfo->reg_lock);
        timer_setup(&rinfo->lvds_timer, radeon_lvds_timer_func, 0);
 
@@ -2521,7 +2512,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
+
         if (!rinfo)
                 return;
 
@@ -2540,7 +2531,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev)
 
         iounmap(rinfo->mmio_base);
         iounmap(rinfo->fb_base);
+
        pci_release_region(pdev, 2);
        pci_release_region(pdev, 0);
 
@@ -2550,7 +2541,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev)
                fb_destroy_modedb(rinfo->mon1_modedb);
 #ifdef CONFIG_FB_RADEON_I2C
        radeon_delete_i2c_busses(rinfo);
-#endif        
+#endif
        fb_dealloc_cmap(&info->cmap);
         framebuffer_release(info);
 }
index 3a1c2e0739a1609103ae93f3050b217556fe5d47..4651b48a87f9396a2de3a986928dc2b0fea4a422 100644 (file)
@@ -7,6 +7,7 @@
  * - FB1 is display 1 with unique memory area
  * - both display use 32 bit colors
  */
+#include <linux/aperture.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fb.h>
@@ -614,6 +615,10 @@ static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        struct fb_info *info;
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(dev, "carminefb");
+       if (ret)
+               return ret;
+
        ret = pci_enable_device(dev);
        if (ret)
                return ret;
index 393894af26f849981e71f22b22923e49d6de8d57..5ad64714d39eae2b32b09951ddf522aaef722307 100644 (file)
@@ -14,6 +14,7 @@
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -122,7 +123,7 @@ static int chipsfb_set_par(struct fb_info *info)
                info->var.blue.offset = 0;
                info->var.red.length = info->var.green.length =
                        info->var.blue.length = 5;
-               
+
        } else {
                /* p->var.bits_per_pixel == 8 */
                write_cr(0x13, 100);            // Set line length (doublewords)
@@ -131,13 +132,13 @@ static int chipsfb_set_par(struct fb_info *info)
                write_xr(0x20, 0x00);           // 8 bit blitter mode
 
                info->fix.line_length = 800;
-               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;               
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 
                info->var.red.offset = info->var.green.offset =
                        info->var.blue.offset = 0;
                info->var.red.length = info->var.green.length =
                        info->var.blue.length = 8;
-               
+
        }
        return 0;
 }
@@ -351,7 +352,11 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
        struct fb_info *p;
        unsigned long addr;
        unsigned short cmd;
-       int rc = -ENODEV;
+       int rc;
+
+       rc = aperture_remove_conflicting_pci_devices(dp, "chipsfb");
+       if (rc)
+               return rc;
 
        if (pci_enable_device(dp) < 0) {
                dev_err(&dp->dev, "Cannot enable PCI device\n");
index a41a75841e10ef06f5d506da669c440a5b3257af..851367e159c022ac3bbdabe3ddea2eebdebe4b12 100644 (file)
@@ -34,6 +34,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -2085,6 +2086,10 @@ static int cirrusfb_pci_register(struct pci_dev *pdev,
        unsigned long board_addr, board_size;
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "cirrusfb");
+       if (ret)
+               return ret;
+
        ret = pci_enable_device(pdev);
        if (ret < 0) {
                printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
index 02b0cf2cfafed195fe86bfd07983cf5b8e93c107..1e70d8c6765337b9b8ad99676fc61d9edc180cc8 100644 (file)
 
 #include <linux/module.h>
 
+#include <linux/aperture.h>
 #include <linux/compat.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/slab.h>
-#include <linux/sysfb.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/vt.h>
@@ -40,6 +40,7 @@
 
 #include <asm/fb.h>
 
+#include <video/vga.h>
 
     /*
      *  Frame buffer device initialization and setup routines
 static DEFINE_MUTEX(registration_lock);
 
 struct fb_info *registered_fb[FB_MAX] __read_mostly;
-EXPORT_SYMBOL(registered_fb);
-
 int num_registered_fb __read_mostly;
-EXPORT_SYMBOL(num_registered_fb);
+#define for_each_registered_fb(i)              \
+       for (i = 0; i < FB_MAX; i++)            \
+               if (!registered_fb[i]) {} else
 
 bool fb_center_logo __read_mostly;
 
@@ -1525,103 +1526,6 @@ static int fb_check_foreignness(struct fb_info *fi)
        return 0;
 }
 
-static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
-{
-       /* is the generic aperture base the same as the HW one */
-       if (gen->base == hw->base)
-               return true;
-       /* is the generic aperture base inside the hw base->hw base+size */
-       if (gen->base > hw->base && gen->base < hw->base + hw->size)
-               return true;
-       return false;
-}
-
-static bool fb_do_apertures_overlap(struct apertures_struct *gena,
-                                   struct apertures_struct *hwa)
-{
-       int i, j;
-       if (!hwa || !gena)
-               return false;
-
-       for (i = 0; i < hwa->count; ++i) {
-               struct aperture *h = &hwa->ranges[i];
-               for (j = 0; j < gena->count; ++j) {
-                       struct aperture *g = &gena->ranges[j];
-                       printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
-                               (unsigned long long)g->base,
-                               (unsigned long long)g->size,
-                               (unsigned long long)h->base,
-                               (unsigned long long)h->size);
-                       if (apertures_overlap(g, h))
-                               return true;
-               }
-       }
-
-       return false;
-}
-
-static void do_unregister_framebuffer(struct fb_info *fb_info);
-
-#define VGA_FB_PHYS 0xA0000
-static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
-                                              const char *name, bool primary)
-{
-       int i;
-
-restart_removal:
-       /* check all firmware fbs and kick off if the base addr overlaps */
-       for_each_registered_fb(i) {
-               struct apertures_struct *gen_aper;
-               struct device *device;
-
-               if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
-                       continue;
-
-               gen_aper = registered_fb[i]->apertures;
-               device = registered_fb[i]->device;
-               if (fb_do_apertures_overlap(gen_aper, a) ||
-                       (primary && gen_aper && gen_aper->count &&
-                        gen_aper->ranges[0].base == VGA_FB_PHYS)) {
-
-                       printk(KERN_INFO "fb%d: switching to %s from %s\n",
-                              i, name, registered_fb[i]->fix.id);
-
-                       /*
-                        * If we kick-out a firmware driver, we also want to remove
-                        * the underlying platform device, such as simple-framebuffer,
-                        * VESA, EFI, etc. A native driver will then be able to
-                        * allocate the memory range.
-                        *
-                        * If it's not a platform device, at least print a warning. A
-                        * fix would add code to remove the device from the system. For
-                        * framebuffers without any Linux device, print a warning as
-                        * well.
-                        */
-                       if (!device) {
-                               pr_warn("fb%d: no device set\n", i);
-                               do_unregister_framebuffer(registered_fb[i]);
-                       } else if (dev_is_platform(device)) {
-                               /*
-                                * Drop the lock because if the device is unregistered, its
-                                * driver will call to unregister_framebuffer(), that takes
-                                * this lock.
-                                */
-                               mutex_unlock(&registration_lock);
-                               platform_device_unregister(to_platform_device(device));
-                               mutex_lock(&registration_lock);
-                       } else {
-                               pr_warn("fb%d: cannot remove device\n", i);
-                               do_unregister_framebuffer(registered_fb[i]);
-                       }
-                       /*
-                        * Restart the removal loop now that the device has been
-                        * unregistered and its associated framebuffer gone.
-                        */
-                       goto restart_removal;
-               }
-       }
-}
-
 static int do_register_framebuffer(struct fb_info *fb_info)
 {
        int i;
@@ -1630,10 +1534,6 @@ static int do_register_framebuffer(struct fb_info *fb_info)
        if (fb_check_foreignness(fb_info))
                return -ENOSYS;
 
-       do_remove_conflicting_framebuffers(fb_info->apertures,
-                                          fb_info->fix.id,
-                                          fb_is_primary_device(fb_info));
-
        if (num_registered_fb == FB_MAX)
                return -ENXIO;
 
@@ -1752,100 +1652,31 @@ static void do_unregister_framebuffer(struct fb_info *fb_info)
        put_fb_info(fb_info);
 }
 
-/**
- * remove_conflicting_framebuffers - remove firmware-configured framebuffers
- * @a: memory range, users of which are to be removed
- * @name: requesting driver name
- * @primary: also kick vga16fb if present
- *
- * This function removes framebuffer devices (initialized by firmware/bootloader)
- * which use memory range described by @a. If @a is NULL all such devices are
- * removed.
- */
-int remove_conflicting_framebuffers(struct apertures_struct *a,
-                                   const char *name, bool primary)
+static int fb_aperture_acquire_for_platform_device(struct fb_info *fb_info)
 {
-       bool do_free = false;
-
-       if (!a) {
-               a = alloc_apertures(1);
-               if (!a)
-                       return -ENOMEM;
-
-               a->ranges[0].base = 0;
-               a->ranges[0].size = ~0;
-               do_free = true;
-       }
-
-       /*
-        * If a driver asked to unregister a platform device registered by
-        * sysfb, then can be assumed that this is a driver for a display
-        * that is set up by the system firmware and has a generic driver.
-        *
-        * Drivers for devices that don't have a generic driver will never
-        * ask for this, so let's assume that a real driver for the display
-        * was already probed and prevent sysfb to register devices later.
-        */
-       sysfb_disable();
-
-       mutex_lock(&registration_lock);
-       do_remove_conflicting_framebuffers(a, name, primary);
-       mutex_unlock(&registration_lock);
-
-       if (do_free)
-               kfree(a);
-
-       return 0;
-}
-EXPORT_SYMBOL(remove_conflicting_framebuffers);
+       struct apertures_struct *ap = fb_info->apertures;
+       struct device *dev = fb_info->device;
+       struct platform_device *pdev;
+       unsigned int i;
+       int ret;
 
-/**
- * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
- * @pdev: PCI device
- * @name: requesting driver name
- *
- * This function removes framebuffer devices (eg. initialized by firmware)
- * using memory range configured for any of @pdev's memory bars.
- *
- * The function assumes that PCI device with shadowed ROM drives a primary
- * display and so kicks out vga16fb.
- */
-int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
-{
-       struct apertures_struct *ap;
-       bool primary = false;
-       int err, idx, bar;
+       if (!ap)
+               return 0;
 
-       for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
-               if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
-                       continue;
-               idx++;
-       }
+       if (!dev_is_platform(dev))
+               return 0;
 
-       ap = alloc_apertures(idx);
-       if (!ap)
-               return -ENOMEM;
+       pdev = to_platform_device(dev);
 
-       for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
-               if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
-                       continue;
-               ap->ranges[idx].base = pci_resource_start(pdev, bar);
-               ap->ranges[idx].size = pci_resource_len(pdev, bar);
-               pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
-                       (unsigned long)pci_resource_start(pdev, bar),
-                       (unsigned long)pci_resource_end(pdev, bar));
-               idx++;
+       for (ret = 0, i = 0; i < ap->count; ++i) {
+               ret = devm_aperture_acquire_for_platform_device(pdev, ap->ranges[i].base,
+                                                               ap->ranges[i].size);
+               if (ret)
+                       break;
        }
 
-#ifdef CONFIG_X86
-       primary = pdev->resource[PCI_ROM_RESOURCE].flags &
-                                       IORESOURCE_ROM_SHADOW;
-#endif
-       err = remove_conflicting_framebuffers(ap, name, primary);
-       kfree(ap);
-       return err;
+       return ret;
 }
-EXPORT_SYMBOL(remove_conflicting_pci_framebuffers);
 
 /**
  *     register_framebuffer - registers a frame buffer device
@@ -1861,6 +1692,12 @@ register_framebuffer(struct fb_info *fb_info)
 {
        int ret;
 
+       if (fb_info->flags & FBINFO_MISC_FIRMWARE) {
+               ret = fb_aperture_acquire_for_platform_device(fb_info);
+               if (ret)
+                       return ret;
+       }
+
        mutex_lock(&registration_lock);
        ret = do_register_framebuffer(fb_info);
        mutex_unlock(&registration_lock);
index d45355b9a58ca3aae87833054fef2386d7a7da85..be7bcf95c96a5c6dc3b73674720d47262a9f3405 100644 (file)
@@ -33,6 +33,7 @@
  * (which, incidentally, is about the same saving as a 2.5in hard disk
  * entering standby mode.)
  */
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1720,6 +1721,10 @@ static int cyberpro_pci_probe(struct pci_dev *dev,
 
        sprintf(name, "CyberPro%4X", id->device);
 
+       err = aperture_remove_conflicting_pci_devices(dev, name);
+       if (err)
+               return err;
+
        err = pci_enable_device(dev);
        if (err)
                return err;
index 5d34d89fb665346e0688c380aff0854b0bd4db10..4cac7e3bb1a0cc2445ed3232d233ef6bc363b618 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2005 Arcom Control Systems Ltd.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -320,6 +321,10 @@ static int gx1fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct fb_info *info;
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "gx1fb");
+       if (ret)
+               return ret;
+
        info = gx1fb_init_fbinfo(&pdev->dev);
        if (!info)
                return -ENOMEM;
index 44089b331f91db542467db2c6fc232f9eeb3e503..2527bd80ec5f537e704742f69f2836bb0d9c512a 100644 (file)
@@ -15,6 +15,7 @@
  *
  * 16 MiB of framebuffer memory is assumed to be available.
  */
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -364,6 +365,10 @@ static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct fb_videomode *modedb_ptr;
        unsigned int modedb_size;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "gxfb");
+       if (ret)
+               return ret;
+
        info = gxfb_init_fbinfo(&pdev->dev);
        if (!info)
                return -ENOMEM;
index 66c81262d18f873645810dc28dd52efa12314b47..9d26592dbfce9aaf06b54d2cf22f455fc2694b50 100644 (file)
@@ -6,6 +6,7 @@
  * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.)
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -484,6 +485,10 @@ static int lxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct fb_videomode *modedb_ptr;
        unsigned int modedb_size;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "lxfb");
+       if (ret)
+               return ret;
+
        info = lxfb_init_fbinfo(&pdev->dev);
 
        if (info == NULL)
index e5475ae1e1587ef5cf7dbd2d504c4cd21e02a6f4..f0d36a4fdaefd159f6babdfc4d0a52ff169963db 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
  */
 
+#include <linux/aperture.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fb.h>
@@ -621,6 +622,10 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct fb_var_screeninfo var;
        enum gxt_cards cardtype;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "gxt4500fb");
+       if (err)
+               return err;
+
        err = pci_enable_device(pdev);
        if (err) {
                dev_err(&pdev->dev, "gxt4500: cannot enable PCI device: %d\n",
index 886c564787f152f8eef16d0990bf9242662bdc88..a0e1d70b90d75f9803796b3d82f232f2ccf342f6 100644 (file)
@@ -45,6 +45,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/vmalloc.h>
@@ -1074,8 +1075,9 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
        info->screen_size = dio_fb_size;
 
 getmem_done:
-       remove_conflicting_framebuffers(info->apertures,
-                                       KBUILD_MODNAME, false);
+       aperture_remove_conflicting_devices(info->apertures->ranges[0].base,
+                                           info->apertures->ranges[0].size,
+                                           false, KBUILD_MODNAME);
 
        if (gen2vm) {
                /* framebuffer is reallocated, clear screen_info to avoid misuse from kexec */
index 7f09a0daaaa24dd7c6b37dcf219c0129eca3c407..199f786f9eedec1d7ec185963c48301bda2ad485 100644 (file)
@@ -12,6 +12,7 @@
  *  i740fb by Patrick LERDA, v0.9
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1013,6 +1014,10 @@ static int i740fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        bool found = false;
        u8 *edid;
 
+       ret = aperture_remove_conflicting_pci_devices(dev, "i740fb");
+       if (ret)
+               return ret;
+
        info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
        if (!info)
                return -ENOMEM;
index 13bbf7fe13bf30ecbf388eb06a6de32744e4784f..ff09f8c20bfcbaafac8d0a233537b608d8742f11 100644 (file)
@@ -2,12 +2,12 @@
  *  linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
  *
  *      Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
- *      All Rights Reserved      
+ *      All Rights Reserved
  *
  *      Contributors:
  *         Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
- *                                        and enabling the power-on state of 
- *                                        external VGA connectors for 
+ *                                        and enabling the power-on state of
+ *                                        external VGA connectors for
  *                                        secondary displays
  *
  *         Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
  *                                        timings support
  *
  *     The code framework is a modification of vfb.c by Geert Uytterhoeven.
- *      DotClock and PLL calculations are partly based on i810_driver.c 
+ *      DotClock and PLL calculations are partly based on i810_driver.c
  *              in xfree86 v4.0.3 by Precision Insight.
- *      Watermark calculation and tables are based on i810_wmark.c 
- *              in xfre86 v4.0.3 by Precision Insight.  Slight modifications 
+ *      Watermark calculation and tables are based on i810_wmark.c
+ *              in xfre86 v4.0.3 by Precision Insight.  Slight modifications
  *              only to allow for integer operations instead of floating point.
  *
  *  This file is subject to the terms and conditions of the GNU General Public
@@ -28,6 +28,7 @@
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -204,8 +205,8 @@ static void i810_dram_off(u8 __iomem *mmio, u8 mode)
  * @mode: protect/unprotect
  *
  * DESCRIPTION:
- * The IBM VGA standard allows protection of certain VGA registers.  
- * This will  protect or unprotect them. 
+ * The IBM VGA standard allows protection of certain VGA registers.
+ * This will  protect or unprotect them.
  */
 static void i810_protect_regs(u8 __iomem *mmio, int mode)
 {
@@ -215,7 +216,7 @@ static void i810_protect_regs(u8 __iomem *mmio, int mode)
        reg = i810_readb(CR_DATA_CGA, mmio);
        reg = (mode == OFF) ? reg & ~0x80 :
                reg | 0x80;
-               
+
        i810_writeb(CR_INDEX_CGA, mmio, CR11);
        i810_writeb(CR_DATA_CGA, mmio, reg);
 }
@@ -225,18 +226,18 @@ static void i810_protect_regs(u8 __iomem *mmio, int mode)
  * @par: pointer to i810fb_par structure
  *
  * DESCRIPTION:
- * Loads the P, M, and N registers.  
+ * Loads the P, M, and N registers.
  */
 static void i810_load_pll(struct i810fb_par *par)
 {
        u32 tmp1, tmp2;
        u8 __iomem *mmio = par->mmio_start_virtual;
-       
+
        tmp1 = par->regs.M | par->regs.N << 16;
        tmp2 = i810_readl(DCLK_2D, mmio);
        tmp2 &= ~MN_MASK;
        i810_writel(DCLK_2D, mmio, tmp1 | tmp2);
-       
+
        tmp1 = par->regs.P;
        tmp2 = i810_readl(DCLK_0DS, mmio);
        tmp2 &= ~(P_OR << 16);
@@ -254,7 +255,7 @@ static void i810_load_pll(struct i810fb_par *par)
  * Load values to VGA registers
  */
 static void i810_load_vga(struct i810fb_par *par)
-{      
+{
        u8 __iomem *mmio = par->mmio_start_virtual;
 
        /* interlace */
@@ -327,7 +328,7 @@ static void i810_load_2d(struct i810fb_par *par)
        u8 tmp8;
        u8 __iomem *mmio = par->mmio_start_virtual;
 
-       i810_writel(FW_BLC, mmio, par->watermark); 
+       i810_writel(FW_BLC, mmio, par->watermark);
        tmp = i810_readl(PIXCONF, mmio);
        tmp |= 1 | 1 << 20;
        i810_writel(PIXCONF, mmio, tmp);
@@ -339,7 +340,7 @@ static void i810_load_2d(struct i810fb_par *par)
        tmp8 |= 2;
        i810_writeb(GR_INDEX, mmio, GR10);
        i810_writeb(GR_DATA, mmio, tmp8);
-}      
+}
 
 /**
  * i810_hires - enables high resolution mode
@@ -348,7 +349,7 @@ static void i810_load_2d(struct i810fb_par *par)
 static void i810_hires(u8 __iomem *mmio)
 {
        u8 val;
-       
+
        i810_writeb(CR_INDEX_CGA, mmio, CR80);
        val = i810_readb(CR_DATA_CGA, mmio);
        i810_writeb(CR_INDEX_CGA, mmio, CR80);
@@ -363,13 +364,13 @@ static void i810_hires(u8 __iomem *mmio)
  *
  * DESCRIPTION:
  * Loads the characters per line
- */    
+ */
 static void i810_load_pitch(struct i810fb_par *par)
 {
        u32 tmp, pitch;
        u8 val;
        u8 __iomem *mmio = par->mmio_start_virtual;
-                       
+
        pitch = par->pitch >> 3;
        i810_writeb(SR_INDEX, mmio, SR01);
        val = i810_readb(SR_DATA, mmio);
@@ -381,7 +382,7 @@ static void i810_load_pitch(struct i810fb_par *par)
        tmp = pitch & 0xFF;
        i810_writeb(CR_INDEX_CGA, mmio, CR13);
        i810_writeb(CR_DATA_CGA, mmio, (u8) tmp);
-       
+
        tmp = pitch >> 8;
        i810_writeb(CR_INDEX_CGA, mmio, CR41);
        val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F;
@@ -414,7 +415,7 @@ static void i810_load_color(struct i810fb_par *par)
 /**
  * i810_load_regs - loads all registers for the mode
  * @par: pointer to i810fb_par structure
- * 
+ *
  * DESCRIPTION:
  * Loads registers
  */
@@ -428,7 +429,7 @@ static void i810_load_regs(struct i810fb_par *par)
        i810_load_pll(par);
        i810_load_vga(par);
        i810_load_vgax(par);
-       i810_dram_off(mmio, ON);        
+       i810_dram_off(mmio, ON);
        i810_load_2d(par);
        i810_hires(mmio);
        i810_screen_off(mmio, ON);
@@ -443,7 +444,7 @@ static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue,
        i810_writeb(CLUT_INDEX_WRITE, mmio, regno);
        i810_writeb(CLUT_DATA, mmio, red);
        i810_writeb(CLUT_DATA, mmio, green);
-       i810_writeb(CLUT_DATA, mmio, blue);     
+       i810_writeb(CLUT_DATA, mmio, blue);
 }
 
 static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
@@ -456,13 +457,13 @@ static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue,
 }
 
 /************************************************************
- *                   VGA State Restore                      * 
+ *                   VGA State Restore                      *
  ************************************************************/
 static void i810_restore_pll(struct i810fb_par *par)
 {
        u32 tmp1, tmp2;
        u8 __iomem *mmio = par->mmio_start_virtual;
-       
+
        tmp1 = par->hw_state.dclk_2d;
        tmp2 = i810_readl(DCLK_2D, mmio);
        tmp1 &= ~MN_MASK;
@@ -494,7 +495,7 @@ static void i810_restore_vgax(struct i810fb_par *par)
 {
        u8 i, j;
        u8 __iomem *mmio = par->mmio_start_virtual;
-       
+
        for (i = 0; i < 4; i++) {
                i810_writeb(CR_INDEX_CGA, mmio, CR30+i);
                i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i));
@@ -528,7 +529,7 @@ static void i810_restore_vga(struct i810fb_par *par)
 {
        u8 i;
        u8 __iomem *mmio = par->mmio_start_virtual;
-       
+
        for (i = 0; i < 10; i++) {
                i810_writeb(CR_INDEX_CGA, mmio, CR00 + i);
                i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i));
@@ -559,10 +560,10 @@ static void i810_restore_2d(struct i810fb_par *par)
        u8 __iomem *mmio = par->mmio_start_virtual;
 
        tmp_word = i810_readw(BLTCNTL, mmio);
-       tmp_word &= ~(3 << 4); 
+       tmp_word &= ~(3 << 4);
        tmp_word |= par->hw_state.bltcntl;
        i810_writew(BLTCNTL, mmio, tmp_word);
-       
+
        i810_dram_off(mmio, OFF);
        i810_writel(PIXCONF, mmio, par->hw_state.pixconf);
        i810_dram_off(mmio, ON);
@@ -577,7 +578,7 @@ static void i810_restore_2d(struct i810fb_par *par)
        tmp_long |= par->hw_state.fw_blc;
        i810_writel(FW_BLC, mmio, tmp_long);
 
-       i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); 
+       i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga);
        i810_writew(IER, mmio, par->hw_state.ier);
        i810_writew(IMR, mmio, par->hw_state.imr);
        i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);
@@ -621,7 +622,7 @@ static void i810_save_vgax(struct i810fb_par *par)
        i810_writeb(CR_INDEX_CGA, mmio, CR41);
        par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio);
        i810_writeb(CR_INDEX_CGA, mmio, CR70);
-       par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);     
+       par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio);
        par->hw_state.msr = i810_readb(MSR_READ, mmio);
        i810_writeb(CR_INDEX_CGA, mmio, CR80);
        par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio);
@@ -654,8 +655,8 @@ static void i810_save_2d(struct i810fb_par *par)
        par->hw_state.pixconf = i810_readl(PIXCONF, mmio);
        par->hw_state.fw_blc = i810_readl(FW_BLC, mmio);
        par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio);
-       par->hw_state.hwstam = i810_readw(HWSTAM, mmio); 
-       par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); 
+       par->hw_state.hwstam = i810_readw(HWSTAM, mmio);
+       par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio);
        par->hw_state.ier = i810_readw(IER, mmio);
        par->hw_state.imr = i810_readw(IMR, mmio);
        par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio);
@@ -669,7 +670,7 @@ static void i810_save_vga_state(struct i810fb_par *par)
 }
 
 /************************************************************
- *                    Helpers                               * 
+ *                    Helpers                               *
  ************************************************************/
 /**
  * get_line_length - calculates buffer pitch in bytes
@@ -678,12 +679,12 @@ static void i810_save_vga_state(struct i810fb_par *par)
  * @bpp: bits per pixel
  *
  * DESCRIPTION:
- * Calculates buffer pitch in bytes.  
+ * Calculates buffer pitch in bytes.
  */
 static u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp)
 {
        u32 length;
-       
+
        length = xres_virtual*bpp;
        length = (length+31)&-32;
        length >>= 3;
@@ -716,17 +717,17 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
        n_target_max = 30;
 
        /*
-        * find P such that target freq is 16x reference freq (Hz). 
+        * find P such that target freq is 16x reference freq (Hz).
         */
        p_divisor = 1;
        p_target = 0;
-       while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && 
+       while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) &&
              p_divisor <= 32) {
                p_divisor <<= 1;
                p_target++;
        }
 
-       n_reg = m_reg = n_target = 3;   
+       n_reg = m_reg = n_target = 3;
        while (diff_min && mod_min && (n_target < n_target_max)) {
                f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg);
                mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg);
@@ -744,14 +745,14 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
                        diff_min = diff;
                        n_best = n_target;
                        m_best = m_target;
-               }                
+               }
 
                if (!diff && mod_min > mod) {
                        mod_min = mod;
                        n_best = n_target;
                        m_best = m_target;
                }
-       } 
+       }
        if (m) *m = (m_best - 2) & 0x3FF;
        if (n) *n = (n_best - 2) & 0x3FF;
        if (p) *p = (p_target << 4);
@@ -772,7 +773,7 @@ static void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p)
 static void i810_enable_cursor(u8 __iomem *mmio, int mode)
 {
        u32 temp;
-       
+
        temp = i810_readl(PIXCONF, mmio);
        temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK :
                temp & ~CURSOR_ENABLE_MASK;
@@ -786,10 +787,10 @@ static void i810_reset_cursor_image(struct i810fb_par *par)
        int i, j;
 
        for (i = 64; i--; ) {
-               for (j = 0; j < 8; j++) {             
-                       i810_writeb(j, addr, 0xff);   
-                       i810_writeb(j+8, addr, 0x00); 
-               }       
+               for (j = 0; j < 8; j++) {
+                       i810_writeb(j, addr, 0xff);
+                       i810_writeb(j+8, addr, 0x00);
+               }
                addr +=16;
        }
 }
@@ -800,9 +801,9 @@ static void i810_load_cursor_image(int width, int height, u8 *data,
        u8 __iomem *addr = par->cursor_heap.virtual;
        int i, j, w = width/8;
        int mod = width % 8, t_mask, d_mask;
-       
+
        t_mask = 0xff >> mod;
-       d_mask = ~(0xff >> mod); 
+       d_mask = ~(0xff >> mod);
        for (i = height; i--; ) {
                for (j = 0; j < w; j++) {
                        i810_writeb(j+0, addr, 0x00);
@@ -854,7 +855,7 @@ static void i810_init_cursor(struct i810fb_par *par)
        i810_enable_cursor(mmio, OFF);
        i810_writel(CURBASE, mmio, par->cursor_heap.physical);
        i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR);
-}      
+}
 
 /*********************************************************************
  *                    Framebuffer hook helpers                       *
@@ -873,7 +874,7 @@ static void i810_round_off(struct fb_var_screeninfo *var)
        u32 xres, yres, vxres, vyres;
 
        /*
-        *  Presently supports only these configurations 
+        *  Presently supports only these configurations
         */
 
        xres = var->xres;
@@ -883,20 +884,20 @@ static void i810_round_off(struct fb_var_screeninfo *var)
 
        var->bits_per_pixel += 7;
        var->bits_per_pixel &= ~7;
-       
+
        if (var->bits_per_pixel < 8)
                var->bits_per_pixel = 8;
-       if (var->bits_per_pixel > 32) 
+       if (var->bits_per_pixel > 32)
                var->bits_per_pixel = 32;
 
        round_off_xres(&xres);
        if (xres < 40)
                xres = 40;
-       if (xres > 2048) 
+       if (xres > 2048)
                xres = 2048;
        xres = (xres + 7) & ~7;
 
-       if (vxres < xres) 
+       if (vxres < xres)
                vxres = xres;
 
        round_off_yres(&xres, &yres);
@@ -905,7 +906,7 @@ static void i810_round_off(struct fb_var_screeninfo *var)
        if (yres >= 2048)
                yres = 2048;
 
-       if (vyres < yres) 
+       if (vyres < yres)
                vyres = yres;
 
        if (var->bits_per_pixel == 32)
@@ -917,30 +918,30 @@ static void i810_round_off(struct fb_var_screeninfo *var)
        var->hsync_len = (var->hsync_len + 4) & ~7;
 
        if (var->vmode & FB_VMODE_INTERLACED) {
-               if (!((yres + var->upper_margin + var->vsync_len + 
+               if (!((yres + var->upper_margin + var->vsync_len +
                       var->lower_margin) & 1))
                        var->upper_margin++;
        }
-       
+
        var->xres = xres;
        var->yres = yres;
        var->xres_virtual = vxres;
        var->yres_virtual = vyres;
-}      
+}
 
 /**
  * set_color_bitfields - sets rgba fields
  * @var: pointer to fb_var_screeninfo
  *
  * DESCRIPTION:
- * The length, offset and ordering  for each color field 
- * (red, green, blue)  will be set as specified 
+ * The length, offset and ordering  for each color field
+ * (red, green, blue)  will be set as specified
  * by the hardware
- */  
+ */
 static void set_color_bitfields(struct fb_var_screeninfo *var)
 {
        switch (var->bits_per_pixel) {
-       case 8:       
+       case 8:
                var->red.offset = 0;
                var->red.length = 8;
                var->green.offset = 0;
@@ -984,11 +985,11 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
  * @info: pointer to fb_info
  *
  * DESCRIPTION:
- * This will check if the framebuffer size is sufficient 
- * for the current mode and if the user's monitor has the 
+ * This will check if the framebuffer size is sufficient
+ * for the current mode and if the user's monitor has the
  * required specifications to display the current mode.
  */
-static int i810_check_params(struct fb_var_screeninfo *var, 
+static int i810_check_params(struct fb_var_screeninfo *var,
                             struct fb_info *info)
 {
        struct i810fb_par *par = info->par;
@@ -1007,14 +1008,14 @@ static int i810_check_params(struct fb_var_screeninfo *var,
                        vyres = info->var.yres;
                        vxres = par->fb.size/vyres;
                        vxres /= var->bits_per_pixel >> 3;
-                       line_length = get_line_length(par, vxres, 
+                       line_length = get_line_length(par, vxres,
                                                      var->bits_per_pixel);
                        vidmem = line_length * info->var.yres;
                        if (vxres < var->xres) {
                                printk("i810fb: required video memory, "
                                       "%d bytes, for %dx%d-%d (virtual) "
-                                      "is out of range\n", 
-                                      vidmem, vxres, vyres, 
+                                      "is out of range\n",
+                                      vidmem, vxres, vyres,
                                       var->bits_per_pixel);
                                return -ENOMEM;
                        }
@@ -1074,7 +1075,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
        }
 
        return retval;
-}      
+}
 
 /**
  * encode_fix - fill up fb_fix_screeninfo structure
@@ -1131,9 +1132,9 @@ static int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
  *
  * DESCRIPTION:
  * Based on the contents of @var, @par will be dynamically filled up.
- * @par contains all information necessary to modify the hardware. 
+ * @par contains all information necessary to modify the hardware.
 */
-static void decode_var(const struct fb_var_screeninfo *var, 
+static void decode_var(const struct fb_var_screeninfo *var,
                       struct i810fb_par *par)
 {
        u32 xres, yres, vxres, vyres;
@@ -1175,13 +1176,13 @@ static void decode_var(const struct fb_var_screeninfo *var,
        if (var->nonstd && var->bits_per_pixel != 8)
                par->pixconf |= 1 << 27;
 
-       i810_calc_dclk(var->pixclock, &par->regs.M, 
+       i810_calc_dclk(var->pixclock, &par->regs.M,
                       &par->regs.N, &par->regs.P);
        i810fb_encode_registers(var, par, xres, yres);
 
        par->watermark = i810_get_watermark(var, par);
        par->pitch = get_line_length(par, vxres, var->bits_per_pixel);
-}      
+}
 
 /**
  * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
@@ -1196,7 +1197,7 @@ static void decode_var(const struct fb_var_screeninfo *var,
  * Gets the red, green and blue values of the hardware DAC as pointed by @regno
  * and writes them to @red, @green and @blue respectively
  */
-static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 
+static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
                            u8 *transp, struct fb_info *info)
 {
        struct i810fb_par *par = info->par;
@@ -1212,18 +1213,18 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
        temp = i810_readb(PIXCONF1, mmio);
        i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
 
-       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
-           info->var.green.length == 5) 
+       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
+           info->var.green.length == 5)
                i810_read_dac(regno * 8, red, green, blue, mmio);
 
-       else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+       else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
                 info->var.green.length == 6) {
                u8 tmp;
 
                i810_read_dac(regno * 8, red, &tmp, blue, mmio);
                i810_read_dac(regno * 4, &tmp, green, &tmp, mmio);
        }
-       else 
+       else
                i810_read_dac(regno, red, green, blue, mmio);
 
        *transp = 0;
@@ -1232,7 +1233,7 @@ static int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue,
        return 0;
 }
 
-/****************************************************************** 
+/******************************************************************
  *           Framebuffer device-specific hooks                    *
  ******************************************************************/
 
@@ -1252,7 +1253,7 @@ static int i810fb_open(struct fb_info *info, int user)
 
        par->use_count++;
        mutex_unlock(&par->open_lock);
-       
+
        return 0;
 }
 
@@ -1273,13 +1274,13 @@ static int i810fb_release(struct fb_info *info, int user)
 
        par->use_count--;
        mutex_unlock(&par->open_lock);
-       
+
        return 0;
 }
 
 
-static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, 
-                           unsigned blue, unsigned transp, 
+static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+                           unsigned blue, unsigned transp,
                            struct fb_info *info)
 {
        struct i810fb_par *par = info->par;
@@ -1302,24 +1303,24 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
        temp = i810_readb(PIXCONF1, mmio);
        i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE);
 
-       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
            info->var.green.length == 5) {
-               for (i = 0; i < 8; i++) 
-                       i810_write_dac((u8) (regno * 8) + i, (u8) red, 
+               for (i = 0; i < 8; i++)
+                       i810_write_dac((u8) (regno * 8) + i, (u8) red,
                                       (u8) green, (u8) blue, mmio);
-       } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 
+       } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR &&
                 info->var.green.length == 6) {
                u8 r, g, b;
 
                if (regno < 32) {
-                       for (i = 0; i < 8; i++) 
+                       for (i = 0; i < 8; i++)
                                i810_write_dac((u8) (regno * 8) + i,
-                                              (u8) red, (u8) green, 
+                                              (u8) red, (u8) green,
                                               (u8) blue, mmio);
                }
                i810_read_dac((u8) (regno*4), &r, &g, &b, mmio);
-               for (i = 0; i < 4; i++) 
-                       i810_write_dac((u8) (regno*4) + i, r, (u8) green, 
+               for (i = 0; i < 4; i++)
+                       i810_write_dac((u8) (regno*4) + i, r, (u8) green,
                                       b, mmio);
        } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
                i810_write_dac((u8) regno, (u8) red, (u8) green,
@@ -1330,20 +1331,20 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
        if (regno < 16) {
                switch (info->var.bits_per_pixel) {
-               case 16:        
+               case 16:
                        if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-                               if (info->var.green.length == 5) 
-                                       ((u32 *)info->pseudo_palette)[regno] = 
+                               if (info->var.green.length == 5)
+                                       ((u32 *)info->pseudo_palette)[regno] =
                                                (regno << 10) | (regno << 5) |
                                                regno;
                                else
-                                       ((u32 *)info->pseudo_palette)[regno] = 
+                                       ((u32 *)info->pseudo_palette)[regno] =
                                                (regno << 11) | (regno << 5) |
                                                regno;
                        } else {
                                if (info->var.green.length == 5) {
                                        /* RGB 555 */
-                                       ((u32 *)info->pseudo_palette)[regno] = 
+                                       ((u32 *)info->pseudo_palette)[regno] =
                                                ((red & 0xf800) >> 1) |
                                                ((green & 0xf800) >> 6) |
                                                ((blue & 0xf800) >> 11);
@@ -1358,12 +1359,12 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
                        break;
                case 24:        /* RGB 888 */
                case 32:        /* RGBA 8888 */
-                       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 
-                               ((u32 *)info->pseudo_palette)[regno] = 
+                       if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
+                               ((u32 *)info->pseudo_palette)[regno] =
                                        (regno << 16) | (regno << 8) |
                                        regno;
-                       else 
-                               ((u32 *)info->pseudo_palette)[regno] = 
+                       else
+                               ((u32 *)info->pseudo_palette)[regno] =
                                        ((red & 0xff00) << 8) |
                                        (green & 0xff00) |
                                        ((blue & 0xff00) >> 8);
@@ -1373,13 +1374,13 @@ static int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green,
        return 0;
 }
 
-static int i810fb_pan_display(struct fb_var_screeninfo *var, 
+static int i810fb_pan_display(struct fb_var_screeninfo *var,
                              struct fb_info *info)
 {
        struct i810fb_par *par = info->par;
        u32 total;
-       
-       total = var->xoffset * par->depth + 
+
+       total = var->xoffset * par->depth +
                var->yoffset * info->fix.line_length;
        i810fb_load_front(total, info);
 
@@ -1391,7 +1392,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info)
        struct i810fb_par *par = info->par;
        u8 __iomem *mmio = par->mmio_start_virtual;
        int mode = 0, pwr, scr_off = 0;
-       
+
        pwr = i810_readl(PWR_CLKC, mmio);
 
        switch (blank_mode) {
@@ -1421,7 +1422,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info)
                scr_off = OFF;
                break;
        default:
-               return -EINVAL; 
+               return -EINVAL;
        }
 
        i810_screen_off(mmio, scr_off);
@@ -1452,7 +1453,7 @@ static int i810fb_set_par(struct fb_info *info)
        return 0;
 }
 
-static int i810fb_check_var(struct fb_var_screeninfo *var, 
+static int i810fb_check_var(struct fb_var_screeninfo *var,
                            struct fb_info *info)
 {
        int err;
@@ -1550,7 +1551,7 @@ static const struct fb_ops i810fb_ops = {
        .fb_set_par =        i810fb_set_par,
        .fb_setcolreg =      i810fb_setcolreg,
        .fb_blank =          i810fb_blank,
-       .fb_pan_display =    i810fb_pan_display, 
+       .fb_pan_display =    i810fb_pan_display,
        .fb_fillrect =       i810fb_fillrect,
        .fb_copyarea =       i810fb_copyarea,
        .fb_imageblit =      i810fb_imageblit,
@@ -1593,7 +1594,7 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
        return 0;
 }
 
-static int i810fb_resume(struct pci_dev *dev) 
+static int i810fb_resume(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct i810fb_par *par = info->par;
@@ -1628,14 +1629,14 @@ fail:
 /***********************************************************************
  *                  AGP resource allocation                            *
  ***********************************************************************/
-  
+
 static void i810_fix_pointers(struct i810fb_par *par)
 {
        par->fb.physical = par->aperture.physical+(par->fb.offset << 12);
        par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12);
-       par->iring.physical = par->aperture.physical + 
+       par->iring.physical = par->aperture.physical +
                (par->iring.offset << 12);
-       par->iring.virtual = par->aperture.virtual + 
+       par->iring.virtual = par->aperture.virtual +
                (par->iring.offset << 12);
        par->cursor_heap.virtual = par->aperture.virtual+
                (par->cursor_heap.offset << 12);
@@ -1666,7 +1667,7 @@ static int i810_alloc_agp_mem(struct fb_info *info)
        struct i810fb_par *par = info->par;
        int size;
        struct agp_bridge_data *bridge;
-       
+
        i810_fix_offsets(par);
        size = par->fb.size + par->iring.size;
 
@@ -1674,7 +1675,7 @@ static int i810_alloc_agp_mem(struct fb_info *info)
                printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
                return -ENODEV;
        }
-       if (!(par->i810_gtt.i810_fb_memory = 
+       if (!(par->i810_gtt.i810_fb_memory =
              agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
                printk("i810fb_alloc_fbmem: can't allocate framebuffer "
                       "memory\n");
@@ -1686,9 +1687,9 @@ static int i810_alloc_agp_mem(struct fb_info *info)
                printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
                agp_backend_release(bridge);
                return -EBUSY;
-       }       
-       
-       if (!(par->i810_gtt.i810_cursor_memory = 
+       }
+
+       if (!(par->i810_gtt.i810_cursor_memory =
              agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
                                  AGP_PHYSICAL_MEMORY))) {
                printk("i810fb_alloc_cursormem:  can't allocate "
@@ -1701,7 +1702,7 @@ static int i810_alloc_agp_mem(struct fb_info *info)
                printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
                agp_backend_release(bridge);
                return -EBUSY;
-       }       
+       }
 
        par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical;
 
@@ -1712,8 +1713,8 @@ static int i810_alloc_agp_mem(struct fb_info *info)
        return 0;
 }
 
-/*************************************************************** 
- *                    Initialization                           * 
+/***************************************************************
+ *                    Initialization                           *
  ***************************************************************/
 
 /**
@@ -1728,7 +1729,7 @@ static void i810_init_monspecs(struct fb_info *info)
 {
        if (!hsync1)
                hsync1 = HFMIN;
-       if (!hsync2) 
+       if (!hsync2)
                hsync2 = HFMAX;
        if (!info->monspecs.hfmax)
                info->monspecs.hfmax = hsync2;
@@ -1739,7 +1740,7 @@ static void i810_init_monspecs(struct fb_info *info)
 
        if (!vsync1)
                vsync1 = VFMIN;
-       if (!vsync2) 
+       if (!vsync2)
                vsync2 = VFMAX;
        if (IS_DVT && vsync1 < 60)
                vsync1 = 60;
@@ -1747,7 +1748,7 @@ static void i810_init_monspecs(struct fb_info *info)
                info->monspecs.vfmax = vsync2;
        if (!info->monspecs.vfmin)
                info->monspecs.vfmin = vsync1;
-       if (vsync2 < vsync1) 
+       if (vsync2 < vsync1)
                info->monspecs.vfmin = vsync2;
 }
 
@@ -1760,27 +1761,27 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
 {
        mutex_init(&par->open_lock);
 
-       if (voffset) 
+       if (voffset)
                v_offset_default = voffset;
        else if (par->aperture.size > 32 * 1024 * 1024)
                v_offset_default = 16;
        else
                v_offset_default = 8;
 
-       if (!vram) 
+       if (!vram)
                vram = 1;
 
-       if (accel) 
+       if (accel)
                par->dev_flags |= HAS_ACCELERATION;
 
-       if (sync) 
+       if (sync)
                par->dev_flags |= ALWAYS_SYNC;
 
        par->ddc_num = (ddc3 ? 3 : 2);
 
        if (bpp < 8)
                bpp = 8;
-       
+
        par->i810fb_ops = i810fb_ops;
 
        if (xres)
@@ -1793,7 +1794,7 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
        else
                info->var.yres = 480;
 
-       if (!vyres) 
+       if (!vyres)
                vyres = (vram << 20)/(info->var.xres*bpp >> 3);
 
        info->var.yres_virtual = vyres;
@@ -1802,12 +1803,12 @@ static void i810_init_defaults(struct i810fb_par *par, struct fb_info *info)
        if (dcolor)
                info->var.nonstd = 1;
 
-       if (par->dev_flags & HAS_ACCELERATION) 
+       if (par->dev_flags & HAS_ACCELERATION)
                info->var.accel_flags = 1;
 
        i810_init_monspecs(info);
 }
-       
+
 /**
  * i810_init_device - initialize device
  * @par: pointer to i810fb_par structure
@@ -1840,9 +1841,9 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
 {
        int err;
 
-       if ((err = pci_enable_device(par->dev))) { 
+       if ((err = pci_enable_device(par->dev))) {
                printk("i810fb_init: cannot enable device\n");
-               return err;             
+               return err;
        }
        par->res_flags |= PCI_DEVICE_ENABLED;
 
@@ -1860,8 +1861,8 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
                return -ENOMEM;
        }
 
-       if (!request_mem_region(par->aperture.physical, 
-                               par->aperture.size, 
+       if (!request_mem_region(par->aperture.physical,
+                               par->aperture.size,
                                i810_pci_list[entry->driver_data])) {
                printk("i810fb_init: cannot request framebuffer region\n");
                return -ENODEV;
@@ -1874,16 +1875,16 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
                printk("i810fb_init: cannot remap framebuffer region\n");
                return -ENODEV;
        }
-  
-       if (!request_mem_region(par->mmio_start_phys, 
-                               MMIO_SIZE, 
+
+       if (!request_mem_region(par->mmio_start_phys,
+                               MMIO_SIZE,
                                i810_pci_list[entry->driver_data])) {
                printk("i810fb_init: cannot request mmio region\n");
                return -ENODEV;
        }
        par->res_flags |= MMIO_REQ;
 
-       par->mmio_start_virtual = ioremap(par->mmio_start_phys, 
+       par->mmio_start_virtual = ioremap(par->mmio_start_phys,
                                                  MMIO_SIZE);
        if (!par->mmio_start_virtual) {
                printk("i810fb_init: cannot remap mmio region\n");
@@ -1963,7 +1964,7 @@ static int i810fb_setup(char *options)
 
        if (!options || !*options)
                return 0;
-       
+
        while ((this_opt = strsep(&options, ",")) != NULL) {
                if (!strncmp(this_opt, "mtrr", 4))
                        mtrr = true;
@@ -1987,13 +1988,13 @@ static int i810fb_setup(char *options)
                        bpp = simple_strtoul(this_opt+4, NULL, 0);
                else if (!strncmp(this_opt, "hsync1:", 7)) {
                        hsync1 = simple_strtoul(this_opt+7, &suffix, 0);
-                       if (strncmp(suffix, "H", 1)) 
+                       if (strncmp(suffix, "H", 1))
                                hsync1 *= 1000;
                } else if (!strncmp(this_opt, "hsync2:", 7)) {
                        hsync2 = simple_strtoul(this_opt+7, &suffix, 0);
-                       if (strncmp(suffix, "H", 1)) 
+                       if (strncmp(suffix, "H", 1))
                                hsync2 *= 1000;
-               } else if (!strncmp(this_opt, "vsync1:", 7)) 
+               } else if (!strncmp(this_opt, "vsync1:", 7))
                        vsync1 = simple_strtoul(this_opt+7, NULL, 0);
                else if (!strncmp(this_opt, "vsync2:", 7))
                        vsync2 = simple_strtoul(this_opt+7, NULL, 0);
@@ -2016,6 +2017,10 @@ static int i810fb_init_pci(struct pci_dev *dev,
        struct fb_videomode mode;
        int err = -1, vfreq, hfreq, pixclock;
 
+       err = aperture_remove_conflicting_pci_devices(dev, "i810fb");
+       if (err)
+               return err;
+
        info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev);
        if (!info)
                return -ENOMEM;
@@ -2044,7 +2049,7 @@ static int i810fb_init_pci(struct pci_dev *dev,
                return err;
        }
 
-       i810_init_device(par);        
+       i810_init_device(par);
 
        info->screen_base = par->fb.virtual;
        info->fbops = &par->i810fb_ops;
@@ -2064,21 +2069,21 @@ static int i810fb_init_pci(struct pci_dev *dev,
        err = register_framebuffer(info);
 
        if (err < 0) {
-               i810fb_release_resource(info, par); 
+               i810fb_release_resource(info, par);
                printk("i810fb_init: cannot register framebuffer device\n");
-               return err;  
-       }   
+               return err;
+       }
 
        pci_set_drvdata(dev, info);
        pixclock = 1000000000/(info->var.pixclock);
        pixclock *= 1000;
-       hfreq = pixclock/(info->var.xres + info->var.left_margin + 
+       hfreq = pixclock/(info->var.xres + info->var.left_margin +
                          info->var.hsync_len + info->var.right_margin);
        vfreq = hfreq/(info->var.yres + info->var.upper_margin +
                       info->var.vsync_len + info->var.lower_margin);
 
        printk("I810FB: fb%d         : %s v%d.%d.%d%s\n"
-              "I810FB: Video RAM   : %dK\n" 
+              "I810FB: Video RAM   : %dK\n"
               "I810FB: Monitor     : H: %d-%d KHz V: %d-%d Hz\n"
               "I810FB: Mode        : %dx%d-%dbpp@%dHz\n",
               info->node,
@@ -2086,7 +2091,7 @@ static int i810fb_init_pci(struct pci_dev *dev,
               VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
               (int) par->fb.size>>10, info->monspecs.hfmin/1000,
               info->monspecs.hfmax/1000, info->monspecs.vfmin,
-              info->monspecs.vfmax, info->var.xres, 
+              info->monspecs.vfmax, info->var.xres,
               info->var.yres, info->var.bits_per_pixel, vfreq);
        return 0;
 }
@@ -2095,7 +2100,7 @@ static int i810fb_init_pci(struct pci_dev *dev,
  *                     De-initialization                        *
  ***************************************************************/
 
-static void i810fb_release_resource(struct fb_info *info, 
+static void i810fb_release_resource(struct fb_info *info,
                                    struct i810fb_par *par)
 {
        struct gtt_data *gtt = &par->i810_gtt;
@@ -2128,10 +2133,10 @@ static void i810fb_remove_pci(struct pci_dev *dev)
        struct fb_info *info = pci_get_drvdata(dev);
        struct i810fb_par *par = info->par;
 
-       unregister_framebuffer(info);  
+       unregister_framebuffer(info);
        i810fb_release_resource(info, par);
        printk("cleanup_module:  unloaded i810 framebuffer device\n");
-}                                                      
+}
 
 #ifndef MODULE
 static int i810fb_init(void)
@@ -2144,7 +2149,7 @@ static int i810fb_init(void)
 
        return pci_register_driver(&i810fb_driver);
 }
-#endif 
+#endif
 
 /*********************************************************************
  *                          Modularization                           *
@@ -2161,7 +2166,7 @@ static int i810fb_init(void)
 }
 
 module_param(vram, int, 0);
-MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" 
+MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB"
                 " (default=4)");
 module_param(voffset, int, 0);
 MODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer "
@@ -2186,7 +2191,7 @@ module_param(vsync1, int, 0);
 MODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz"
                 " (default = 50)");
 module_param(vsync2, int, 0);
-MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" 
+MODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz"
                 " (default = 60)");
 module_param(accel, bool, 0);
 MODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)");
@@ -2208,7 +2213,7 @@ MODULE_PARM_DESC(mode_option, "Specify initial video mode");
 MODULE_AUTHOR("Tony A. Daplas");
 MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
                   " compatible cards");
-MODULE_LICENSE("GPL"); 
+MODULE_LICENSE("GPL");
 
 static void __exit i810fb_exit(void)
 {
index 16f272a508112c91a6381f2d08081ced787de643..d7edb9c5d3a3feb0e176f2e05bd11d45bab10c36 100644 (file)
@@ -16,6 +16,7 @@
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -86,7 +87,7 @@ enum {
        SSTATUS = 36, /* 0x90 */
        PRC     = 37, /* 0x94 */
 
-#if 0  
+#if 0
        /* PCI Registers */
        DVID    = 0x00000000L,
        SC      = 0x00000004L,
@@ -103,8 +104,8 @@ enum {
        PDATA   = 0x04,
        PPMASK  = 0x08,
        PADDRR  = 0x0c,
-       PIDXLO  = 0x10, 
-       PIDXHI  = 0x14, 
+       PIDXLO  = 0x10,
+       PIDXHI  = 0x14,
        PIDXDATA= 0x18,
        PIDXCTL = 0x1c
 };
@@ -131,7 +132,7 @@ enum {
        SYSCLKC         = 0x18, /* () System Clock C */
        /*
         * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
-        * c is charge pump bias which depends on the VCO frequency  
+        * c is charge pump bias which depends on the VCO frequency
         */
        PIXM0           = 0x20, /* () Pixel M 0 */
        PIXN0           = 0x21, /* () Pixel N 0 */
@@ -320,7 +321,7 @@ struct imstt_par {
        __u32 ramdac;
        __u32 palette[16];
 };
+
 enum {
        IBM = 0,
        TVP = 1
@@ -373,7 +374,7 @@ static struct imstt_regvals tvp_reg_init_17 = {
 
 static struct imstt_regvals tvp_reg_init_18 = {
        1152,
-       0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
+       0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000,
        0xfd, 0x3a, 0xf1,
        { 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
 };
@@ -856,10 +857,10 @@ imsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 }
 
 static int
-imsttfb_set_par(struct fb_info *info) 
+imsttfb_set_par(struct fb_info *info)
 {
        struct imstt_par *par = info->par;
-               
+
        if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))
                return -EINVAL;
 
@@ -930,7 +931,7 @@ imsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
        return 0;
 }
 
-static int 
+static int
 imsttfb_blank(int blank, struct fb_info *info)
 {
        struct imstt_par *par = info->par;
@@ -986,7 +987,7 @@ imsttfb_blank(int blank, struct fb_info *info)
 
 static void
 imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{ 
+{
        struct imstt_par *par = info->par;
        __u32 Bpp, line_pitch, bgc, dx, dy, width, height;
 
@@ -1192,7 +1193,7 @@ imstt_set_cursor(struct imstt_par *par, struct fb_image *d, int on)
        }
 }
 
-static int 
+static int
 imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
        struct imstt_par *par = info->par;
@@ -1200,7 +1201,7 @@ imsttfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
        if (cursor->dest == NULL && cursor->rop == ROP_XOR)
                return 1;
-       
+
        imstt_set_cursor(info, cursor, 0);
 
        if (flags & FB_CUR_SETPOS) {
@@ -1469,8 +1470,13 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct imstt_par *par;
        struct fb_info *info;
        struct device_node *dp;
-       int ret = -ENOMEM;
-       
+       int ret;
+
+       ret = aperture_remove_conflicting_pci_devices(pdev, "imsttfb");
+       if (ret)
+               return ret;
+       ret = -ENOMEM;
+
        dp = pci_device_to_OF_node(pdev);
        if(dp)
                printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp);
@@ -1619,7 +1625,7 @@ static int __init imsttfb_init(void)
 #endif
        return pci_register_driver(&imsttfb_pci_driver);
 }
+
 static void __exit imsttfb_exit(void)
 {
        pci_unregister_driver(&imsttfb_pci_driver);
index 5647fca8c49a26612e9e4686b0a3b26919c2eaa8..d4a2891a9a7acee21a3563529198e67961d1436c 100644 (file)
  *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>)
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -483,6 +484,10 @@ static int intelfb_pci_register(struct pci_dev *pdev,
 
        DBG_MSG("intelfb_pci_register\n");
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "intelfb");
+       if (err)
+               return err;
+
        num_registered++;
        if (num_registered != 1) {
                ERR_MSG("Attempted to register %d devices "
index d57772f96ad26718eb01c0ab83dd6f870364c889..b4b93054c5208fa4fda85d8202f54fb87006048b 100644 (file)
@@ -9,6 +9,7 @@
  * for more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -676,6 +677,10 @@ static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        unsigned long size;
        int err;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "kyrofb");
+       if (err)
+               return err;
+
        if ((err = pci_enable_device(pdev))) {
                printk(KERN_WARNING "kyrofb: Can't enable pdev: %d\n", err);
                return err;
index 236521b19daf7799f76a219585f827aeba385eaf..3e26346c05a2852beeba6c25027081749e3b97de 100644 (file)
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/version.h>
 
 #include "matroxfb_base.h"
@@ -2044,6 +2045,10 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm
        u_int32_t cmd;
        DBG(__func__)
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "matroxfb");
+       if (err)
+               return err;
+
        svid = pdev->subsystem_vendor;
        sid = pdev->subsystem_device;
        for (b = dev_list; b->vendor; b++) {
index a7508f5be343a654e615b45b17308ac888047656..96800c9c9cd9ee75783daac06433af9b95b699ae 100644 (file)
@@ -10,6 +10,7 @@
 
 #undef DEBUG
 
+#include <linux/aperture.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/uaccess.h>
@@ -999,6 +1000,10 @@ static int mb862xx_pci_probe(struct pci_dev *pdev,
        struct device *dev = &pdev->dev;
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "mb862xxfb");
+       if (ret)
+               return ret;
+
        ret = pci_enable_device(pdev);
        if (ret < 0) {
                dev_err(dev, "Cannot enable PCI device\n");
index 28d32cbf496b5554416ed5bfef95f05cfa55e9ee..93a2d2d1abe8f620a57f55e43ec8f3a71dec52ca 100644 (file)
@@ -23,9 +23,9 @@
  *
  * 0.3.3
  *  - Porting over to new fbdev api. (jsimmons)
- *  
+ *
  * 0.3.2
- *  - got rid of all floating point (dok) 
+ *  - got rid of all floating point (dok)
  *
  * 0.3.1
  *  - added module license (dok)
@@ -54,6 +54,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1154,14 +1155,14 @@ static int neofb_set_par(struct fb_info *info)
 
        switch (info->fix.accel) {
                case FB_ACCEL_NEOMAGIC_NM2200:
-               case FB_ACCEL_NEOMAGIC_NM2230: 
-               case FB_ACCEL_NEOMAGIC_NM2360: 
-               case FB_ACCEL_NEOMAGIC_NM2380: 
+               case FB_ACCEL_NEOMAGIC_NM2230:
+               case FB_ACCEL_NEOMAGIC_NM2360:
+               case FB_ACCEL_NEOMAGIC_NM2380:
                        neo2200_accel_init(info, &info->var);
                        break;
                default:
                        break;
-       }       
+       }
        return 0;
 }
 
@@ -1493,15 +1494,15 @@ neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        switch (info->fix.accel) {
                case FB_ACCEL_NEOMAGIC_NM2200:
-               case FB_ACCEL_NEOMAGIC_NM2230: 
-               case FB_ACCEL_NEOMAGIC_NM2360: 
+               case FB_ACCEL_NEOMAGIC_NM2230:
+               case FB_ACCEL_NEOMAGIC_NM2360:
                case FB_ACCEL_NEOMAGIC_NM2380:
                        neo2200_fillrect(info, rect);
                        break;
                default:
                        cfb_fillrect(info, rect);
                        break;
-       }       
+       }
 }
 
 static void
@@ -1509,15 +1510,15 @@ neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        switch (info->fix.accel) {
                case FB_ACCEL_NEOMAGIC_NM2200:
-               case FB_ACCEL_NEOMAGIC_NM2230: 
-               case FB_ACCEL_NEOMAGIC_NM2360: 
-               case FB_ACCEL_NEOMAGIC_NM2380: 
+               case FB_ACCEL_NEOMAGIC_NM2230:
+               case FB_ACCEL_NEOMAGIC_NM2360:
+               case FB_ACCEL_NEOMAGIC_NM2380:
                        neo2200_copyarea(info, area);
                        break;
                default:
                        cfb_copyarea(info, area);
                        break;
-       }       
+       }
 }
 
 static void
@@ -1536,20 +1537,20 @@ neofb_imageblit(struct fb_info *info, const struct fb_image *image)
        }
 }
 
-static int 
+static int
 neofb_sync(struct fb_info *info)
 {
        switch (info->fix.accel) {
                case FB_ACCEL_NEOMAGIC_NM2200:
-               case FB_ACCEL_NEOMAGIC_NM2230: 
-               case FB_ACCEL_NEOMAGIC_NM2360: 
-               case FB_ACCEL_NEOMAGIC_NM2380: 
+               case FB_ACCEL_NEOMAGIC_NM2230:
+               case FB_ACCEL_NEOMAGIC_NM2360:
+               case FB_ACCEL_NEOMAGIC_NM2380:
                        neo2200_sync(info);
                        break;
                default:
                        break;
        }
-       return 0;               
+       return 0;
 }
 
 /*
@@ -2029,6 +2030,10 @@ static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        DBG("neofb_probe");
 
+       err = aperture_remove_conflicting_pci_devices(dev, "neofb");
+       if (err)
+               return err;
+
        err = pci_enable_device(dev);
        if (err)
                return err;
index a372a183c1f0196d6ad74a22a1634ba52aa22edf..329e2e8133c6937095ff75fbf22d60d893828a2d 100644 (file)
@@ -9,6 +9,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1276,11 +1277,15 @@ static int nvidiafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
        struct nvidia_par *par;
        struct fb_info *info;
        unsigned short cmd;
-
+       int ret;
 
        NVTRACE_ENTER();
        assert(pd != NULL);
 
+       ret = aperture_remove_conflicting_pci_devices(pd, "nvidiafb");
+       if (ret)
+               return ret;
+
        info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
 
        if (!info)
index d3be2c64f1c08dce2b1c10eb0be7ee397e030bff..bc80d8498aeb0b60c70a1cafe343f85966fad02c 100644 (file)
@@ -27,6 +27,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -1516,6 +1517,10 @@ static int pm2fb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        int err;
        int retval = -ENXIO;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "pm2fb");
+       if (err)
+               return err;
+
        err = pci_enable_device(pdev);
        if (err) {
                printk(KERN_WARNING "pm2fb: Can't enable pdev: %d\n", err);
index a8faf46adeb16083865904d3be0fefdcf11b8078..ba69846d444f532c700b2732ad665e9dfa210b0d 100644 (file)
@@ -22,6 +22,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1315,6 +1316,10 @@ static int pm3fb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        int err;
        int retval = -ENXIO;
 
+       err = aperture_remove_conflicting_pci_devices(dev, "pm3fb");
+       if (err)
+               return err;
+
        err = pci_enable_device(dev);
        if (err) {
                printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
index f4add36cb5f4d6fa64ecab6184a7f602d8d67da2..b73ad14efa201c0b6d6f648194f712f85c431bde 100644 (file)
@@ -45,6 +45,7 @@
 
 #undef DEBUG
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -942,6 +943,10 @@ static int pvr2fb_pci_probe(struct pci_dev *pdev,
 {
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "pvrfb");
+       if (ret)
+               return ret;
+
        ret = pci_enable_device(pdev);
        if (ret) {
                printk(KERN_ERR "pvr2fb: PCI enable failed\n");
index 84d5e23ad7d38c6e0fea68671327a1bbe5cac41c..0ea74e28f9152e528fa42c22b0183e6e4e3e2245 100644 (file)
@@ -29,6 +29,7 @@
  *     doublescan modes are broken
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -474,7 +475,7 @@ static inline void reverse_order(u32 *l)
  * DESCRIPTiON:
  * Loads cursor image based on a monochrome source and mask bitmap.  The
  * image bits determines the color of the pixel, 0 for background, 1 for
- * foreground.  Only the affected region (as determined by @w and @h 
+ * foreground.  Only the affected region (as determined by @w and @h
  * parameters) will be updated.
  *
  * CALLED FROM:
@@ -494,7 +495,7 @@ static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
        for (i = 0; i < h; i++) {
                b = *data++;
                reverse_order(&b);
-               
+
                for (j = 0; j < w/2; j++) {
                        tmp = 0;
 #if defined (__BIG_ENDIAN)
@@ -562,7 +563,7 @@ static void riva_rclut(RIVA_HW_INST *chip,
                       unsigned char regnum, unsigned char *red,
                       unsigned char *green, unsigned char *blue)
 {
-       
+
        VGA_WR08(chip->PDIO, 0x3c7, regnum);
        *red = VGA_RD08(chip->PDIO, 0x3c9);
        *green = VGA_RD08(chip->PDIO, 0x3c9);
@@ -673,7 +674,7 @@ static int riva_load_video_mode(struct fb_info *info)
        int rc;
        struct riva_par *par = info->par;
        struct riva_regs newmode;
-       
+
        NVTRACE_ENTER();
        /* time to calculate */
        rivafb_blank(FB_BLANK_NORMAL, info);
@@ -717,7 +718,7 @@ static int riva_load_video_mode(struct fb_info *info)
                hBlankEnd = hTotal + 4;
        }
 
-       newmode.crtc[0x0] = Set8Bits (hTotal); 
+       newmode.crtc[0x0] = Set8Bits (hTotal);
        newmode.crtc[0x1] = Set8Bits (hDisplay);
        newmode.crtc[0x2] = Set8Bits (hBlankStart);
        newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
@@ -748,20 +749,20 @@ static int riva_load_video_mode(struct fb_info *info)
                | SetBitField(vStart,10:10,2:2)
                | SetBitField(vDisplay,10:10,1:1)
                | SetBitField(vTotal,10:10,0:0);
-       newmode.ext.horiz  = SetBitField(hTotal,8:8,0:0) 
+       newmode.ext.horiz  = SetBitField(hTotal,8:8,0:0)
                | SetBitField(hDisplay,8:8,1:1)
                | SetBitField(hBlankStart,8:8,2:2)
                | SetBitField(hStart,8:8,3:3);
        newmode.ext.extra  = SetBitField(vTotal,11:11,0:0)
                | SetBitField(vDisplay,11:11,2:2)
                | SetBitField(vStart,11:11,4:4)
-               | SetBitField(vBlankStart,11:11,6:6); 
+               | SetBitField(vBlankStart,11:11,6:6);
 
        if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
                int tmp = (hTotal >> 1) & ~1;
                newmode.ext.interlace = Set8Bits(tmp);
                newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4);
-       } else 
+       } else
                newmode.ext.interlace = 0xff; /* interlace off */
 
        if (par->riva.Architecture >= NV_ARCH_10)
@@ -774,7 +775,7 @@ static int riva_load_video_mode(struct fb_info *info)
        if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
                newmode.misc_output &= ~0x80;
        else
-               newmode.misc_output |= 0x80;    
+               newmode.misc_output |= 0x80;
 
        rc = CalcStateExt(&par->riva, &newmode.ext, par->pdev, bpp, width,
                          hDisplaySize, height, dotClock);
@@ -841,7 +842,7 @@ static void riva_update_var(struct fb_var_screeninfo *var,
 }
 
 /**
- * rivafb_do_maximize - 
+ * rivafb_do_maximize -
  * @info: pointer to fb_info object containing info for current riva board
  * @var: standard kernel fb changeable data
  * @nom: nom
@@ -852,7 +853,7 @@ static void riva_update_var(struct fb_var_screeninfo *var,
  *
  * RETURNS:
  * -EINVAL on failure, 0 on success
- * 
+ *
  *
  * CALLED FROM:
  * rivafb_check_var()
@@ -916,14 +917,14 @@ static int rivafb_do_maximize(struct fb_info *info,
                        return -EINVAL;
                }
        }
-       
+
        if (var->xres_virtual * nom / den >= 8192) {
                printk(KERN_WARNING PFX
                       "virtual X resolution (%d) is too high, lowering to %d\n",
                       var->xres_virtual, 8192 * den / nom - 16);
                var->xres_virtual = 8192 * den / nom - 16;
        }
-       
+
        if (var->xres_virtual < var->xres) {
                printk(KERN_ERR PFX
                       "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
@@ -1010,7 +1011,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
                break;
        case 6:
                rc = 64;        /* 64 entries (2^6), 16 bpp, RGB565 */
-               break;          
+               break;
        default:
                /* should not occur */
                break;
@@ -1042,7 +1043,7 @@ static int rivafb_open(struct fb_info *info, int user)
                /* vgaHWunlock() + riva unlock (0x7F) */
                CRTCout(par, 0x11, 0xFF);
                par->riva.LockUnlock(&par->riva, 0);
-       
+
                riva_save_state(par, &par->initial_state);
        }
        par->ref_count++;
@@ -1082,7 +1083,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        struct riva_par *par = info->par;
        int nom, den;           /* translating from pixels->bytes */
        int mode_valid = 0;
-       
+
        NVTRACE_ENTER();
        if (!var->pixclock)
                return -EINVAL;
@@ -1176,7 +1177,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        if (var->yoffset > var->yres_virtual - var->yres)
                var->yoffset = var->yres_virtual - var->yres - 1;
 
-       var->red.msb_right = 
+       var->red.msb_right =
            var->green.msb_right =
            var->blue.msb_right =
            var->transp.offset = var->transp.length = var->transp.msb_right = 0;
@@ -1198,7 +1199,7 @@ static int rivafb_set_par(struct fb_info *info)
                goto out;
        if(!(info->flags & FBINFO_HWACCEL_DISABLED))
                riva_setup_accel(info);
-       
+
        par->cursor_reset = 1;
        info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
        info->fix.visual = (info->var.bits_per_pixel == 8) ?
@@ -1486,7 +1487,7 @@ static inline void convert_bgcolor_16(u32 *col)
  * CALLED FROM:
  * framebuffer hook
  */
-static void rivafb_imageblit(struct fb_info *info, 
+static void rivafb_imageblit(struct fb_info *info,
                             const struct fb_image *image)
 {
        struct riva_par *par = info->par;
@@ -1515,7 +1516,7 @@ static void rivafb_imageblit(struct fb_info *info,
                        bgx = par->palette[image->bg_color];
                }
                if (info->var.green.length == 6)
-                       convert_bgcolor_16(&bgx);       
+                       convert_bgcolor_16(&bgx);
                break;
        }
 
@@ -1612,7 +1613,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
                u8 *dat = (u8 *) cursor->image.data;
                u8 *msk = (u8 *) cursor->mask;
                u8 *src;
-               
+
                src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC);
 
                if (src) {
@@ -1683,7 +1684,7 @@ static const struct fb_ops riva_fb_ops = {
        .fb_fillrect    = rivafb_fillrect,
        .fb_copyarea    = rivafb_copyarea,
        .fb_imageblit   = rivafb_imageblit,
-       .fb_cursor      = rivafb_cursor,        
+       .fb_cursor      = rivafb_cursor,
        .fb_sync        = rivafb_sync,
 };
 
@@ -1713,7 +1714,7 @@ static int riva_set_fbinfo(struct fb_info *info)
        info->pseudo_palette = par->pseudo_palette;
 
        cmap_len = riva_get_cmap_len(&info->var);
-       fb_alloc_cmap(&info->cmap, cmap_len, 0);        
+       fb_alloc_cmap(&info->cmap, cmap_len, 0);
 
        info->pixmap.size = 8 * 1024;
        info->pixmap.buf_align = 4;
@@ -1898,6 +1899,10 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
        NVTRACE_ENTER();
        assert(pd != NULL);
 
+       ret = aperture_remove_conflicting_pci_devices(pd, "rivafb");
+       if (ret)
+               return ret;
+
        info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev);
        if (!info) {
                ret = -ENOMEM;
@@ -1929,7 +1934,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
 
        default_par->Chipset = (pd->vendor << 16) | pd->device;
        printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
-       
+
        if(default_par->riva.Architecture == 0) {
                printk(KERN_ERR PFX "unknown NV_ARCH\n");
                ret=-ENODEV;
@@ -1947,7 +1952,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
        if (flatpanel == 1)
                printk(KERN_INFO PFX "flatpanel support enabled\n");
        default_par->forceCRTC = forceCRTC;
-       
+
        rivafb_fix.mmio_len = pci_resource_len(pd, 0);
        rivafb_fix.smem_len = pci_resource_len(pd, 1);
 
@@ -1959,7 +1964,7 @@ static int rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent)
                cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
                pci_write_config_word(pd, PCI_COMMAND, cmd);
        }
-       
+
        rivafb_fix.mmio_start = pci_resource_start(pd, 0);
        rivafb_fix.smem_start = pci_resource_start(pd, 1);
 
@@ -2058,7 +2063,7 @@ err_iounmap_screen_base:
 #endif
        iounmap(info->screen_base);
 err_iounmap_pramin:
-       if (default_par->riva.Architecture == NV_ARCH_03) 
+       if (default_par->riva.Architecture == NV_ARCH_03)
                iounmap(default_par->riva.PRAMIN);
 err_iounmap_ctrl_base:
        iounmap(default_par->ctrl_base);
@@ -2077,7 +2082,7 @@ static void rivafb_remove(struct pci_dev *pd)
 {
        struct fb_info *info = pci_get_drvdata(pd);
        struct riva_par *par = info->par;
-       
+
        NVTRACE_ENTER();
 
 #ifdef CONFIG_FB_RIVA_I2C
@@ -2117,11 +2122,11 @@ static int rivafb_setup(char *options)
        while ((this_opt = strsep(&options, ",")) != NULL) {
                if (!strncmp(this_opt, "forceCRTC", 9)) {
                        char *p;
-                       
+
                        p = this_opt + 9;
-                       if (!*p || !*(++p)) continue; 
+                       if (!*p || !*(++p)) continue;
                        forceCRTC = *p - '0';
-                       if (forceCRTC < 0 || forceCRTC > 1) 
+                       if (forceCRTC < 0 || forceCRTC > 1)
                                forceCRTC = -1;
                } else if (!strncmp(this_opt, "flatpanel", 9)) {
                        flatpanel = 1;
index 5069f6f67923f81532f5326532b473f4e9450958..1882408b2d13707c68650a379392a39195267820 100644 (file)
@@ -11,6 +11,7 @@
  * which is based on the code of neofb.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1131,6 +1132,10 @@ static int s3_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
+       rc = aperture_remove_conflicting_pci_devices(dev, "s3fb");
+       if (rc)
+               return rc;
+
        /* Allocate and fill driver data structure */
        info = framebuffer_alloc(sizeof(struct s3fb_info), &(dev->dev));
        if (!info)
index 8114c921ceb8baa11e39a6546f1813d8a46471a0..b7818b652698f079ba2500fd963bb9c89efbd7ab 100644 (file)
@@ -41,6 +41,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -2176,6 +2177,10 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        DBG("savagefb_probe");
 
+       err = aperture_remove_conflicting_pci_devices(dev, "savagefb");
+       if (err)
+               return err;
+
        info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
        if (!info)
                return -ENOMEM;
index f28fd69d5eb75919920465ae533ce532633dd7cf..7114c5c17c9121d3ead5516d9fcfa0fc52d9c4cd 100644 (file)
@@ -19,6 +19,7 @@
  * which is (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
@@ -5849,6 +5850,10 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if(sisfb_off)
                return -ENXIO;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "sisfb");
+       if (ret)
+               return ret;
+
        sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
        if(!sis_fb_info)
                return -ENOMEM;
index 8ab9a3fbd281635c54bbd466070e3076c10a5545..a10f1057293b40d7dc30704f6521a6d283725c88 100644 (file)
  *  The primary goal is to remove the console code from fbdev and place it
  *  into fbcon.c. This reduces the code and makes writing a new fbdev driver
  *  easy since the author doesn't need to worry about console internals. It
- *  also allows the ability to run fbdev without a console/tty system on top 
- *  of it. 
+ *  also allows the ability to run fbdev without a console/tty system on top
+ *  of it.
  *
  *  First the roles of struct fb_info and struct display have changed. Struct
  *  display will go away. The way the new framebuffer console code will
- *  work is that it will act to translate data about the tty/console in 
+ *  work is that it will act to translate data about the tty/console in
  *  struct vc_data to data in a device independent way in struct fb_info. Then
- *  various functions in struct fb_ops will be called to store the device 
- *  dependent state in the par field in struct fb_info and to change the 
+ *  various functions in struct fb_ops will be called to store the device
+ *  dependent state in the par field in struct fb_info and to change the
  *  hardware to that state. This allows a very clean separation of the fbdev
  *  layer from the console layer. It also allows one to use fbdev on its own
- *  which is a bounus for embedded devices. The reason this approach works is  
+ *  which is a bounus for embedded devices. The reason this approach works is
  *  for each framebuffer device when used as a tty/console device is allocated
- *  a set of virtual terminals to it. Only one virtual terminal can be active 
- *  per framebuffer device. We already have all the data we need in struct 
+ *  a set of virtual terminals to it. Only one virtual terminal can be active
+ *  per framebuffer device. We already have all the data we need in struct
  *  vc_data so why store a bunch of colormaps and other fbdev specific data
- *  per virtual terminal. 
+ *  per virtual terminal.
  *
  *  As you can see doing this makes the con parameter pretty much useless
- *  for struct fb_ops functions, as it should be. Also having struct  
- *  fb_var_screeninfo and other data in fb_info pretty much eliminates the 
+ *  for struct fb_ops functions, as it should be. Also having struct
+ *  fb_var_screeninfo and other data in fb_info pretty much eliminates the
  *  need for get_fix and get_var. Once all drivers use the fix, var, and cmap
  *  fbcon can be written around these fields. This will also eliminate the
  *  need to regenerate struct fb_var_screeninfo, struct fb_fix_screeninfo
  *  struct fb_cmap every time get_var, get_fix, get_cmap functions are called
- *  as many drivers do now. 
+ *  as many drivers do now.
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 static char *mode_option;
 
 /*
- *  If your driver supports multiple boards, you should make the  
- *  below data types arrays, or allocate them dynamically (using kmalloc()). 
- */ 
+ *  If your driver supports multiple boards, you should make the
+ *  below data types arrays, or allocate them dynamically (using kmalloc()).
+ */
 
-/* 
+/*
  * This structure defines the hardware state of the graphics card. Normally
  * you place this in a header file in linux/include/video. This file usually
  * also includes register information. That allows other driver subsystems
- * and userland applications the ability to use the same header file to 
- * avoid duplicate work and easy porting of software. 
+ * and userland applications the ability to use the same header file to
+ * avoid duplicate work and easy porting of software.
  */
 struct xxx_par;
 
 /*
  * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
  * if we don't use modedb. If we do use modedb see xxxfb_init how to use it
- * to get a fb_var_screeninfo. Otherwise define a default var as well. 
+ * to get a fb_var_screeninfo. Otherwise define a default var as well.
  */
 static const struct fb_fix_screeninfo xxxfb_fix = {
-       .id =           "FB's name", 
+       .id =           "FB's name",
        .type =         FB_TYPE_PACKED_PIXELS,
        .visual =       FB_VISUAL_PSEUDOCOLOR,
        .xpanstep =     1,
        .ypanstep =     1,
-       .ywrapstep =    1, 
+       .ywrapstep =    1,
        .accel =        FB_ACCEL_NONE,
 };
 
     /*
-     *         Modern graphical hardware not only supports pipelines but some 
+     *         Modern graphical hardware not only supports pipelines but some
      *  also support multiple monitors where each display can have
-     *  its own unique data. In this case each display could be  
-     *  represented by a separate framebuffer device thus a separate 
+     *  its own unique data. In this case each display could be
+     *  represented by a separate framebuffer device thus a separate
      *  struct fb_info. Now the struct xxx_par represents the graphics
-     *  hardware state thus only one exist per card. In this case the 
-     *  struct xxx_par for each graphics card would be shared between 
-     *  every struct fb_info that represents a framebuffer on that card. 
-     *  This allows when one display changes it video resolution (info->var) 
+     *  hardware state thus only one exist per card. In this case the
+     *  struct xxx_par for each graphics card would be shared between
+     *  every struct fb_info that represents a framebuffer on that card.
+     *  This allows when one display changes it video resolution (info->var)
      *  the other displays know instantly. Each display can always be
      *  aware of the entire hardware state that affects it because they share
      *  the same xxx_par struct. The other side of the coin is multiple
      *  graphics cards that pass data around until it is finally displayed
      *  on one monitor. Such examples are the voodoo 1 cards and high end
      *  NUMA graphics servers. For this case we have a bunch of pars, each
-     *  one that represents a graphics state, that belong to one struct 
+     *  one that represents a graphics state, that belong to one struct
      *  fb_info. Their you would want to have *par point to a array of device
-     *  states and have each struct fb_ops function deal with all those 
+     *  states and have each struct fb_ops function deal with all those
      *  states. I hope this covers every possible hardware design. If not
-     *  feel free to send your ideas at jsimmons@users.sf.net 
+     *  feel free to send your ideas at jsimmons@users.sf.net
      */
 
     /*
-     *  If your driver supports multiple boards or it supports multiple 
-     *  framebuffers, you should make these arrays, or allocate them 
+     *  If your driver supports multiple boards or it supports multiple
+     *  framebuffers, you should make these arrays, or allocate them
      *  dynamically using framebuffer_alloc() and free them with
      *  framebuffer_release().
-     */ 
+     */
 static struct fb_info info;
 
-    /* 
+    /*
      * Each one represents the state of the hardware. Most hardware have
-     * just one hardware state. These here represent the default state(s). 
+     * just one hardware state. These here represent the default state(s).
      */
 static struct xxx_par __initdata current_par;
 
@@ -136,12 +137,12 @@ static struct xxx_par __initdata current_par;
  *                  first accessed.
  *     @info: frame buffer structure that represents a single frame buffer
  *     @user: tell us if the userland (value=1) or the console is accessing
- *            the framebuffer. 
+ *            the framebuffer.
  *
  *     This function is the first function called in the framebuffer api.
- *     Usually you don't need to provide this function. The case where it 
+ *     Usually you don't need to provide this function. The case where it
  *     is used is to change from a text mode hardware state to a graphics
- *     mode state. 
+ *     mode state.
  *
  *     Returns negative errno on error, or zero on success.
  */
@@ -151,13 +152,13 @@ static int xxxfb_open(struct fb_info *info, int user)
 }
 
 /**
- *     xxxfb_release - Optional function. Called when the framebuffer 
- *                     device is closed. 
+ *     xxxfb_release - Optional function. Called when the framebuffer
+ *                     device is closed.
  *     @info: frame buffer structure that represents a single frame buffer
  *     @user: tell us if the userland (value=1) or the console is accessing
- *            the framebuffer. 
- *     
- *     Thus function is called when we close /dev/fb or the framebuffer 
+ *            the framebuffer.
+ *
+ *     Thus function is called when we close /dev/fb or the framebuffer
  *     console system is released. Usually you don't need this function.
  *     The case where it is usually used is to go from a graphics state
  *     to a text mode state.
@@ -170,17 +171,17 @@ static int xxxfb_release(struct fb_info *info, int user)
 }
 
 /**
- *      xxxfb_check_var - Optional function. Validates a var passed in. 
+ *      xxxfb_check_var - Optional function. Validates a var passed in.
  *      @var: frame buffer variable screen structure
- *      @info: frame buffer structure that represents a single frame buffer 
+ *      @info: frame buffer structure that represents a single frame buffer
  *
  *     Checks to see if the hardware supports the state requested by
- *     var passed in. This function does not alter the hardware state!!! 
- *     This means the data stored in struct fb_info and struct xxx_par do 
- *      not change. This includes the var inside of struct fb_info. 
+ *     var passed in. This function does not alter the hardware state!!!
+ *     This means the data stored in struct fb_info and struct xxx_par do
+ *      not change. This includes the var inside of struct fb_info.
  *     Do NOT change these. This function can be called on its own if we
- *     intent to only test a mode and not actually set it. The stuff in 
- *     modedb.c is a example of this. If the var passed in is slightly 
+ *     intent to only test a mode and not actually set it. The stuff in
+ *     modedb.c is a example of this. If the var passed in is slightly
  *     off by what the hardware can support then we alter the var PASSED in
  *     to what we can do.
  *
@@ -208,7 +209,7 @@ static int xxxfb_release(struct fb_info *info, int user)
 static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
     /* ... */
-    return 0;          
+    return 0;
 }
 
 /**
@@ -217,9 +218,9 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
  *
  *     Using the fb_var_screeninfo in fb_info we set the resolution of the
  *     this particular framebuffer. This function alters the par AND the
- *     fb_fix_screeninfo stored in fb_info. It doesn't not alter var in 
+ *     fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
  *     fb_info since we are using that data. This means we depend on the
- *     data in var inside fb_info to be supported by the hardware. 
+ *     data in var inside fb_info to be supported by the hardware.
  *
  *      This function is also used to recover/restore the hardware to a
  *      known working state.
@@ -254,20 +255,20 @@ static int xxxfb_set_par(struct fb_info *info)
 {
     struct xxx_par *par = info->par;
     /* ... */
-    return 0;  
+    return 0;
 }
 
 /**
  *     xxxfb_setcolreg - Optional function. Sets a color register.
- *      @regno: Which register in the CLUT we are programming 
- *      @red: The red value which can be up to 16 bits wide 
- *     @green: The green value which can be up to 16 bits wide 
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *     @green: The green value which can be up to 16 bits wide
  *     @blue:  The blue value which can be up to 16 bits wide.
  *     @transp: If supported, the alpha value which can be up to 16 bits wide.
  *      @info: frame buffer info structure
- * 
+ *
  *     Set a single color register. The values supplied have a 16 bit
- *     magnitude which needs to be scaled in this function for the hardware. 
+ *     magnitude which needs to be scaled in this function for the hardware.
  *     Things to take into consideration are how many color registers, if
  *     any, are supported with the current color visual. With truecolor mode
  *     no color palettes are supported. Here a pseudo palette is created
@@ -275,8 +276,8 @@ static int xxxfb_set_par(struct fb_info *info)
  *     pseudocolor mode we have a limited color palette. To deal with this
  *     we can program what color is displayed for a particular pixel value.
  *     DirectColor is similar in that we can program each color field. If
- *     we have a static colormap we don't need to implement this function. 
- * 
+ *     we have a static colormap we don't need to implement this function.
+ *
  *     Returns negative errno on error, or zero on success.
  */
 static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
@@ -440,7 +441,7 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var,
 
 /**
  *      xxxfb_blank - NOT a required function. Blanks the display.
- *      @blank_mode: the blank mode we want. 
+ *      @blank_mode: the blank mode we want.
  *      @info: frame buffer structure that represents a single frame buffer
  *
  *      Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank.
@@ -469,22 +470,22 @@ static int xxxfb_blank(int blank_mode, struct fb_info *info)
 
 /*
  * We provide our own functions if we have hardware acceleration
- * or non packed pixel format layouts. If we have no hardware 
+ * or non packed pixel format layouts. If we have no hardware
  * acceleration, we can use a generic unaccelerated function. If using
- * a pack pixel format just use the functions in cfb_*.c. Each file 
+ * a pack pixel format just use the functions in cfb_*.c. Each file
  * has one of the three different accel functions we support.
  */
 
 /**
- *      xxxfb_fillrect - REQUIRED function. Can use generic routines if 
+ *      xxxfb_fillrect - REQUIRED function. Can use generic routines if
  *                      non acclerated hardware and packed pixel based.
- *                      Draws a rectangle on the screen.               
+ *                      Draws a rectangle on the screen.
  *
  *      @info: frame buffer structure that represents a single frame buffer
- *     @region: The structure representing the rectangular region we 
+ *     @region: The structure representing the rectangular region we
  *              wish to draw to.
  *
- *     This drawing operation places/removes a retangle on the screen 
+ *     This drawing operation places/removes a retangle on the screen
  *     depending on the rastering operation with the value of color which
  *     is in the current color depth format.
  */
@@ -492,13 +493,13 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
 {
 /*     Meaning of struct fb_fillrect
  *
- *     @dx: The x and y corrdinates of the upper left hand corner of the 
- *     @dy: area we want to draw to. 
+ *     @dx: The x and y corrdinates of the upper left hand corner of the
+ *     @dy: area we want to draw to.
  *     @width: How wide the rectangle is we want to draw.
  *     @height: How tall the rectangle is we want to draw.
- *     @color: The color to fill in the rectangle with. 
+ *     @color: The color to fill in the rectangle with.
  *     @rop: The raster operation. We can draw the rectangle with a COPY
- *           of XOR which provides erasing effect. 
+ *           of XOR which provides erasing effect.
  */
 }
 
@@ -514,7 +515,7 @@ void xxxfb_fillrect(struct fb_info *p, const struct fb_fillrect *region)
  *      This drawing operation copies a rectangular area from one area of the
  *     screen to another area.
  */
-void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) 
+void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 {
 /*
  *      @dx: The x and y coordinates of the upper left hand corner of the
@@ -530,28 +531,28 @@ void xxxfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 /**
  *      xxxfb_imageblit - REQUIRED function. Can use generic routines if
  *                        non acclerated hardware and packed pixel based.
- *                        Copies a image from system memory to the screen. 
+ *                        Copies a image from system memory to the screen.
  *
  *      @info: frame buffer structure that represents a single frame buffer
  *     @image: structure defining the image.
  *
- *      This drawing operation draws a image on the screen. It can be a 
+ *      This drawing operation draws a image on the screen. It can be a
  *     mono image (needed for font handling) or a color image (needed for
- *     tux). 
+ *     tux).
  */
-void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) 
+void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
 {
 /*
  *      @dx: The x and y coordinates of the upper left hand corner of the
  *     @dy: destination area to place the image on the screen.
  *      @width: How wide the image is we want to copy.
  *      @height: How tall the image is we want to copy.
- *      @fg_color: For mono bitmap images this is color data for     
+ *      @fg_color: For mono bitmap images this is color data for
  *      @bg_color: the foreground and background of the image to
  *                write directly to the frmaebuffer.
  *     @depth: How many bits represent a single pixel for this image.
  *     @data: The actual data used to construct the image on the display.
- *     @cmap: The colormap used for color images.   
+ *     @cmap: The colormap used for color images.
  */
 
 /*
@@ -578,13 +579,13 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image)
 int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 /*
- *      @set:  Which fields we are altering in struct fb_cursor 
- *     @enable: Disable or enable the cursor 
- *      @rop:  The bit operation we want to do. 
- *      @mask:  This is the cursor mask bitmap. 
+ *      @set:  Which fields we are altering in struct fb_cursor
+ *     @enable: Disable or enable the cursor
+ *      @rop:  The bit operation we want to do.
+ *      @mask:  This is the cursor mask bitmap.
  *      @dest:  A image of the area we are going to display the cursor.
- *             Used internally by the driver.   
- *      @hot:  The hot spot. 
+ *             Used internally by the driver.
+ *      @hot:  The hot spot.
  *     @image: The actual data for the cursor image.
  *
  *      NOTES ON FLAGS (cursor->set):
@@ -612,11 +613,11 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 }
 
 /**
- *     xxxfb_sync - NOT a required function. Normally the accel engine 
+ *     xxxfb_sync - NOT a required function. Normally the accel engine
  *                  for a graphics card take a specific amount of time.
  *                  Often we have to wait for the accelerator to finish
  *                  its operation before we can write to the framebuffer
- *                  so we can have consistent display output. 
+ *                  so we can have consistent display output.
  *
  *      @info: frame buffer structure that represents a single frame buffer
  *
@@ -664,8 +665,15 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
     struct fb_info *info;
     struct xxx_par *par;
     struct device *device = &dev->dev; /* or &pdev->dev */
-    int cmap_len, retval;      
-   
+    int cmap_len, retval;
+
+    /*
+     * Remove firmware-based drivers that create resource conflicts.
+     */
+    retval = aperture_remove_conflicting_pci_devices(pdev, "xxxfb");
+    if (retval)
+           return retval;
+
     /*
      * Dynamically allocate info and par
      */
@@ -677,11 +685,11 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 
     par = info->par;
 
-    /* 
+    /*
      * Here we set the screen_base to the virtual memory address
      * for the framebuffer. Usually we obtain the resource address
      * from the bus layer and then translate it to virtual memory
-     * space via ioremap. Consult ioport.h. 
+     * space via ioremap. Consult ioport.h.
      */
     info->screen_base = framebuffer_virtual_memory;
     info->fbops = &xxxfb_ops;
@@ -765,24 +773,24 @@ static int xxxfb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 
     /*
      * This should give a reasonable default video mode. The following is
-     * done when we can set a video mode. 
+     * done when we can set a video mode.
      */
     if (!mode_option)
-       mode_option = "640x480@60";             
+       mode_option = "640x480@60";
 
     retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
-  
+
     if (!retval || retval == 4)
-       return -EINVAL;                 
+       return -EINVAL;
 
     /* This has to be done! */
     if (fb_alloc_cmap(&info->cmap, cmap_len, 0))
        return -ENOMEM;
-       
-    /* 
-     * The following is done in the case of having hardware with a static 
-     * mode. If we are setting the mode ourselves we don't call this. 
-     */        
+
+    /*
+     * The following is done in the case of having hardware with a static
+     * mode. If we are setting the mode ourselves we don't call this.
+     */
     info->var = xxxfb_var;
 
     /*
index 092a1caa1208e191b016a0ec2097208e5e2d960f..3baf33635e65f8ac6b013c37dd261b7680d38773 100644 (file)
@@ -18,6 +18,7 @@
  * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips
  */
 
+#include <linux/aperture.h>
 #include <linux/io.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
@@ -1502,6 +1503,10 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
 
        dev_info(&pdev->dev, "Silicon Motion display driver.\n");
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "smtcfb");
+       if (err)
+               return err;
+
        err = pci_enable_device(pdev);  /* enable SMTC chip */
        if (err)
                return err;
index 27d4b0ace2d61bcf2b3ec84dd081535449eee92f..73ca2782ebfc8c534067a30dfd27fbf09eb544f0 100644 (file)
@@ -80,6 +80,7 @@
  * Includes
  */
 
+#include <linux/aperture.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -364,7 +365,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
        var->pixclock = KHZ2PICOS(freq);
-       
+
        if (var->vmode & FB_VMODE_INTERLACED)
                vBackPorch += (vBackPorch % 2);
        if (var->vmode & FB_VMODE_DOUBLE) {
@@ -382,7 +383,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
                printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel);
                return -EINVAL;
        }
-       
+
        /* validity tests */
        if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1  ||
            hSyncOff <= 1  || var->left_margin <= 2  || vSyncOn <= 0 ||
@@ -392,7 +393,7 @@ static int sstfb_check_var(struct fb_var_screeninfo *var,
 
        if (IS_VOODOO2(par)) {
                /* Voodoo 2 limits */
-               tiles_in_X = (var->xres + 63 ) / 64 * 2;                
+               tiles_in_X = (var->xres + 63 ) / 64 * 2;
 
                if (var->xres  > POW2(11) || yDim >= POW2(11)) {
                        printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
@@ -631,7 +632,7 @@ static int sstfb_set_par(struct fb_info *info)
        lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
                     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
 #endif
-       
+
        if (clipping) {
                sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
        /*
@@ -684,7 +685,7 @@ static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
            | (green << info->var.green.offset)
            | (blue  << info->var.blue.offset)
            | (transp << info->var.transp.offset);
-       
+
        par->palette[regno] = col;
 
        return 0;
@@ -773,7 +774,7 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        struct sstfb_par *par = info->par;
        u32 stride = info->fix.line_length;
-   
+
        if (!IS_VOODOO2(par))
                return;
 
@@ -795,17 +796,17 @@ static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
  * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
  */
 #if 0
-static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
+static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
        struct sstfb_par *par = info->par;
        u32 stride = info->fix.line_length;
 
        if (!IS_VOODOO2(par))
                return;
-       
+
        sst_write(BLTCLIPX, info->var.xres);
        sst_write(BLTCLIPY, info->var.yres);
-       
+
        sst_write(BLTDSTBASEADDR, 0);
        sst_write(BLTCOLOR, rect->color);
        sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
@@ -820,8 +821,8 @@ static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 
 
 
-/* 
- * get lfb size 
+/*
+ * get lfb size
  */
 static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
 {
@@ -859,8 +860,8 @@ static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
 }
 
 
-/* 
- * DAC detection routines 
+/*
+ * DAC detection routines
  */
 
 /* fbi should be idle, and fifo emty and mem disabled */
@@ -963,7 +964,7 @@ static int sst_detect_ics(struct fb_info *info)
  * see detect_dac
  */
 
-static int sst_set_pll_att_ti(struct fb_info *info, 
+static int sst_set_pll_att_ti(struct fb_info *info,
                const struct pll_timing *t, const int clock)
 {
        struct sstfb_par *par = info->par;
@@ -1326,6 +1327,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct sst_spec *spec;
        int err;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "sstfb");
+       if (err)
+               return err;
+
        /* Enable device in PCI config. */
        if ((err=pci_enable_device(pdev))) {
                printk(KERN_ERR "cannot enable device\n");
@@ -1338,10 +1343,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return -ENOMEM;
 
        pci_set_drvdata(pdev, info);
-       
+
        par  = info->par;
        fix  = &info->fix;
-       
+
        par->type = id->driver_data;
        spec = &voodoo_spec[par->type];
        f_ddprintk("found device : %s\n", spec->name);
@@ -1407,7 +1412,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
         * fact dithered to 16bit).
         */
        fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
-       
+
        fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
 
        if (sstfb_check_var(&info->var, info)) {
@@ -1419,7 +1424,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(KERN_ERR "sstfb: can't set default video mode.\n");
                goto fail;
        }
-       
+
        if (fb_alloc_cmap(&info->cmap, 256, 0)) {
                printk(KERN_ERR "sstfb: can't alloc cmap memory.\n");
                goto fail;
@@ -1465,7 +1470,7 @@ static void sstfb_remove(struct pci_dev *pdev)
 
        info = pci_get_drvdata(pdev);
        par = info->par;
-       
+
        device_remove_file(info->dev, &device_attrs[0]);
        sst_shutdown(info);
        iounmap(info->screen_base);
index 1d3bacd9d5acd80f916829b5a83970b1fd8993aa..81d59613ea1f67ae66cca76cef16f62af7c84dd9 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
+#include <linux/aperture.h>
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
@@ -123,6 +124,10 @@ static int s3d_pci_register(struct pci_dev *pdev,
        struct s3d_info *sp;
        int err;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "s3dfb");
+       if (err)
+               return err;
+
        err = pci_enable_device(pdev);
        if (err < 0) {
                printk(KERN_ERR "s3d: Cannot enable PCI device %s\n",
index 9daf17b111065761d456f1b0dca70ff4618eeff4..3a51b2a1480c1fd9eebfd4f034b1b69cabe90cfb 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  */
 
+#include <linux/aperture.h>
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
@@ -249,6 +250,10 @@ static int e3d_pci_register(struct pci_dev *pdev,
        unsigned int line_length;
        int err;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "e3dfb");
+       if (err)
+               return err;
+
        of_node = pci_device_to_OF_node(pdev);
        if (!of_node) {
                printk(KERN_ERR "e3d: Cannot find OF node of %s\n",
index 67e37a62b07c3fec02ac9b4518453d87c2ef746f..059e0174e139757260fbe3b807545ea2bd724aff 100644 (file)
@@ -64,6 +64,7 @@
  *
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -1376,6 +1377,10 @@ static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        struct fb_monspecs *specs;
        bool found;
 
+       err = aperture_remove_conflicting_pci_devices(pdev, "tdfxfb");
+       if (err)
+               return err;
+
        err = pci_enable_device(pdev);
        if (err) {
                printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
index ae0cf55406369c44c22865ab8afdf41d13c4ae4f..4600138e3bef9f88c9a49cf9ef9f82afe68f45b4 100644 (file)
@@ -12,6 +12,7 @@
  *  more details.
  */
 
+#include <linux/aperture.h>
 #include <linux/bitrev.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
@@ -106,6 +107,12 @@ static struct pci_driver tgafb_pci_driver = {
 static int tgafb_pci_register(struct pci_dev *pdev,
                              const struct pci_device_id *ent)
 {
+       int ret;
+
+       ret = aperture_remove_conflicting_pci_devices(pdev, "tgafb");
+       if (ret)
+               return ret;
+
        return tgafb_register(&pdev->dev);
 }
 
@@ -729,7 +736,7 @@ tgafb_mono_imageblit(struct fb_info *info, const struct fb_image *image)
 
                /* Handle another common case in which accel_putcs
                   generates a large bitmap, which happens to be aligned.
-                  Allow the tail to be misaligned.  This case is 
+                  Allow the tail to be misaligned.  This case is
                   interesting because we've not got to hold partial
                   bytes across the words being written.  */
 
@@ -908,9 +915,9 @@ tgafb_imageblit(struct fb_info *info, const struct fb_image *image)
 }
 
 /**
- *      tgafb_fillrect - REQUIRED function. Can use generic routines if 
+ *      tgafb_fillrect - REQUIRED function. Can use generic routines if
  *                       non acclerated hardware and packed pixel based.
- *                       Draws a rectangle on the screen.               
+ *                       Draws a rectangle on the screen.
  *
  *      @info: frame buffer structure that represents a single frame buffer
  *      @rect: structure defining the rectagle and operation.
@@ -1044,7 +1051,7 @@ tgafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 
 /* Handle the special case of copying entire lines, e.g. during scrolling.
    We can avoid a lot of needless computation in this case.  In the 8bpp
-   case we need to use the COPY64 registers instead of mask writes into 
+   case we need to use the COPY64 registers instead of mask writes into
    the frame buffer to achieve maximum performance.  */
 
 static inline void
@@ -1251,7 +1258,7 @@ copyarea_8bpp(struct fb_info *info, u32 dx, u32 dy, u32 sx, u32 sy,
 }
 
 static void
-tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 
+tgafb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
        unsigned long dx, dy, width, height, sx, sy, vxres, vyres;
        unsigned long line_length, bpp;
index 319131bd72cffa11a965f69588102012942d40fd..6813df793c494c9753b94446f908739a9e0d3bf6 100644 (file)
@@ -16,6 +16,7 @@
  *     timing value tweaking so it looks good on every monitor in every mode
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/fb.h>
 #include <linux/init.h>
@@ -1470,6 +1471,10 @@ static int trident_pci_probe(struct pci_dev *dev,
        int chip_id;
        bool found = false;
 
+       err = aperture_remove_conflicting_pci_devices(dev, "tridentfb");
+       if (err)
+               return err;
+
        err = pci_enable_device(dev);
        if (err)
                return err;
index ff61605b8764fc7262fd90d85f6360c93276d374..82b36dbb5b1a93b223419ae4465383a4d0f938da 100644 (file)
@@ -14,6 +14,7 @@
  *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -442,7 +443,11 @@ static int vml_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        struct vml_info *vinfo;
        struct fb_info *info;
        struct vml_par *par;
-       int err = 0;
+       int err;
+
+       err = aperture_remove_conflicting_pci_devices(dev, "vmlfb");
+       if (err)
+               return err;
 
        par = kzalloc(sizeof(*par), GFP_KERNEL);
        if (par == NULL)
index d21f68f3ee44c0d78772de4d536cde5be505d453..35cf51ae3292917386d8c12c175e7ab9bb5d29e0 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
- * 
+ *
  * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
  * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
  * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
- * archive for more details.  
+ * archive for more details.
  */
 
 #include <linux/module.h>
@@ -25,9 +25,6 @@
 #include <asm/io.h>
 #include <video/vga.h>
 
-#define VGA_FB_PHYS 0xA0000
-#define VGA_FB_PHYS_LEN 65536
-
 #define MODE_SKIP4     1
 #define MODE_8BPP      2
 #define MODE_CFB       4
@@ -70,7 +67,7 @@ static struct fb_var_screeninfo vga16fb_defined = {
        .yres           = 480,
        .xres_virtual   = 640,
        .yres_virtual   = 480,
-       .bits_per_pixel = 4,    
+       .bits_per_pixel = 4,
        .activate       = FB_ACTIVATE_TEST,
        .height         = -1,
        .width          = -1,
@@ -87,8 +84,8 @@ static struct fb_var_screeninfo vga16fb_defined = {
 /* name should not depend on EGA/VGA */
 static const struct fb_fix_screeninfo vga16fb_fix = {
        .id             = "VGA16 VGA",
-       .smem_start     = VGA_FB_PHYS,
-       .smem_len       = VGA_FB_PHYS_LEN,
+       .smem_start     = VGA_FB_PHYS_BASE,
+       .smem_len       = VGA_FB_PHYS_SIZE,
        .type           = FB_TYPE_VGA_PLANES,
        .type_aux       = FB_AUX_VGA_PLANES_VGA4,
        .visual         = FB_VISUAL_PSEUDOCOLOR,
@@ -120,7 +117,7 @@ static inline void rmw(volatile char __iomem *p)
 static inline int setmode(int mode)
 {
        int oldmode;
-       
+
        oldmode = vga_io_rgfx(VGA_GFX_MODE);
        vga_io_w(VGA_GFX_D, mode);
        return oldmode;
@@ -139,19 +136,19 @@ static inline void setmask(int mask)
        vga_io_w(VGA_GFX_D, mask);
 }
 
-/* Set the Data Rotate Register and return its old value. 
+/* Set the Data Rotate Register and return its old value.
    Bits 0-2 are rotate count, bits 3-4 are logical operation
    (0=NOP, 1=AND, 2=OR, 3=XOR). */
 static inline int setop(int op)
 {
        int oldop;
-       
+
        oldop = vga_io_rgfx(VGA_GFX_DATA_ROTATE);
        vga_io_w(VGA_GFX_D, op);
        return oldop;
 }
 
-/* Set the Enable Set/Reset Register and return its old value.  
+/* Set the Enable Set/Reset Register and return its old value.
    The code here always uses value 0xf for this register. */
 static inline int setsr(int sr)
 {
@@ -185,25 +182,25 @@ static inline void setindex(int index)
 }
 
 /* Check if the video mode is supported by the driver */
-static inline int check_mode_supported(void)
+static inline int check_mode_supported(const struct screen_info *si)
 {
        /* non-x86 architectures treat orig_video_isVGA as a boolean flag */
 #if defined(CONFIG_X86)
        /* only EGA and VGA in 16 color graphic mode are supported */
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_EGAC &&
-           screen_info.orig_video_isVGA != VIDEO_TYPE_VGAC)
+       if (si->orig_video_isVGA != VIDEO_TYPE_EGAC &&
+           si->orig_video_isVGA != VIDEO_TYPE_VGAC)
                return -ENODEV;
 
-       if (screen_info.orig_video_mode != 0x0D &&      /* 320x200/4 (EGA) */
-           screen_info.orig_video_mode != 0x0E &&      /* 640x200/4 (EGA) */
-           screen_info.orig_video_mode != 0x10 &&      /* 640x350/4 (EGA) */
-           screen_info.orig_video_mode != 0x12)        /* 640x480/4 (VGA) */
+       if (si->orig_video_mode != 0x0D &&      /* 320x200/4 (EGA) */
+           si->orig_video_mode != 0x0E &&      /* 640x200/4 (EGA) */
+           si->orig_video_mode != 0x10 &&      /* 640x350/4 (EGA) */
+           si->orig_video_mode != 0x12)        /* 640x480/4 (VGA) */
                return -ENODEV;
 #endif
        return 0;
 }
 
-static void vga16fb_pan_var(struct fb_info *info, 
+static void vga16fb_pan_var(struct fb_info *info,
                            struct fb_var_screeninfo *var)
 {
        struct vga16fb_par *par = info->par;
@@ -296,7 +293,7 @@ static void vga16fb_clock_chip(struct vga16fb_par *par,
        par->clkdiv = best->seq_clock_mode;
        *pixclock = (best->pixclock * div) / mul;
 }
-                              
+
 #define FAIL(X) return -EINVAL
 
 static int vga16fb_open(struct fb_info *info, int user)
@@ -511,7 +508,7 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
                par->misc &= ~0x40;
        if (var->sync & FB_SYNC_VERT_HIGH_ACT)
                par->misc &= ~0x80;
-       
+
        par->mode = mode;
 
        if (mode & MODE_8BPP)
@@ -520,8 +517,8 @@ static int vga16fb_check_var(struct fb_var_screeninfo *var,
        else
                /* pixel clock == vga clock */
                vga16fb_clock_chip(par, &var->pixclock, info, 1, 1);
-       
-       var->red.offset = var->green.offset = var->blue.offset = 
+
+       var->red.offset = var->green.offset = var->blue.offset =
        var->transp.offset = 0;
        var->red.length = var->green.length = var->blue.length =
                (par->isVGA) ? 6 : 2;
@@ -588,10 +585,10 @@ static int vga16fb_set_par(struct fb_info *info)
        else
                atc[VGA_ATC_PEL] = info->var.xoffset & 7;
        atc[VGA_ATC_COLOR_PAGE] = 0x00;
-       
+
        if (par->mode & MODE_TEXT) {
-               fh = 16; // FIXME !!! Fudge font height. 
-               par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 
+               fh = 16; // FIXME !!! Fudge font height.
+               par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN]
                                               & ~0x1F) | (fh - 1);
        }
 
@@ -602,10 +599,10 @@ static int vga16fb_set_par(struct fb_info *info)
                vga_io_w(EGA_GFX_E0, 0x00);
                vga_io_w(EGA_GFX_E1, 0x01);
        }
-       
+
        /* update misc output register */
        vga_io_w(VGA_MIS_W, par->misc);
-       
+
        /* synchronous reset on */
        vga_io_wseq(0x00, 0x01);
 
@@ -617,7 +614,7 @@ static int vga16fb_set_par(struct fb_info *info)
        for (i = 2; i < VGA_SEQ_C; i++) {
                vga_io_wseq(i, seq[i]);
        }
-       
+
        /* synchronous reset off */
        vga_io_wseq(0x00, 0x03);
 
@@ -628,12 +625,12 @@ static int vga16fb_set_par(struct fb_info *info)
        for (i = 0; i < VGA_CRTC_REGS; i++) {
                vga_io_wcrt(i, par->crtc[i]);
        }
-       
+
        /* write graphics controller registers */
        for (i = 0; i < VGA_GFX_C; i++) {
                vga_io_wgfx(i, gdc[i]);
        }
-       
+
        /* write attribute controller registers */
        for (i = 0; i < VGA_ATT_C; i++) {
                vga_io_r(VGA_IS1_RC);           /* reset flip-flop */
@@ -656,7 +653,7 @@ static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned b
 {
        static const unsigned char map[] = { 000, 001, 010, 011 };
        int val;
-       
+
        if (regno >= 16)
                return;
        val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
@@ -687,17 +684,17 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
         *  (according to the entries in the `var' structure). Return
         *  != 0 for invalid regno.
         */
-       
+
        if (regno >= 256)
                return 1;
 
        gray = info->var.grayscale;
-       
+
        if (gray) {
                /* gray = 0.30*R + 0.59*G + 0.11*B */
                red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
        }
-       if (par->isVGA) 
+       if (par->isVGA)
                vga16_setpalette(regno,red,green,blue);
        else
                ega16_setpalette(regno,red,green,blue);
@@ -705,7 +702,7 @@ static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 }
 
 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
-                              struct fb_info *info) 
+                              struct fb_info *info)
 {
        vga16fb_pan_var(info, var);
        return 0;
@@ -720,7 +717,7 @@ static void vga_vesa_blank(struct vga16fb_par *par, int mode)
 {
        unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
        unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-       
+
        /* save original values of VGA controller registers */
        if(!par->vesa_blanked) {
                par->vga_state.CrtMiscIO = vga_io_r(VGA_MIS_R);
@@ -776,7 +773,7 @@ static void vga_vesa_unblank(struct vga16fb_par *par)
 {
        unsigned char SeqCtrlIndex = vga_io_r(VGA_SEQ_I);
        unsigned char CrtCtrlIndex = vga_io_r(VGA_CRT_IC);
-       
+
        /* restore original values of VGA controller registers */
        vga_io_w(VGA_MIS_W, par->vga_state.CrtMiscIO);
 
@@ -962,7 +959,7 @@ static void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
                                }
                                break;
                        }
-               } else 
+               } else
                        vga_8planes_fillrect(info, rect);
                break;
        case FB_TYPE_PACKED_PIXELS:
@@ -1029,7 +1026,7 @@ static void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea
 
 static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-       u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
+       u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
        int x, x2, y2, old_dx, old_dy, vxres, vyres;
        int height, width, line_ofs;
        char __iomem *dst = NULL;
@@ -1094,9 +1091,9 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
                                        dst += line_ofs;
                                }
                        } else {
-                               dst = info->screen_base + (dx/8) + width + 
+                               dst = info->screen_base + (dx/8) + width +
                                        (dy + height - 1) * info->fix.line_length;
-                               src = info->screen_base + (sx/8) + width + 
+                               src = info->screen_base + (sx/8) + width +
                                        (sy + height  - 1) * info->fix.line_length;
                                while (height--) {
                                        for (x = 0; x < width; x++) {
@@ -1109,7 +1106,7 @@ static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
                                        dst -= line_ofs;
                                }
                        }
-               } else 
+               } else
                        vga_8planes_copyarea(info, area);
                break;
        case FB_TYPE_PACKED_PIXELS:
@@ -1182,7 +1179,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
                                setsr(0xf);
                                setcolor(image->fg_color);
                                selectmask();
-                               
+
                                setmask(0xff);
                                writeb(image->bg_color, where);
                                rmb();
@@ -1191,7 +1188,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
                                wmb();
                                for (y = 0; y < image->height; y++) {
                                        dst = where;
-                                       for (x = image->width/8; x--;) 
+                                       for (x = image->width/8; x--;)
                                                writeb(*cdat++, dst++);
                                        where += info->fix.line_length;
                                }
@@ -1202,7 +1199,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
                                setsr(0xf);
                                setcolor(image->bg_color);
                                selectmask();
-                               
+
                                setmask(0xff);
                                for (y = 0; y < image->height; y++) {
                                        dst = where;
@@ -1218,7 +1215,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
                                        where += info->fix.line_length;
                                }
                        }
-               } else 
+               } else
                        vga_8planes_imageblit(info, image);
                break;
        case FB_TYPE_PACKED_PIXELS:
@@ -1231,7 +1228,7 @@ static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *im
 static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image)
 {
        /*
-        * Draw logo 
+        * Draw logo
         */
        struct vga16fb_par *par = info->par;
        char __iomem *where =
@@ -1248,7 +1245,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima
                        setsr(0xf);
                        setop(0);
                        setmode(0);
-                       
+
                        for (y = 0; y < image->height; y++) {
                                for (x = 0; x < image->width; x++) {
                                        dst = where + x/8;
@@ -1272,7 +1269,7 @@ static void vga_imageblit_color(struct fb_info *info, const struct fb_image *ima
                break;
        }
 }
-                               
+
 static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
        if (image->depth == 1)
@@ -1304,28 +1301,22 @@ static const struct fb_ops vga16fb_ops = {
        .fb_imageblit   = vga16fb_imageblit,
 };
 
-#ifndef MODULE
-static int __init vga16fb_setup(char *options)
-{
-       char *this_opt;
-       
-       if (!options || !*options)
-               return 0;
-       
-       while ((this_opt = strsep(&options, ",")) != NULL) {
-               if (!*this_opt) continue;
-       }
-       return 0;
-}
-#endif
-
 static int vga16fb_probe(struct platform_device *dev)
 {
+       struct screen_info *si;
        struct fb_info *info;
        struct vga16fb_par *par;
        int i;
        int ret = 0;
 
+       si = dev_get_platdata(&dev->dev);
+       if (!si)
+               return -ENODEV;
+
+       ret = check_mode_supported(si);
+       if (ret)
+               return ret;
+
        printk(KERN_DEBUG "vga16fb: initializing\n");
        info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
 
@@ -1339,8 +1330,8 @@ static int vga16fb_probe(struct platform_device *dev)
                goto err_ioremap;
        }
 
-       /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
-       info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
+       /* XXX share VGA_FB_PHYS_BASE and I/O region with vgacon and others */
+       info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS_BASE, 0);
 
        if (!info->screen_base) {
                printk(KERN_ERR "vga16fb: unable to map device\n");
@@ -1352,19 +1343,19 @@ static int vga16fb_probe(struct platform_device *dev)
        par = info->par;
 
 #if defined(CONFIG_X86)
-       par->isVGA = screen_info.orig_video_isVGA == VIDEO_TYPE_VGAC;
+       par->isVGA = si->orig_video_isVGA == VIDEO_TYPE_VGAC;
 #else
        /* non-x86 architectures treat orig_video_isVGA as a boolean flag */
-       par->isVGA = screen_info.orig_video_isVGA;
+       par->isVGA = si->orig_video_isVGA;
 #endif
        par->palette_blanked = 0;
        par->vesa_blanked = 0;
 
        i = par->isVGA? 6 : 2;
-       
+
        vga16fb_defined.red.length   = i;
        vga16fb_defined.green.length = i;
-       vga16fb_defined.blue.length  = i;       
+       vga16fb_defined.blue.length  = i;
 
        /* name should not depend on EGA/VGA */
        info->fbops = &vga16fb_ops;
@@ -1391,8 +1382,8 @@ static int vga16fb_probe(struct platform_device *dev)
 
        vga16fb_update_fix(info);
 
-       info->apertures->ranges[0].base = VGA_FB_PHYS;
-       info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
+       info->apertures->ranges[0].base = VGA_FB_PHYS_BASE;
+       info->apertures->ranges[0].size = VGA_FB_PHYS_SIZE;
 
        if (register_framebuffer(info) < 0) {
                printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
@@ -1425,58 +1416,22 @@ static int vga16fb_remove(struct platform_device *dev)
        return 0;
 }
 
+static const struct platform_device_id vga16fb_driver_id_table[] = {
+       {"ega-framebuffer", 0},
+       {"vga-framebuffer", 0},
+       { }
+};
+
 static struct platform_driver vga16fb_driver = {
        .probe = vga16fb_probe,
        .remove = vga16fb_remove,
        .driver = {
                .name = "vga16fb",
        },
+       .id_table = vga16fb_driver_id_table,
 };
 
-static struct platform_device *vga16fb_device;
-
-static int __init vga16fb_init(void)
-{
-       int ret;
-#ifndef MODULE
-       char *option = NULL;
-
-       if (fb_get_options("vga16fb", &option))
-               return -ENODEV;
-
-       vga16fb_setup(option);
-#endif
-
-       ret = check_mode_supported();
-       if (ret)
-               return ret;
-
-       ret = platform_driver_register(&vga16fb_driver);
-
-       if (!ret) {
-               vga16fb_device = platform_device_alloc("vga16fb", 0);
-
-               if (vga16fb_device)
-                       ret = platform_device_add(vga16fb_device);
-               else
-                       ret = -ENOMEM;
-
-               if (ret) {
-                       platform_device_put(vga16fb_device);
-                       platform_driver_unregister(&vga16fb_driver);
-               }
-       }
-
-       return ret;
-}
-
-static void __exit vga16fb_exit(void)
-{
-       platform_device_unregister(vga16fb_device);
-       platform_driver_unregister(&vga16fb_driver);
-}
+module_platform_driver(vga16fb_driver);
 
 MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");
 MODULE_LICENSE("GPL");
-module_init(vga16fb_init);
-module_exit(vga16fb_exit);
index 89d75079b73071be5ddf876be6db07f21c4cfed3..2ee8fcae08dfbbf3fe1dac69643ed0dc1ee88940 100644 (file)
@@ -8,6 +8,7 @@
 /*
  * Core code for the Via multifunction framebuffer device.
  */
+#include <linux/aperture.h>
 #include <linux/via-core.h>
 #include <linux/via_i2c.h>
 #include <linux/via-gpio.h>
@@ -617,6 +618,10 @@ static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int ret;
 
+       ret = aperture_remove_conflicting_pci_devices(pdev, "viafb");
+       if (ret)
+               return ret;
+
        ret = pci_enable_device(pdev);
        if (ret)
                return ret;
index 4274c6efb24909eaeeee4e35d366ac01e1309d55..49b9f148d3a17cb611490dcbbf86c9e6b931e626 100644 (file)
@@ -12,6 +12,7 @@
  * (http://davesdomain.org.uk/viafb/)
  */
 
+#include <linux/aperture.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -672,6 +673,10 @@ static int vt8623_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
+       rc = aperture_remove_conflicting_pci_devices(dev, "vt8623fb");
+       if (rc)
+               return rc;
+
        /* Allocate and fill driver data structure */
        info = framebuffer_alloc(sizeof(struct vt8623fb_info), &(dev->dev));
        if (!info)
index 2a0b17842402c6af82b6cab2f2fbed1dba8eb2d5..54b321f20d53976503f4fc945065b233e5b16e97 100644 (file)
 #include <drm/drm_atomic_state_helper.h>
 #include <drm/drm_util.h>
 
+/*
+ * Drivers that don't allow primary plane scaling may pass this macro in place
+ * of the min/max scale parameters of the plane-state checker function.
+ *
+ * Due to src being in 16.16 fixed point and dest being in integer pixels,
+ * 1<<16 represents no scaling.
+ */
+#define DRM_PLANE_NO_SCALING (1<<16)
+
 struct drm_atomic_state;
 struct drm_private_obj;
 struct drm_private_state;
index d434ab416ad470212f160a8ab33701b85eef8bfc..6b65b0dfb4fb48466657a86ed25723356695aa03 100644 (file)
@@ -930,6 +930,8 @@ struct drm_bridge *devm_drm_panel_bridge_add(struct device *dev,
 struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
                                                   struct drm_panel *panel,
                                                   u32 connector_type);
+struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm,
+                                            struct drm_panel *panel);
 struct drm_connector *drm_panel_bridge_connector(struct drm_bridge *bridge);
 #else
 static inline bool drm_bridge_is_panel(const struct drm_bridge *bridge)
@@ -947,6 +949,8 @@ static inline int drm_panel_bridge_set_orientation(struct drm_connector *connect
 #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL_BRIDGE)
 struct drm_bridge *devm_drm_of_get_bridge(struct device *dev, struct device_node *node,
                                          u32 port, u32 endpoint);
+struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm, struct device_node *node,
+                                         u32 port, u32 endpoint);
 #else
 static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
                                                        struct device_node *node,
@@ -955,6 +959,14 @@ static inline struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
 {
        return ERR_PTR(-ENODEV);
 }
+
+static inline struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
+                                                    struct device_node *node,
+                                                    u32 port,
+                                                    u32 endpoint)
+{
+       return ERR_PTR(-ENODEV);
+}
 #endif
 
 #endif
index a1705d6b3fba20d9be64a651b9f2f3cb4a5c36e8..248206bbd975ed8dc0fd217f868b88131e5659b0 100644 (file)
@@ -323,6 +323,22 @@ struct drm_monitor_range_info {
        u8 max_vfreq;
 };
 
+/**
+ * struct drm_luminance_range_info - Panel's luminance range for
+ * &drm_display_info. Calculated using data in EDID
+ *
+ * This struct is used to store a luminance range supported by panel
+ * as calculated using data from EDID's static hdr metadata.
+ *
+ * @min_luminance: This is the min supported luminance value
+ *
+ * @max_luminance: This is the max supported luminance value
+ */
+struct drm_luminance_range_info {
+       u32 min_luminance;
+       u32 max_luminance;
+};
+
 /**
  * enum drm_privacy_screen_status - privacy screen status
  *
@@ -624,6 +640,11 @@ struct drm_display_info {
         */
        struct drm_monitor_range_info monitor_range;
 
+       /**
+        * @luminance_range: Luminance range supported by panel
+        */
+       struct drm_luminance_range_info luminance_range;
+
        /**
         * @mso_stream_count: eDP Multi-SST Operation (MSO) stream count from
         * the DisplayID VESA vendor block. 0 for conventional Single-Stream
@@ -1677,6 +1698,11 @@ int drm_connector_init_with_ddc(struct drm_device *dev,
                                const struct drm_connector_funcs *funcs,
                                int connector_type,
                                struct i2c_adapter *ddc);
+int drmm_connector_init(struct drm_device *dev,
+                       struct drm_connector *connector,
+                       const struct drm_connector_funcs *funcs,
+                       int connector_type,
+                       struct i2c_adapter *ddc);
 void drm_connector_attach_edid_property(struct drm_connector *connector);
 int drm_connector_register(struct drm_connector *connector);
 void drm_connector_unregister(struct drm_connector *connector);
index ffc1cde331d3e6aeecb38cc74c83f569ae3b98ff..8e1cbc75143ef2161be189b7dbfc3cb63260026d 100644 (file)
@@ -1216,6 +1216,15 @@ int drm_crtc_init_with_planes(struct drm_device *dev,
                              struct drm_plane *cursor,
                              const struct drm_crtc_funcs *funcs,
                              const char *name, ...);
+
+__printf(6, 7)
+int drmm_crtc_init_with_planes(struct drm_device *dev,
+                              struct drm_crtc *crtc,
+                              struct drm_plane *primary,
+                              struct drm_plane *cursor,
+                              const struct drm_crtc_funcs *funcs,
+                              const char *name, ...);
+
 void drm_crtc_cleanup(struct drm_crtc *crtc);
 
 __printf(7, 8)
index 6e91a0280f31b5aae5c33efe8b7b8f09ede8f027..3a09682af685a36ba42565e926fe2e0ec6955a1d 100644 (file)
@@ -194,6 +194,12 @@ int drm_encoder_init(struct drm_device *dev,
                     const struct drm_encoder_funcs *funcs,
                     int encoder_type, const char *name, ...);
 
+__printf(5, 6)
+int drmm_encoder_init(struct drm_device *dev,
+                     struct drm_encoder *encoder,
+                     const struct drm_encoder_funcs *funcs,
+                     int encoder_type, const char *name, ...);
+
 __printf(6, 7)
 void *__drmm_encoder_alloc(struct drm_device *dev,
                           size_t size, size_t offset,
diff --git a/include/drm/drm_fb_cma_helper.h b/include/drm/drm_fb_cma_helper.h
deleted file mode 100644 (file)
index 6447e34..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __DRM_FB_CMA_HELPER_H__
-#define __DRM_FB_CMA_HELPER_H__
-
-#include <linux/types.h>
-
-struct drm_device;
-struct drm_framebuffer;
-struct drm_plane_state;
-
-struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
-       unsigned int plane);
-
-dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
-                                  struct drm_plane_state *state,
-                                  unsigned int plane);
-
-void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
-                                 struct drm_plane_state *old_state,
-                                 struct drm_plane_state *state);
-
-#endif
-
diff --git a/include/drm/drm_fb_dma_helper.h b/include/drm/drm_fb_dma_helper.h
new file mode 100644 (file)
index 0000000..d5e036c
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DRM_FB_DMA_HELPER_H__
+#define __DRM_FB_DMA_HELPER_H__
+
+#include <linux/types.h>
+
+struct drm_device;
+struct drm_framebuffer;
+struct drm_plane_state;
+
+struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
+       unsigned int plane);
+
+dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
+                                  struct drm_plane_state *state,
+                                  unsigned int plane);
+
+void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
+                                 struct drm_plane_state *old_state,
+                                 struct drm_plane_state *state);
+
+#endif
+
index e0a73a1e2df74cb5caf75899598c86d1dd06c325..d780fd1517892811f3f146ec56bb6f0c934dee94 100644 (file)
@@ -421,13 +421,4 @@ void drm_send_event_timestamp_locked(struct drm_device *dev,
 
 struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags);
 
-#ifdef CONFIG_MMU
-struct drm_vma_offset_manager;
-unsigned long drm_get_unmapped_area(struct file *file,
-                                   unsigned long uaddr, unsigned long len,
-                                   unsigned long pgoff, unsigned long flags,
-                                   struct drm_vma_offset_manager *mgr);
-#endif /* CONFIG_MMU */
-
-
 #endif /* _DRM_FILE_H_ */
index 55145eca078283219b48c80be597a27ec9ca8941..caa18119433576419e1123c8e91fd23249109c85 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef __LINUX_DRM_FORMAT_HELPER_H
 #define __LINUX_DRM_FORMAT_HELPER_H
 
+struct iosys_map;
 struct drm_format_info;
 struct drm_framebuffer;
 struct drm_rect;
@@ -13,37 +14,34 @@ struct drm_rect;
 unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info *format,
                                const struct drm_rect *clip);
 
-void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr,
-                  const struct drm_framebuffer *fb, const struct drm_rect *clip);
-void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr,
-                       const struct drm_framebuffer *fb, const struct drm_rect *clip);
-void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src,
-                const struct drm_framebuffer *fb, const struct drm_rect *clip,
-                bool cached);
-void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *vaddr,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip);
-void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip,
-                              bool swab);
-void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch,
-                                   const void *vaddr, const struct drm_framebuffer *fb,
-                                   const struct drm_rect *clip, bool swab);
-void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src,
-                              const struct drm_framebuffer *fb, const struct drm_rect *clip);
-void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
-                                   const void *vaddr, const struct drm_framebuffer *fb,
+void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
+                  const struct iosys_map *src, const struct drm_framebuffer *fb,
+                  const struct drm_rect *clip);
+void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
+                const struct iosys_map *src, const struct drm_framebuffer *fb,
+                const struct drm_rect *clip, bool cached);
+void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip, bool swab);
+void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
+                              const struct iosys_map *src, const struct drm_framebuffer *fb,
+                              const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
+                                   const struct iosys_map *src, const struct drm_framebuffer *fb,
                                    const struct drm_rect *clip);
-void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst, unsigned int dst_pitch,
-                                        const void *vaddr, const struct drm_framebuffer *fb,
-                                        const struct drm_rect *clip);
-void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr,
-                             const struct drm_framebuffer *fb, const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
+                             const struct iosys_map *src, const struct drm_framebuffer *fb,
+                             const struct drm_rect *clip);
 
-int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format,
-                    const void *vmap, const struct drm_framebuffer *fb,
-                    const struct drm_rect *rect);
+int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
+               const struct iosys_map *src, const struct drm_framebuffer *fb,
+               const struct drm_rect *rect);
 
-void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *src,
-                            const struct drm_framebuffer *fb, const struct drm_rect *clip);
+void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
+                            const struct iosys_map *src, const struct drm_framebuffer *fb,
+                            const struct drm_rect *clip);
 
 #endif /* __LINUX_DRM_FORMAT_HELPER_H */
index 22aa64d07c7905e27ad559f001627480c7d8baf9..532ae78ca747e6c42bcb7c9621cb290f21655bea 100644 (file)
@@ -138,6 +138,9 @@ struct drm_format_info {
 
        /** @is_yuv: Is it a YUV format? */
        bool is_yuv;
+
+       /** @is_color_indexed: Is it a color-indexed format? */
+       bool is_color_indexed;
 };
 
 /**
@@ -313,6 +316,7 @@ unsigned int drm_format_info_block_width(const struct drm_format_info *info,
                                         int plane);
 unsigned int drm_format_info_block_height(const struct drm_format_info *info,
                                          int plane);
+unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane);
 uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
                                   int plane, unsigned int buffer_width);
 
index f67c5b7bcb68654a90f0af108d478cd469e80ecb..0dcc07b68654844ba80c4c812451b52921fa1978 100644 (file)
@@ -154,10 +154,10 @@ struct drm_framebuffer {
         * drm_mode_fb_cmd2.
         *
         * Note that this is a linear offset and does not take into account
-        * tiling or buffer laytou per @modifier. It meant to be used when the
-        * actual pixel data for this framebuffer plane starts at an offset,
-        * e.g.  when multiple planes are allocated within the same backing
-        * storage buffer object. For tiled layouts this generally means it
+        * tiling or buffer layout per @modifier. It is meant to be used when
+        * the actual pixel data for this framebuffer plane starts at an offset,
+        * e.g. when multiple planes are allocated within the same backing
+        * storage buffer object. For tiled layouts this generally means its
         * @offsets must at least be tile-size aligned, but hardware often has
         * stricter requirements.
         *
index 87cffc9efa85500947d53364600524b7ea5a14bb..58a18a17c67ebb9c0d5b61f92f47947b281ed449 100644 (file)
@@ -217,7 +217,7 @@ struct drm_gem_object {
         *
         * SHMEM file node used as backing storage for swappable buffer objects.
         * GEM also supports driver private objects with driver-specific backing
-        * storage (contiguous CMA memory, special reserved blocks). In this
+        * storage (contiguous DMA memory, special reserved blocks). In this
         * case @filp is NULL.
         */
        struct file *filp;
diff --git a/include/drm/drm_gem_cma_helper.h b/include/drm/drm_gem_cma_helper.h
deleted file mode 100644 (file)
index fbda4ce..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __DRM_GEM_CMA_HELPER_H__
-#define __DRM_GEM_CMA_HELPER_H__
-
-#include <drm/drm_file.h>
-#include <drm/drm_ioctl.h>
-#include <drm/drm_gem.h>
-
-struct drm_mode_create_dumb;
-
-/**
- * struct drm_gem_cma_object - GEM object backed by CMA memory allocations
- * @base: base GEM object
- * @paddr: physical address of the backing memory
- * @sgt: scatter/gather table for imported PRIME buffers. The table can have
- *       more than one entry but they are guaranteed to have contiguous
- *       DMA addresses.
- * @vaddr: kernel virtual address of the backing memory
- * @map_noncoherent: if true, the GEM object is backed by non-coherent memory
- */
-struct drm_gem_cma_object {
-       struct drm_gem_object base;
-       dma_addr_t paddr;
-       struct sg_table *sgt;
-
-       /* For objects with DMA memory allocated by GEM CMA */
-       void *vaddr;
-
-       bool map_noncoherent;
-};
-
-#define to_drm_gem_cma_obj(gem_obj) \
-       container_of(gem_obj, struct drm_gem_cma_object, base)
-
-struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
-                                             size_t size);
-void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj);
-void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj,
-                           struct drm_printer *p, unsigned int indent);
-struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj);
-int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj,
-                    struct iosys_map *map);
-int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma);
-
-extern const struct vm_operations_struct drm_gem_cma_vm_ops;
-
-/*
- * GEM object functions
- */
-
-/**
- * drm_gem_cma_object_free - GEM object function for drm_gem_cma_free()
- * @obj: GEM object to free
- *
- * This function wraps drm_gem_cma_free_object(). Drivers that employ the CMA helpers
- * should use it as their &drm_gem_object_funcs.free handler.
- */
-static inline void drm_gem_cma_object_free(struct drm_gem_object *obj)
-{
-       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
-
-       drm_gem_cma_free(cma_obj);
-}
-
-/**
- * drm_gem_cma_object_print_info() - Print &drm_gem_cma_object info for debugfs
- * @p: DRM printer
- * @indent: Tab indentation level
- * @obj: GEM object
- *
- * This function wraps drm_gem_cma_print_info(). Drivers that employ the CMA helpers
- * should use this function as their &drm_gem_object_funcs.print_info handler.
- */
-static inline void drm_gem_cma_object_print_info(struct drm_printer *p, unsigned int indent,
-                                                const struct drm_gem_object *obj)
-{
-       const struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
-
-       drm_gem_cma_print_info(cma_obj, p, indent);
-}
-
-/**
- * drm_gem_cma_object_get_sg_table - GEM object function for drm_gem_cma_get_sg_table()
- * @obj: GEM object
- *
- * This function wraps drm_gem_cma_get_sg_table(). Drivers that employ the CMA helpers should
- * use it as their &drm_gem_object_funcs.get_sg_table handler.
- *
- * Returns:
- * A pointer to the scatter/gather table of pinned pages or NULL on failure.
- */
-static inline struct sg_table *drm_gem_cma_object_get_sg_table(struct drm_gem_object *obj)
-{
-       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
-
-       return drm_gem_cma_get_sg_table(cma_obj);
-}
-
-/*
- * drm_gem_cma_object_vmap - GEM object function for drm_gem_cma_vmap()
- * @obj: GEM object
- * @map: Returns the kernel virtual address of the CMA GEM object's backing store.
- *
- * This function wraps drm_gem_cma_vmap(). Drivers that employ the CMA helpers should
- * use it as their &drm_gem_object_funcs.vmap handler.
- *
- * Returns:
- * 0 on success or a negative error code on failure.
- */
-static inline int drm_gem_cma_object_vmap(struct drm_gem_object *obj,
-                                         struct iosys_map *map)
-{
-       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
-
-       return drm_gem_cma_vmap(cma_obj, map);
-}
-
-/**
- * drm_gem_cma_object_mmap - GEM object function for drm_gem_cma_mmap()
- * @obj: GEM object
- * @vma: VMA for the area to be mapped
- *
- * This function wraps drm_gem_cma_mmap(). Drivers that employ the cma helpers should
- * use it as their &drm_gem_object_funcs.mmap handler.
- *
- * Returns:
- * 0 on success or a negative error code on failure.
- */
-static inline int drm_gem_cma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
-{
-       struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
-
-       return drm_gem_cma_mmap(cma_obj, vma);
-}
-
-/*
- * Driver ops
- */
-
-/* create memory region for DRM framebuffer */
-int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv,
-                                    struct drm_device *drm,
-                                    struct drm_mode_create_dumb *args);
-
-/* create memory region for DRM framebuffer */
-int drm_gem_cma_dumb_create(struct drm_file *file_priv,
-                           struct drm_device *drm,
-                           struct drm_mode_create_dumb *args);
-
-struct drm_gem_object *
-drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
-                                 struct dma_buf_attachment *attach,
-                                 struct sg_table *sgt);
-
-/**
- * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE - CMA GEM driver operations
- * @dumb_create_func: callback function for .dumb_create
- *
- * This macro provides a shortcut for setting the default GEM operations in the
- * &drm_driver structure.
- *
- * This macro is a variant of DRM_GEM_CMA_DRIVER_OPS for drivers that
- * override the default implementation of &struct rm_driver.dumb_create. Use
- * DRM_GEM_CMA_DRIVER_OPS if possible. Drivers that require a virtual address
- * on imported buffers should use
- * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead.
- */
-#define DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(dumb_create_func) \
-       .dumb_create            = (dumb_create_func), \
-       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd, \
-       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle, \
-       .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, \
-       .gem_prime_mmap         = drm_gem_prime_mmap
-
-/**
- * DRM_GEM_CMA_DRIVER_OPS - CMA GEM driver operations
- *
- * This macro provides a shortcut for setting the default GEM operations in the
- * &drm_driver structure.
- *
- * Drivers that come with their own implementation of
- * &struct drm_driver.dumb_create should use
- * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. Use
- * DRM_GEM_CMA_DRIVER_OPS if possible. Drivers that require a virtual address
- * on imported buffers should use DRM_GEM_CMA_DRIVER_OPS_VMAP instead.
- */
-#define DRM_GEM_CMA_DRIVER_OPS \
-       DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_cma_dumb_create)
-
-/**
- * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE - CMA GEM driver operations
- *                                                ensuring a virtual address
- *                                                on the buffer
- * @dumb_create_func: callback function for .dumb_create
- *
- * This macro provides a shortcut for setting the default GEM operations in the
- * &drm_driver structure for drivers that need the virtual address also on
- * imported buffers.
- *
- * This macro is a variant of DRM_GEM_CMA_DRIVER_OPS_VMAP for drivers that
- * override the default implementation of &struct drm_driver.dumb_create. Use
- * DRM_GEM_CMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a
- * virtual address on imported buffers should use
- * DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE() instead.
- */
-#define DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(dumb_create_func) \
-       .dumb_create            = dumb_create_func, \
-       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd, \
-       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle, \
-       .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table_vmap, \
-       .gem_prime_mmap         = drm_gem_prime_mmap
-
-/**
- * DRM_GEM_CMA_DRIVER_OPS_VMAP - CMA GEM driver operations ensuring a virtual
- *                               address on the buffer
- *
- * This macro provides a shortcut for setting the default GEM operations in the
- * &drm_driver structure for drivers that need the virtual address also on
- * imported buffers.
- *
- * Drivers that come with their own implementation of
- * &struct drm_driver.dumb_create should use
- * DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. Use
- * DRM_GEM_CMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a
- * virtual address on imported buffers should use DRM_GEM_CMA_DRIVER_OPS
- * instead.
- */
-#define DRM_GEM_CMA_DRIVER_OPS_VMAP \
-       DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_gem_cma_dumb_create)
-
-struct drm_gem_object *
-drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *drm,
-                                      struct dma_buf_attachment *attach,
-                                      struct sg_table *sgt);
-
-/*
- * File ops
- */
-
-#ifndef CONFIG_MMU
-unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
-                                           unsigned long addr,
-                                           unsigned long len,
-                                           unsigned long pgoff,
-                                           unsigned long flags);
-#define DRM_GEM_CMA_UNMAPPED_AREA_FOPS \
-       .get_unmapped_area      = drm_gem_cma_get_unmapped_area,
-#else
-#define DRM_GEM_CMA_UNMAPPED_AREA_FOPS
-#endif
-
-/**
- * DEFINE_DRM_GEM_CMA_FOPS() - macro to generate file operations for CMA drivers
- * @name: name for the generated structure
- *
- * This macro autogenerates a suitable &struct file_operations for CMA based
- * drivers, which can be assigned to &drm_driver.fops. Note that this structure
- * cannot be shared between drivers, because it contains a reference to the
- * current module using THIS_MODULE.
- *
- * Note that the declaration is already marked as static - if you need a
- * non-static version of this you're probably doing it wrong and will break the
- * THIS_MODULE reference by accident.
- */
-#define DEFINE_DRM_GEM_CMA_FOPS(name) \
-       static const struct file_operations name = {\
-               .owner          = THIS_MODULE,\
-               .open           = drm_open,\
-               .release        = drm_release,\
-               .unlocked_ioctl = drm_ioctl,\
-               .compat_ioctl   = drm_compat_ioctl,\
-               .poll           = drm_poll,\
-               .read           = drm_read,\
-               .llseek         = noop_llseek,\
-               .mmap           = drm_gem_mmap,\
-               DRM_GEM_CMA_UNMAPPED_AREA_FOPS \
-       }
-
-#endif /* __DRM_GEM_CMA_HELPER_H__ */
diff --git a/include/drm/drm_gem_dma_helper.h b/include/drm/drm_gem_dma_helper.h
new file mode 100644 (file)
index 0000000..8a04323
--- /dev/null
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DRM_GEM_DMA_HELPER_H__
+#define __DRM_GEM_DMA_HELPER_H__
+
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_gem.h>
+
+struct drm_mode_create_dumb;
+
+/**
+ * struct drm_gem_dma_object - GEM object backed by DMA memory allocations
+ * @base: base GEM object
+ * @dma_addr: DMA address of the backing memory
+ * @sgt: scatter/gather table for imported PRIME buffers. The table can have
+ *       more than one entry but they are guaranteed to have contiguous
+ *       DMA addresses.
+ * @vaddr: kernel virtual address of the backing memory
+ * @map_noncoherent: if true, the GEM object is backed by non-coherent memory
+ */
+struct drm_gem_dma_object {
+       struct drm_gem_object base;
+       dma_addr_t dma_addr;
+       struct sg_table *sgt;
+
+       /* For objects with DMA memory allocated by GEM DMA */
+       void *vaddr;
+
+       bool map_noncoherent;
+};
+
+#define to_drm_gem_dma_obj(gem_obj) \
+       container_of(gem_obj, struct drm_gem_dma_object, base)
+
+struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
+                                             size_t size);
+void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj);
+void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj,
+                           struct drm_printer *p, unsigned int indent);
+struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj);
+int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj,
+                    struct iosys_map *map);
+int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma);
+
+extern const struct vm_operations_struct drm_gem_dma_vm_ops;
+
+/*
+ * GEM object functions
+ */
+
+/**
+ * drm_gem_dma_object_free - GEM object function for drm_gem_dma_free()
+ * @obj: GEM object to free
+ *
+ * This function wraps drm_gem_dma_free_object(). Drivers that employ the DMA helpers
+ * should use it as their &drm_gem_object_funcs.free handler.
+ */
+static inline void drm_gem_dma_object_free(struct drm_gem_object *obj)
+{
+       struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+
+       drm_gem_dma_free(dma_obj);
+}
+
+/**
+ * drm_gem_dma_object_print_info() - Print &drm_gem_dma_object info for debugfs
+ * @p: DRM printer
+ * @indent: Tab indentation level
+ * @obj: GEM object
+ *
+ * This function wraps drm_gem_dma_print_info(). Drivers that employ the DMA helpers
+ * should use this function as their &drm_gem_object_funcs.print_info handler.
+ */
+static inline void drm_gem_dma_object_print_info(struct drm_printer *p, unsigned int indent,
+                                                const struct drm_gem_object *obj)
+{
+       const struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+
+       drm_gem_dma_print_info(dma_obj, p, indent);
+}
+
+/**
+ * drm_gem_dma_object_get_sg_table - GEM object function for drm_gem_dma_get_sg_table()
+ * @obj: GEM object
+ *
+ * This function wraps drm_gem_dma_get_sg_table(). Drivers that employ the DMA helpers should
+ * use it as their &drm_gem_object_funcs.get_sg_table handler.
+ *
+ * Returns:
+ * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ */
+static inline struct sg_table *drm_gem_dma_object_get_sg_table(struct drm_gem_object *obj)
+{
+       struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+
+       return drm_gem_dma_get_sg_table(dma_obj);
+}
+
+/*
+ * drm_gem_dma_object_vmap - GEM object function for drm_gem_dma_vmap()
+ * @obj: GEM object
+ * @map: Returns the kernel virtual address of the DMA GEM object's backing store.
+ *
+ * This function wraps drm_gem_dma_vmap(). Drivers that employ the DMA helpers should
+ * use it as their &drm_gem_object_funcs.vmap handler.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+static inline int drm_gem_dma_object_vmap(struct drm_gem_object *obj,
+                                         struct iosys_map *map)
+{
+       struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+
+       return drm_gem_dma_vmap(dma_obj, map);
+}
+
+/**
+ * drm_gem_dma_object_mmap - GEM object function for drm_gem_dma_mmap()
+ * @obj: GEM object
+ * @vma: VMA for the area to be mapped
+ *
+ * This function wraps drm_gem_dma_mmap(). Drivers that employ the dma helpers should
+ * use it as their &drm_gem_object_funcs.mmap handler.
+ *
+ * Returns:
+ * 0 on success or a negative error code on failure.
+ */
+static inline int drm_gem_dma_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
+{
+       struct drm_gem_dma_object *dma_obj = to_drm_gem_dma_obj(obj);
+
+       return drm_gem_dma_mmap(dma_obj, vma);
+}
+
+/*
+ * Driver ops
+ */
+
+/* create memory region for DRM framebuffer */
+int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv,
+                                    struct drm_device *drm,
+                                    struct drm_mode_create_dumb *args);
+
+/* create memory region for DRM framebuffer */
+int drm_gem_dma_dumb_create(struct drm_file *file_priv,
+                           struct drm_device *drm,
+                           struct drm_mode_create_dumb *args);
+
+struct drm_gem_object *
+drm_gem_dma_prime_import_sg_table(struct drm_device *dev,
+                                 struct dma_buf_attachment *attach,
+                                 struct sg_table *sgt);
+
+/**
+ * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE - DMA GEM driver operations
+ * @dumb_create_func: callback function for .dumb_create
+ *
+ * This macro provides a shortcut for setting the default GEM operations in the
+ * &drm_driver structure.
+ *
+ * This macro is a variant of DRM_GEM_DMA_DRIVER_OPS for drivers that
+ * override the default implementation of &struct rm_driver.dumb_create. Use
+ * DRM_GEM_DMA_DRIVER_OPS if possible. Drivers that require a virtual address
+ * on imported buffers should use
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead.
+ */
+#define DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(dumb_create_func) \
+       .dumb_create            = (dumb_create_func), \
+       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd, \
+       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle, \
+       .gem_prime_import_sg_table = drm_gem_dma_prime_import_sg_table, \
+       .gem_prime_mmap         = drm_gem_prime_mmap
+
+/**
+ * DRM_GEM_DMA_DRIVER_OPS - DMA GEM driver operations
+ *
+ * This macro provides a shortcut for setting the default GEM operations in the
+ * &drm_driver structure.
+ *
+ * Drivers that come with their own implementation of
+ * &struct drm_driver.dumb_create should use
+ * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE() instead. Use
+ * DRM_GEM_DMA_DRIVER_OPS if possible. Drivers that require a virtual address
+ * on imported buffers should use DRM_GEM_DMA_DRIVER_OPS_VMAP instead.
+ */
+#define DRM_GEM_DMA_DRIVER_OPS \
+       DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(drm_gem_dma_dumb_create)
+
+/**
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE - DMA GEM driver operations
+ *                                                ensuring a virtual address
+ *                                                on the buffer
+ * @dumb_create_func: callback function for .dumb_create
+ *
+ * This macro provides a shortcut for setting the default GEM operations in the
+ * &drm_driver structure for drivers that need the virtual address also on
+ * imported buffers.
+ *
+ * This macro is a variant of DRM_GEM_DMA_DRIVER_OPS_VMAP for drivers that
+ * override the default implementation of &struct drm_driver.dumb_create. Use
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a
+ * virtual address on imported buffers should use
+ * DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE() instead.
+ */
+#define DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(dumb_create_func) \
+       .dumb_create            = dumb_create_func, \
+       .prime_handle_to_fd     = drm_gem_prime_handle_to_fd, \
+       .prime_fd_to_handle     = drm_gem_prime_fd_to_handle, \
+       .gem_prime_import_sg_table = drm_gem_dma_prime_import_sg_table_vmap, \
+       .gem_prime_mmap         = drm_gem_prime_mmap
+
+/**
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP - DMA GEM driver operations ensuring a virtual
+ *                               address on the buffer
+ *
+ * This macro provides a shortcut for setting the default GEM operations in the
+ * &drm_driver structure for drivers that need the virtual address also on
+ * imported buffers.
+ *
+ * Drivers that come with their own implementation of
+ * &struct drm_driver.dumb_create should use
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE() instead. Use
+ * DRM_GEM_DMA_DRIVER_OPS_VMAP if possible. Drivers that do not require a
+ * virtual address on imported buffers should use DRM_GEM_DMA_DRIVER_OPS
+ * instead.
+ */
+#define DRM_GEM_DMA_DRIVER_OPS_VMAP \
+       DRM_GEM_DMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_gem_dma_dumb_create)
+
+struct drm_gem_object *
+drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *drm,
+                                      struct dma_buf_attachment *attach,
+                                      struct sg_table *sgt);
+
+/*
+ * File ops
+ */
+
+#ifndef CONFIG_MMU
+unsigned long drm_gem_dma_get_unmapped_area(struct file *filp,
+                                           unsigned long addr,
+                                           unsigned long len,
+                                           unsigned long pgoff,
+                                           unsigned long flags);
+#define DRM_GEM_DMA_UNMAPPED_AREA_FOPS \
+       .get_unmapped_area      = drm_gem_dma_get_unmapped_area,
+#else
+#define DRM_GEM_DMA_UNMAPPED_AREA_FOPS
+#endif
+
+/**
+ * DEFINE_DRM_GEM_DMA_FOPS() - macro to generate file operations for DMA drivers
+ * @name: name for the generated structure
+ *
+ * This macro autogenerates a suitable &struct file_operations for DMA based
+ * drivers, which can be assigned to &drm_driver.fops. Note that this structure
+ * cannot be shared between drivers, because it contains a reference to the
+ * current module using THIS_MODULE.
+ *
+ * Note that the declaration is already marked as static - if you need a
+ * non-static version of this you're probably doing it wrong and will break the
+ * THIS_MODULE reference by accident.
+ */
+#define DEFINE_DRM_GEM_DMA_FOPS(name) \
+       static const struct file_operations name = {\
+               .owner          = THIS_MODULE,\
+               .open           = drm_open,\
+               .release        = drm_release,\
+               .unlocked_ioctl = drm_ioctl,\
+               .compat_ioctl   = drm_compat_ioctl,\
+               .poll           = drm_poll,\
+               .read           = drm_read,\
+               .llseek         = noop_llseek,\
+               .mmap           = drm_gem_mmap,\
+               DRM_GEM_DMA_UNMAPPED_AREA_FOPS \
+       }
+
+#endif /* __DRM_GEM_DMA_HELPER_H__ */
index d0a57853c188fee4822fa37b2bd89b59b3a5e08c..a2201b2488c56ca4a4d8fae79d8d8acd0f18c7c5 100644 (file)
@@ -210,7 +210,7 @@ static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj)
  * use it as their &drm_gem_object_funcs.get_sg_table handler.
  *
  * Returns:
- * A pointer to the scatter/gather table of pinned pages or NULL on failure.
+ * A pointer to the scatter/gather table of pinned pages or error pointer on failure.
  */
 static inline struct sg_table *drm_gem_shmem_object_get_sg_table(struct drm_gem_object *obj)
 {
index 91a164bdd8f3c879ef0464f596489e9bb233a17f..53e3a8a2f24170fec9ffc8d6391d825721db5188 100644 (file)
@@ -322,7 +322,7 @@ int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
 struct mipi_dsi_driver {
        struct device_driver driver;
        int(*probe)(struct mipi_dsi_device *dsi);
-       int(*remove)(struct mipi_dsi_device *dsi);
+       void (*remove)(struct mipi_dsi_device *dsi);
        void (*shutdown)(struct mipi_dsi_device *dsi);
 };
 
index 331ebd60b3a39ab58ae84bfbadd50604d27da5ac..1781fab24dd69177e5891e110fb108822e827bee 100644 (file)
 #ifndef DRM_PLANE_HELPER_H
 #define DRM_PLANE_HELPER_H
 
-#include <drm/drm_rect.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_modeset_helper_vtables.h>
-#include <drm/drm_modeset_helper.h>
+#include <linux/types.h>
 
-/*
- * Drivers that don't allow primary plane scaling may pass this macro in place
- * of the min/max scale parameters of the update checker function.
- *
- * Due to src being in 16.16 fixed point and dest being in integer pixels,
- * 1<<16 represents no scaling.
- */
-#define DRM_PLANE_HELPER_NO_SCALING (1<<16)
+struct drm_crtc;
+struct drm_framebuffer;
+struct drm_modeset_acquire_ctx;
+struct drm_plane;
 
-void drm_primary_helper_destroy(struct drm_plane *plane);
-extern const struct drm_plane_funcs drm_primary_helper_funcs;
+int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc,
+                                   struct drm_framebuffer *fb,
+                                   int crtc_x, int crtc_y,
+                                   unsigned int crtc_w, unsigned int crtc_h,
+                                   uint32_t src_x, uint32_t src_y,
+                                   uint32_t src_w, uint32_t src_h,
+                                   struct drm_modeset_acquire_ctx *ctx);
+int drm_plane_helper_disable_primary(struct drm_plane *plane,
+                                    struct drm_modeset_acquire_ctx *ctx);
+void drm_plane_helper_destroy(struct drm_plane *plane);
 
 #endif
index 2d524f8b080284ab0c64a975c6f58fec91b561cb..44a538ee5e2a6ce1fb0cee59ea321b386363ab42 100644 (file)
@@ -317,93 +317,16 @@ void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched);
 bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
                              const struct ttm_place *place);
 
-/**
- * ttm_bo_init_reserved
- *
- * @bdev: Pointer to a ttm_device struct.
- * @bo: Pointer to a ttm_buffer_object to be initialized.
- * @size: Requested size of buffer object.
- * @type: Requested type of buffer object.
- * @placement: Initial placement for buffer object.
- * @page_alignment: Data alignment in pages.
- * @ctx: TTM operation context for memory allocation.
- * @sg: Scatter-gather table.
- * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
- * @destroy: Destroy function. Use NULL for kfree().
- *
- * This function initializes a pre-allocated struct ttm_buffer_object.
- * As this object may be part of a larger structure, this function,
- * together with the @destroy function,
- * enables driver-specific objects derived from a ttm_buffer_object.
- *
- * On successful return, the caller owns an object kref to @bo. The kref and
- * list_kref are usually set to 1, but note that in some situations, other
- * tasks may already be holding references to @bo as well.
- * Furthermore, if resv == NULL, the buffer's reservation lock will be held,
- * and it is the caller's responsibility to call ttm_bo_unreserve.
- *
- * If a failure occurs, the function will call the @destroy function, or
- * kfree() if @destroy is NULL. Thus, after a failure, dereferencing @bo is
- * illegal and will likely cause memory corruption.
- *
- * Returns
- * -ENOMEM: Out of memory.
- * -EINVAL: Invalid placement flags.
- * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources.
- */
-
-int ttm_bo_init_reserved(struct ttm_device *bdev,
-                        struct ttm_buffer_object *bo,
-                        size_t size, enum ttm_bo_type type,
-                        struct ttm_placement *placement,
-                        uint32_t page_alignment,
-                        struct ttm_operation_ctx *ctx,
+int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo,
+                        enum ttm_bo_type type, struct ttm_placement *placement,
+                        uint32_t alignment, struct ttm_operation_ctx *ctx,
+                        struct sg_table *sg, struct dma_resv *resv,
+                        void (*destroy) (struct ttm_buffer_object *));
+int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo,
+                        enum ttm_bo_type type, struct ttm_placement *placement,
+                        uint32_t alignment, bool interruptible,
                         struct sg_table *sg, struct dma_resv *resv,
                         void (*destroy) (struct ttm_buffer_object *));
-
-/**
- * ttm_bo_init
- *
- * @bdev: Pointer to a ttm_device struct.
- * @bo: Pointer to a ttm_buffer_object to be initialized.
- * @size: Requested size of buffer object.
- * @type: Requested type of buffer object.
- * @placement: Initial placement for buffer object.
- * @page_alignment: Data alignment in pages.
- * @interruptible: If needing to sleep to wait for GPU resources,
- * sleep interruptible.
- * pinned in physical memory. If this behaviour is not desired, this member
- * holds a pointer to a persistent shmem object. Typically, this would
- * point to the shmem object backing a GEM object if TTM is used to back a
- * GEM user interface.
- * @sg: Scatter-gather table.
- * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one.
- * @destroy: Destroy function. Use NULL for kfree().
- *
- * This function initializes a pre-allocated struct ttm_buffer_object.
- * As this object may be part of a larger structure, this function,
- * together with the @destroy function,
- * enables driver-specific objects derived from a ttm_buffer_object.
- *
- * On successful return, the caller owns an object kref to @bo. The kref and
- * list_kref are usually set to 1, but note that in some situations, other
- * tasks may already be holding references to @bo as well.
- *
- * If a failure occurs, the function will call the @destroy function, or
- * kfree() if @destroy is NULL. Thus, after a failure, dereferencing @bo is
- * illegal and will likely cause memory corruption.
- *
- * Returns
- * -ENOMEM: Out of memory.
- * -EINVAL: Invalid placement flags.
- * -ERESTARTSYS: Interrupted by signal while sleeping waiting for resources.
- */
-int ttm_bo_init(struct ttm_device *bdev, struct ttm_buffer_object *bo,
-               size_t size, enum ttm_bo_type type,
-               struct ttm_placement *placement,
-               uint32_t page_alignment, bool interrubtible,
-               struct sg_table *sg, struct dma_resv *resv,
-               void (*destroy) (struct ttm_buffer_object *));
 
 /**
  * ttm_kmap_obj_virtual
index c8ccbc94d5d293e7d58673dab6369e1d20a096a1..0637659a702cd7a2da0f377ca818651fd8e5a3a2 100644 (file)
@@ -62,6 +62,11 @@ struct dma_resv_list;
  * For example when asking for WRITE fences then the KERNEL fences are returned
  * as well. Similar when asked for READ fences then both WRITE and KERNEL
  * fences are returned as well.
+ *
+ * Already used fences can be promoted in the sense that a fence with
+ * DMA_RESV_USAGE_BOOKKEEP could become DMA_RESV_USAGE_READ by adding it again
+ * with this usage. But fences can never be degraded in the sense that a fence
+ * with DMA_RESV_USAGE_WRITE could become DMA_RESV_USAGE_READ.
  */
 enum dma_resv_usage {
        /**
@@ -98,10 +103,15 @@ enum dma_resv_usage {
         * @DMA_RESV_USAGE_BOOKKEEP: No implicit sync.
         *
         * This should be used by submissions which don't want to participate in
-        * implicit synchronization.
+        * any implicit synchronization.
+        *
+        * The most common case are preemption fences, page table updates, TLB
+        * flushes as well as explicit synced user submissions.
         *
-        * The most common case are preemption fences as well as page table
-        * updates and their TLB flushes.
+        * Explicit synced user user submissions can be promoted to
+        * DMA_RESV_USAGE_READ or DMA_RESV_USAGE_WRITE as needed using
+        * dma_buf_import_sync_file() when implicit synchronization should
+        * become necessary after initial adding of the fence.
         */
        DMA_RESV_USAGE_BOOKKEEP
 };
index 07fcd0e566826d2497c7c5168093f67701275b94..0aff76bcbb00cff75d868e771e28204b29c5c17b 100644 (file)
@@ -615,10 +615,6 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern void unregister_framebuffer(struct fb_info *fb_info);
-extern int remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
-                                              const char *name);
-extern int remove_conflicting_framebuffers(struct apertures_struct *a,
-                                          const char *name, bool primary);
 extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
 extern int fb_show_logo(struct fb_info *fb_info, int rotate);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
@@ -631,16 +627,10 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var,
 extern int fb_get_options(const char *name, char **option);
 extern int fb_new_modelist(struct fb_info *info);
 
-extern struct fb_info *registered_fb[FB_MAX];
-extern int num_registered_fb;
 extern bool fb_center_logo;
 extern int fb_logo_count;
 extern struct class *fb_class;
 
-#define for_each_registered_fb(i)              \
-       for (i = 0; i < FB_MAX; i++)            \
-               if (!registered_fb[i]) {} else
-
 static inline void lock_fb_info(struct fb_info *info)
 {
        mutex_lock(&info->lock);
index a533cae189d795df89e0d32a911b888d9d050df8..cb71aa616bd37f8bacb5e70689814704c1671acd 100644 (file)
  *
  *     iosys_map_set_vaddr(&map, 0xdeadbeaf);
  *
- * To set an address in I/O memory, use iosys_map_set_vaddr_iomem().
+ * To set an address in I/O memory, use IOSYS_MAP_INIT_VADDR_IOMEM() or
+ * iosys_map_set_vaddr_iomem().
  *
  * .. code-block:: c
  *
+ *     struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(0xdeadbeaf);
+ *
  *     iosys_map_set_vaddr_iomem(&map, 0xdeadbeaf);
  *
  * Instances of struct iosys_map do not have to be cleaned up, but
@@ -121,6 +124,16 @@ struct iosys_map {
                .is_iomem = false,      \
        }
 
+/**
+ * IOSYS_MAP_INIT_VADDR_IOMEM - Initializes struct iosys_map to an address in I/O memory
+ * @vaddr_iomem_:      An I/O-memory address
+ */
+#define IOSYS_MAP_INIT_VADDR_IOMEM(vaddr_iomem_)       \
+       {                                               \
+               .vaddr_iomem = (vaddr_iomem_),          \
+               .is_iomem = true,                       \
+       }
+
 /**
  * IOSYS_MAP_INIT_OFFSET - Initializes struct iosys_map from another iosys_map
  * @map_:      The dma-buf mapping structure to copy from
index 0206f812c56995d2c608a921457195b2568dc0d2..868d6909b718290765e65cfaa7e5a06926f6598c 100644 (file)
@@ -99,18 +99,42 @@ extern "C" {
 #define DRM_FORMAT_INVALID     0
 
 /* color index */
+#define DRM_FORMAT_C1          fourcc_code('C', '1', ' ', ' ') /* [7:0] C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte */
+#define DRM_FORMAT_C2          fourcc_code('C', '2', ' ', ' ') /* [7:0] C0:C1:C2:C3 2:2:2:2 four pixels/byte */
+#define DRM_FORMAT_C4          fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 4:4 two pixels/byte */
 #define DRM_FORMAT_C8          fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
 
-/* 8 bpp Red */
+/* 1 bpp Darkness (inverse relationship between channel value and brightness) */
+#define DRM_FORMAT_D1          fourcc_code('D', '1', ' ', ' ') /* [7:0] D0:D1:D2:D3:D4:D5:D6:D7 1:1:1:1:1:1:1:1 eight pixels/byte */
+
+/* 2 bpp Darkness (inverse relationship between channel value and brightness) */
+#define DRM_FORMAT_D2          fourcc_code('D', '2', ' ', ' ') /* [7:0] D0:D1:D2:D3 2:2:2:2 four pixels/byte */
+
+/* 4 bpp Darkness (inverse relationship between channel value and brightness) */
+#define DRM_FORMAT_D4          fourcc_code('D', '4', ' ', ' ') /* [7:0] D0:D1 4:4 two pixels/byte */
+
+/* 8 bpp Darkness (inverse relationship between channel value and brightness) */
+#define DRM_FORMAT_D8          fourcc_code('D', '8', ' ', ' ') /* [7:0] D */
+
+/* 1 bpp Red (direct relationship between channel value and brightness) */
+#define DRM_FORMAT_R1          fourcc_code('R', '1', ' ', ' ') /* [7:0] R0:R1:R2:R3:R4:R5:R6:R7 1:1:1:1:1:1:1:1 eight pixels/byte */
+
+/* 2 bpp Red (direct relationship between channel value and brightness) */
+#define DRM_FORMAT_R2          fourcc_code('R', '2', ' ', ' ') /* [7:0] R0:R1:R2:R3 2:2:2:2 four pixels/byte */
+
+/* 4 bpp Red (direct relationship between channel value and brightness) */
+#define DRM_FORMAT_R4          fourcc_code('R', '4', ' ', ' ') /* [7:0] R0:R1 4:4 two pixels/byte */
+
+/* 8 bpp Red (direct relationship between channel value and brightness) */
 #define DRM_FORMAT_R8          fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
 
-/* 10 bpp Red */
+/* 10 bpp Red (direct relationship between channel value and brightness) */
 #define DRM_FORMAT_R10         fourcc_code('R', '1', '0', ' ') /* [15:0] x:R 6:10 little endian */
 
-/* 12 bpp Red */
+/* 12 bpp Red (direct relationship between channel value and brightness) */
 #define DRM_FORMAT_R12         fourcc_code('R', '1', '2', ' ') /* [15:0] x:R 4:12 little endian */
 
-/* 16 bpp Red */
+/* 16 bpp Red (direct relationship between channel value and brightness) */
 #define DRM_FORMAT_R16         fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
 
 /* 16 bpp RG */
@@ -205,7 +229,9 @@ extern "C" {
 #define DRM_FORMAT_VYUY                fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
 
 #define DRM_FORMAT_AYUV                fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_AVUY8888    fourcc_code('A', 'V', 'U', 'Y') /* [31:0] A:Cr:Cb:Y 8:8:8:8 little endian */
 #define DRM_FORMAT_XYUV8888    fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
+#define DRM_FORMAT_XVUY8888    fourcc_code('X', 'V', 'U', 'Y') /* [31:0] X:Cr:Cb:Y 8:8:8:8 little endian */
 #define DRM_FORMAT_VUY888      fourcc_code('V', 'U', '2', '4') /* [23:0] Cr:Cb:Y 8:8:8 little endian */
 #define DRM_FORMAT_VUY101010   fourcc_code('V', 'U', '3', '0') /* Y followed by U then V, 10:10:10. Non-linear modifier only */
 
index 0a0d56a6158e63275eda358e49d27e76c41a82b8..fa953309d9ce5775c15fffd5a7642a37e0f6d8e7 100644 (file)
@@ -675,11 +675,11 @@ struct drm_mode_fb_cmd {
  *   fetch metadata about an existing frame-buffer.
  *
  * In case of planar formats, this struct allows up to 4 buffer objects with
- * offsets and pitches per plane. The pitch and offset order is dictated by the
- * format FourCC as defined by ``drm_fourcc.h``, e.g. NV12 is described as:
+ * offsets and pitches per plane. The pitch and offset order are dictated by
+ * the format FourCC as defined by ``drm_fourcc.h``, e.g. NV12 is described as:
  *
- *     YUV 4:2:0 image with a plane of 8 bit Y samples followed by an
- *     interleaved U/V plane containing 8 bit 2x2 subsampled colour difference
+ *     YUV 4:2:0 image with a plane of 8-bit Y samples followed by an
+ *     interleaved U/V plane containing 8-bit 2x2 subsampled colour difference
  *     samples.
  *
  * So it would consist of a Y plane at ``offsets[0]`` and a UV plane at
index 9e40277d81858f0722df527a70cc6878ff448711..eac87310b3483c491f5d4c216776a8921ae80d26 100644 (file)
@@ -224,6 +224,53 @@ struct drm_panfrost_madvise {
        __u32 retained;       /* out, whether backing store still exists */
 };
 
+/* Definitions for coredump decoding in user space */
+#define PANFROSTDUMP_MAJOR 1
+#define PANFROSTDUMP_MINOR 0
+
+#define PANFROSTDUMP_MAGIC 0x464E4150 /* PANF */
+
+#define PANFROSTDUMP_BUF_REG 0
+#define PANFROSTDUMP_BUF_BOMAP (PANFROSTDUMP_BUF_REG + 1)
+#define PANFROSTDUMP_BUF_BO (PANFROSTDUMP_BUF_BOMAP + 1)
+#define PANFROSTDUMP_BUF_TRAILER (PANFROSTDUMP_BUF_BO + 1)
+
+struct panfrost_dump_object_header {
+       __le32 magic;
+       __le32 type;
+       __le32 file_size;
+       __le32 file_offset;
+
+       union {
+               struct pan_reg_hdr {
+                       __le64 jc;
+                       __le32 gpu_id;
+                       __le32 major;
+                       __le32 minor;
+                       __le64 nbos;
+               } reghdr;
+
+               struct pan_bomap_hdr {
+                       __le32 valid;
+                       __le64 iova;
+                       __le32 data[2];
+               } bomap;
+
+               /*
+                * Force same size in case we want to expand the header
+                * with new fields and also keep it 512-byte aligned
+                */
+
+               __le32 sizer[496];
+       };
+};
+
+/* Registers object, an array of these */
+struct panfrost_dump_registers {
+       __le32 reg;
+       __le32 value;
+};
+
 #if defined(__cplusplus)
 }
 #endif
index d334e64c1c193e23d739510bd164d96944112206..947c0abd04ef9332d6868fa97f3f16dcdb3c53b3 100644 (file)
@@ -2,15 +2,15 @@
  * linux/include/video/vga.h -- standard VGA chipset interaction
  *
  * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
- * 
+ *
  * Copyright history from vga16fb.c:
  *     Copyright 1999 Ben Pfaff and Petr Vandrovec
- *     Based on VGA info at http://www.osdever.net/FreeVGA/home.htm 
+ *     Based on VGA info at http://www.osdever.net/FreeVGA/home.htm
  *     Based on VESA framebuffer (c) 1998 Gerd Knorr
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file COPYING in the main directory of this
- * archive for more details.  
+ * archive for more details.
  *
  */
 
@@ -22,6 +22,8 @@
 #include <asm/vga.h>
 #include <asm/byteorder.h>
 
+#define VGA_FB_PHYS_BASE       0xA0000 /* VGA framebuffer I/O base */
+#define VGA_FB_PHYS_SIZE       65536   /* VGA framebuffer I/O size */
 
 /* Some of the code below is taken from SVGAlib.  The original,
    unmodified copyright notice for that code is below. */
@@ -190,7 +192,7 @@ struct vgastate {
        __u32 num_gfx;          /* number of gfx registers, 0 for default  */
        __u32 num_seq;          /* number of seq registers, 0 for default  */
        void *vidstate;
-};     
+};
 
 extern int save_vga(struct vgastate *state);
 extern int restore_vga(struct vgastate *state);
@@ -198,7 +200,7 @@ extern int restore_vga(struct vgastate *state);
 /*
  * generic VGA port read/write
  */
+
 static inline unsigned char vga_io_r (unsigned short port)
 {
        return inb_p(port);
@@ -261,7 +263,7 @@ static inline void vga_w_fast (void __iomem *regbase, unsigned short port,
 /*
  * VGA CRTC register read/write
  */
+
 static inline unsigned char vga_rcrt (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_CRT_IC, reg);
@@ -314,7 +316,7 @@ static inline void vga_mm_wcrt (void __iomem *regbase, unsigned char reg, unsign
 /*
  * VGA sequencer register read/write
  */
+
 static inline unsigned char vga_rseq (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_SEQ_I, reg);
@@ -366,7 +368,7 @@ static inline void vga_mm_wseq (void __iomem *regbase, unsigned char reg, unsign
 /*
  * VGA graphics controller register read/write
  */
+
 static inline unsigned char vga_rgfx (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_GFX_I, reg);
@@ -419,7 +421,7 @@ static inline void vga_mm_wgfx (void __iomem *regbase, unsigned char reg, unsign
 /*
  * VGA attribute controller register read/write
  */
+
 static inline unsigned char vga_rattr (void __iomem *regbase, unsigned char reg)
 {
         vga_w (regbase, VGA_ATT_IW, reg);