Monday, April 27, 2015

GSoC: Convert the BOCHS and CIRRUS drivers to atomic mode-setting

This is my first blog on the project Google Summer of Code. I just post my proposal below:


Organization: X.Org Foundation
Mentor: Daniel Vetter
Abstract: Atomic mode-setting has been discussed and designed for literally years, now it's finally there, it is not only necessary but allows a bunch of nice and long overdue cleanup and unification. There are a lot ongoing atomic mode-setting conversions and some already committed to drm-next ones, while there still are some subsystems haven't started the work, as far as I know, radeon, udl, bochs and cirrus are some optional drivers. I will take DRM_BOCHS and DRM_CIRRUS_QEMU as my converting goals.

Introduction to the Project
This project aims to convert two existing KMS drivers to atomic mode-setting, DRM_BOCHS and DRM_CIRRUS_QEMU.
BOCHS stands for standard VGA card with Bochs VBE extensions, we can emulate it in qemu by adding the option '-vga std'. While CIRRUS is the default Video card that QEMU emulated. 
For these two drivers used by KVM/QEMU, they are still in the Renaissace era of KMS, something not perfect:
  • mode sets fail too late, if the mode-setting fails, there's no way to rollback
  • KMS does not guarantee that a configuration is applied in totality for the next frame
  • no VBLANK-synchronized page-flips for planes
  • not perfect frames
As we all know the weaknesses in the legacy KMS drivers now, we should overcome them by convert the drivers into Atomic Mode-Setting. The Atomic Mode-Setting
  • allows an output configuration to be validated before it is applied:
    • no hardware is touched before the driver acknowleges that the configuration is valid and can be applied
    • no need for rollback
  • allows atomic updates of an output configuration:
    • multiple planes updated at the same time
    • we got perfect frames show at the same time
  • allows for unification and simplification of drivers
    • legacy code can be removed from drivers
    • much of the handling moves into helpers (core DRM)

Project Goals
The project shall complete two legacy KMS drivers conversion individually:
  1. convert DRM_BOCHS driver into Atomic Mode-Setting driver
  2. convert DRM_CIRRUS_QEMU driver into Atomic Mode-Setting driver
Since Daniel did most of the Transtional and atomic helpers work, so the conversion is surprisingly painless.

Quantifiable Results for the DRI Community
  • Make it a more complete ecosystem for the atomic mode-setting
  • Use unified helpers will make it more concise for the subsystem, less code

Project Details
Since radeon support about 18 years of asics and 8 generations of display hardwares, the conversion will be a huge amout of work and there is a huge potential regressions, so I choose two drivers used by kvm/qeum, which are a lot simpler than mordern GPUs.
The following specified what needs to be done to support atomic modeset updates using Daniel's new helper libraries.
Phase 1 - Reworking the Driver Backend Functions for Planes
There are two big mismatches between the new atomic semantics and the legacy ioctl interfaces:
    1) The primary plane is no longer tied to CRTC.
    2) Atomic updates of multiple planes isn't supported at all.
Both issuse are addressed by adding new driver backend callbacks. So we should implement legacy entry points in term of new atomic callbacks.
The first step is to rework the ->disable/update_plane hooks using the transitional helper implementations drm_plane_helper_update/disable. The following new driver callbacks are needed:
  • CRTCs
    • ->atomic_check()      - validate state
    • ->atomic_begin()      - prepare for updates
    • ->atomic_flush()       - apply updates atomically
    • ->atomic_set_nofb    - apply CRTC timings, this callback must be implement
  • planes
    • ->prepare_fb()          - setup the framebuffers, e.g. pin backing storage into memory and setup any needed hardware resources
    • ->cleanup_fb()          - e.g. unpi backing storage
    • ->atomic_check()      - validate state
    • ->atomic_update()     - per-plane update, like setting up the new viewport or the new base address of the framebuffer for each plane
    • ->atomic_disable()     - disable plane
The provided helpers functions drm_helper_crtc_mode_set and drm_helper_crtc_mode_set_base then implement the callbacks required by the CRTC helpers in terms of new ->mode_set_nofb callback and the the above newly implmented plane helper callbacks.
Phase 2 - Wire up the Atomic State Object Scaffolding
The goal of this phase is to get all the state object handing needed for atomic updates into place.
  • wire up state callbacks for planes, CRTCs and connectors:
    • ->reset()
      • drm_atomic_helper_*_reset()
    • ->atomic_duplicate_state()
      • drm_atomic_helper_*_duplicate_state()
    • ->atomic_destroy_state()
      • drm_atomic_helper_*_destroy_state()
  • patching up the state objects in legacy code paths
    • make sure that we can partially transition to atomic updates.
    • drm_atomic_set_fb_for_plane
      • usually the only place this is need to be manually added is the ->page_flip callback.
  • all ->mode_fixup callbacks need to be audited
    • not depend upon any state which is only set in the various CRTC helpers.
    • not tracked by the atomic state objects.
Phase 3 - Rolling out Atomic Support
Replace all the legacy entry pointers with the corresponding functions from the atomic helper library to implement them in terms of atomic.
  • switch to atomic helpers internally (after this Drivers uses only atomic interfaces internally):
    • Planes:
      • drm_atomic_helper_update_plane()
      • drm_atomic_helper_disable_plane()
    • Drivers
      • drm_atomic_helper_check()
      • drm_atomic_helper_commit()
  • switch to atomic helpers for userspace IOCTLs (after this Drivers is fully atomic):
    • drm_atomic_helper_set_config(): DRM_MODE_IOCTL_SET_CRTC
    • provide a customer ->atomic_commit() implementation to support asynchronous commits, required for page-flipping
    • drm_atomic_helper_page_flip(): DRM_MODE_IOCTL_PAGE_FLIP
Rip out Cruft
There is quite a bit of cleanup work possible afterwards.
  • ->mode_set() and ->mode_set_base() are no longer used, ->mode_set_nofb() does what is necessary to set a mode.
  • atomic DPMS, DPMS standby and suspend are no more, ->disable() and ->enable() callbacks are used now, atomic DPMS is a full off or on cycle

References
Approximative Schedule
(now - 15 April)
     - get familiar with the Atomic Modeset Support for KMS Drivers
     - take a look at the ongoing atomic mode-setting conversations and those already committed to drm-next
     - discuss with the mentor about some confusing details on the code
(16 April - 27 April )
     - get to know more about the DRM_BOCHS and DRM_CIRRUS_QEMU subsystem driver code
     - setup the kvm/qemu environment for further test
(28 April - 18 May)
     - code: write my first version of the atomic mode-setting conversion for DRM_BOCHS driver
     - discuss with the mentor about the conversion if the patches meet the demand
(19 May - 15 June)
     - code: write my second version of the atomic mode-setting conversion for DRM_BOCHS driver
     - test: test the new converted Bochs driver on qemu, using the '-vga std' option
(16 June - 25 June)
     - submit patches to the dri-devel@lists.freedesktop.org, if anything wrong, modify it
     - get to know more about the DRM_CIRRUS_QEMU subsystem
(26 June - 30 June)
     - arrange documentations for mid-term evaluations
(1 July - 3 July)
     - submit mid-term evaluations
(4 July - 17 August)
     - code: write the atomic mode-setting conversion for DRM_CIRRUS_QEMU (same schedule with DRM_BOCHS)
     - do more test to assure the correctness and check the code.
(18 August - 21 August)
     - arrange documets for reports, scub code, write tests, improve documentation, etc.
(22 August - 27 August)
     - submit final evaluations.
(28 August - 30 August)
     - submit required code samples to Google.
(after GSoC)
     - as Alex Deucher suggest, in additon to the two virtual drivers I am going to convert, udl (KMS driver for the USB displaylink video adapters) is another choice for me, as I am still not that skilled in Atomic Modeset Support for KMS Drivers, I will give it a shot after GSoC. 
     - as for the Radeon, since Alex said the community have no immediate plans to convert it to atomic, I hope when it is on the agenda in the future, I can do something helpful.

Stretch Goals
If time permits,
     - I will convert these two drivers to explicitly set up the primary plane, or at least have the appropriate list of supported pixel formats.
     - I will also try to convert the DRM_UDL(KMS driver for the USB displaylink video adapter) to atomic mode-setting which I mentioned before. 

About me 
I am studying for my Master Degree in Peking University, where I am majoring in Computer Architecture.  In the last semester, my lab mentor arrange me to look into the DRM ecosystem, so I can write a Geode LX drm driver later on. I am not sure whether this is significant, but this GSoC project will definitely helps me a lot on understanding the whole ecosystem. Some of my contributions can be found here:
Thank you for reading. Have a nice day.