code:
===============================================
 drm/tegra NVIDIA Tegra GPU and display driver
===============================================

NVIDIA Tegra SoCs support a set of display, graphics and video functions via
the host1x controller. host1x supplies command streams, gathered from a push
buffer provided directly by the CPU, to its clients via channels. Software,
or blocks amongst themselves, can use syncpoints for synchronization.

Up until, but not including, Tegra124 (aka Tegra K1) the drm/tegra driver
supports the built-in GPU, comprised of the gr2d and gr3d engines. Starting
with Tegra124 the GPU is based on the NVIDIA desktop GPU architecture and
supported by the drm/nouveau driver.

The drm/tegra driver supports NVIDIA Tegra SoC generations since Tegra20. It
has three parts:

  - A host1x driver that provides infrastructure and access to the host1x
    services.

  - A KMS driver that supports the display controllers as well as a number of
    outputs, such as RGB, HDMI, DSI, and DisplayPort.

  - A set of custom userspace IOCTLs that can be used to submit jobs to the
    GPU and video engines via host1x.

Driver Infrastructure
=====================

The various host1x clients need to be bound together into a logical device in
order to expose their functionality to users. The infrastructure that supports
this is implemented in the host1x driver. When a driver is registered with the
infrastructure it provides a list of compatible strings specifying the devices
that it needs. The infrastructure creates a logical device and scan the device
tree for matching device nodes, adding the required clients to a list. Drivers
for individual clients register with the infrastructure as well and are added
to the logical host1x device.

Once all clients are available, the infrastructure will initialize the logical
device using a driver-provided function which will set up the bits specific to
the subsystem and in turn initialize each of its clients.

Similarly, when one of the clients is unregistered, the infrastructure will
destroy the logical device by calling back into the driver, which ensures that
the subsystem specific bits are torn down and the clients destroyed in turn.

Host1x Infrastructure Reference
-------------------------------

.. kernel-doc:: include/linux/host1x.h

.. kernel-doc:: drivers/gpu/host1x/bus.c
   :export:

Host1x Syncpoint Reference
--------------------------

.. kernel-doc:: drivers/gpu/host1x/syncpt.c
   :export:

KMS driver
==========

The display hardware has remained mostly backwards compatible over the various
Tegra SoC generations, up until Tegra186 which introduces several changes that
make it difficult to support with a parameterized driver.

Display Controllers
-------------------

Tegra SoCs have two display controllers, each of which can be associated with
zero or more outputs. Outputs can also share a single display controller, but
only if they run with compatible display timings. Two display controllers can
also share a single framebuffer, allowing cloned configurations even if modes
on two outputs don't match. A display controller is modelled as a CRTC in KMS
terms.

On Tegra186, the number of display controllers has been increased to three. A
display controller can no longer drive all of the outputs. While two of these
controllers can drive both DSI outputs and both SOR outputs, the third cannot
drive any DSI.

Windows
~~~~~~~

A display controller controls a set of windows that can be used to composite
multiple buffers onto the screen. While it is possible to assign arbitrary Z
ordering to individual windows (by programming the corresponding blending
registers), this is currently not supported by the driver. Instead, it will
assume a fixed Z ordering of the windows (window A is the root window, that
is, the lowest, while windows B and C are overlaid on top of window A). The
overlay windows support multiple pixel formats and can automatically convert
from YUV to RGB at scanout time. This makes them useful for displaying video
content. In KMS, each window is modelled as a plane. Each display controller
has a hardware cursor that is exposed as a cursor plane.

Outputs
-------

The type and number of supported outputs varies between Tegra SoC generations.
All generations support at least HDMI. While earlier generations supported the
very simple RGB interfaces (one per display controller), recent generations no
longer do and instead provide standard interfaces such as DSI and eDP/DP.

Outputs are modelled as a composite encoder/connector pair.

RGB/LVDS
~~~~~~~~

This interface is no longer available since Tegra124. It has been replaced by
the more standard DSI and eDP interfaces.

HDMI
~~~~

HDMI is supported on all Tegra SoCs. Starting with Tegra210, HDMI is provided
by the versatile SOR output, which supports eDP, DP and HDMI. The SOR is able
to support HDMI 2.0, though support for this is currently not merged.

DSI
~~~

Although Tegra has supported DSI since Tegra30, the controller has changed in
several ways in Tegra114. Since none of the publicly available development
boards prior to Dalmore (Tegra114) have made use of DSI, only Tegra114 and
later are supported by the drm/tegra driver.

eDP/DP
~~~~~~

eDP was first introduced in Tegra124 where it was used to drive the display
panel for notebook form factors. Tegra210 added support for full DisplayPort
support, though this is currently not implemented in the drm/tegra driver.

Userspace Interface
===================

The userspace interface provided by drm/tegra allows applications to create
GEM buffers, access and control syncpoints as well as submit command streams
to host1x.

GEM Buffers
-----------

The ``DRM_IOCTL_TEGRA_GEM_CREATE`` IOCTL is used to create a GEM buffer object
with Tegra-specific flags. This is useful for buffers that should be tiled, or
that are to be scanned out upside down (useful for 3D content).

After a GEM buffer object has been created, its memory can be mapped by an
application using the mmap offset returned by the ``DRM_IOCTL_TEGRA_GEM_MMAP``
IOCTL.

Syncpoints
----------

The current value of a syncpoint can be obtained by executing the
``DRM_IOCTL_TEGRA_SYNCPT_READ`` IOCTL. Incrementing the syncpoint is achieved
using the ``DRM_IOCTL_TEGRA_SYNCPT_INCR`` IOCTL.

Userspace can also request blocking on a syncpoint. To do so, it needs to
execute the ``DRM_IOCTL_TEGRA_SYNCPT_WAIT`` IOCTL, specifying the value of
the syncpoint to wait for. The kernel will release the application when the
syncpoint reaches that value or after a specified timeout.

Command Stream Submission
-------------------------

Before an application can submit command streams to host1x it needs to open a
channel to an engine using the ``DRM_IOCTL_TEGRA_OPEN_CHANNEL`` IOCTL. Client
IDs are used to identify the target of the channel. When a channel is no
longer needed, it can be closed using the ``DRM_IOCTL_TEGRA_CLOSE_CHANNEL``
IOCTL. To retrieve the syncpoint associated with a channel, an application
can use the ``DRM_IOCTL_TEGRA_GET_SYNCPT``.

After opening a channel, submitting command streams is easy. The application
writes commands into the memory backing a GEM buffer object and passes these
to the ``DRM_IOCTL_TEGRA_SUBMIT`` IOCTL along with various other parameters,
such as the syncpoints or relocations used in the job submission.


code:
.. _todo:

=========
TODO list
=========

This section contains a list of smaller janitorial tasks in the kernel DRM
graphics subsystem useful as newbie projects. Or for slow rainy days.

Difficulty
----------

To make it easier task are categorized into different levels:

Starter: Good tasks to get started with the DRM subsystem.

Intermediate: Tasks which need some experience with working in the DRM
subsystem, or some specific GPU/display graphics knowledge. For debugging issue
it's good to have the relevant hardware (or a virtual driver set up) available
for testing.

Advanced: Tricky tasks that need fairly good understanding of the DRM subsystem
and graphics topics. Generally need the relevant hardware for development and
testing.

Expert: Only attempt these if you've successfully completed some tricky
refactorings already and are an expert in the specific area

Subsystem-wide refactorings
===========================

Remove custom dumb_map_offset implementations
---------------------------------------------

All GEM based drivers should be using drm_gem_create_mmap_offset() instead.
Audit each individual driver, make sure it'll work with the generic
implementation (there's lots of outdated locking leftovers in various
implementations), and then remove it.

Contact: Daniel Vetter, respective driver maintainers

Level: Intermediate

Convert existing KMS drivers to atomic modesetting
--------------------------------------------------

3.19 has the atomic modeset interfaces and helpers, so drivers can now be
converted over. Modern compositors like Wayland or Surfaceflinger on Android
really want an atomic modeset interface, so this is all about the bright
future.

There is a conversion guide for atomic and all you need is a GPU for a
non-converted driver (again virtual HW drivers for KVM are still all
suitable).

As part of this drivers also need to convert to universal plane (which means
exposing primary & cursor as proper plane objects). But that's much easier to
do by directly using the new atomic helper driver callbacks.

Contact: Daniel Vetter, respective driver maintainers

Level: Advanced

Clean up the clipped coordination confusion around planes
---------------------------------------------------------

We have a helper to get this right with drm_plane_helper_check_update(), but
it's not consistently used. This should be fixed, preferrably in the atomic
helpers (and drivers then moved over to clipped coordinates). Probably the
helper should also be moved from drm_plane_helper.c to the atomic helpers, to
avoid confusion - the other helpers in that file are all deprecated legacy
helpers.

Contact: Ville Syrjälä, Daniel Vetter, driver maintainers

Level: Advanced

Improve plane atomic_check helpers
----------------------------------

Aside from the clipped coordinates right above there's a few suboptimal things
with the current helpers:

- drm_plane_helper_funcs->atomic_check gets called for enabled or disabled
  planes. At best this seems to confuse drivers, worst it means they blow up
  when the plane is disabled without the CRTC. The only special handling is
  resetting values in the plane state structures, which instead should be moved
  into the drm_plane_funcs->atomic_duplicate_state functions.

- Once that's done, helpers could stop calling ->atomic_check for disabled
  planes.

- Then we could go through all the drivers and remove the more-or-less confused
  checks for plane_state->fb and plane_state->crtc.

Contact: Daniel Vetter

Level: Advanced

Convert early atomic drivers to async commit helpers
----------------------------------------------------

For the first year the atomic modeset helpers didn't support asynchronous /
nonblocking commits, and every driver had to hand-roll them. This is fixed
now, but there's still a pile of existing drivers that easily could be
converted over to the new infrastructure.

One issue with the helpers is that they require that drivers handle completion
events for atomic commits correctly. But fixing these bugs is good anyway.

Somewhat related is the legacy_cursor_update hack, which should be replaced with
the new atomic_async_check/commit functionality in the helpers in drivers that
still look at that flag.

Contact: Daniel Vetter, respective driver maintainers

Level: Advanced

Fallout from atomic KMS
-----------------------

``drm_atomic_helper.c`` provides a batch of functions which implement legacy
IOCTLs on top of the new atomic driver interface. Which is really nice for
gradual conversion of drivers, but unfortunately the semantic mismatches are
a bit too severe. So there's some follow-up work to adjust the function
interfaces to fix these issues:

* atomic needs the lock acquire context. At the moment that's passed around
  implicitly with some horrible hacks, and it's also allocate with
  ``GFP_NOFAIL`` behind the scenes. All legacy paths need to start allocating
  the acquire context explicitly on stack and then also pass it down into
  drivers explicitly so that the legacy-on-atomic functions can use them.

  Except for some driver code this is done. This task should be finished by
  adding WARN_ON(!drm_drv_uses_atomic_modeset) in drm_modeset_lock_all().

* A bunch of the vtable hooks are now in the wrong place: DRM has a split
  between core vfunc tables (named ``drm_foo_funcs``), which are used to
  implement the userspace ABI. And then there's the optional hooks for the
  helper libraries (name ``drm_foo_helper_funcs``), which are purely for
  internal use. Some of these hooks should be move from ``_funcs`` to
  ``_helper_funcs`` since they are not part of the core ABI. There's a
  ``FIXME`` comment in the kerneldoc for each such case in ``drm_crtc.h``.

Contact: Daniel Vetter

Level: Intermediate

Get rid of dev->struct_mutex from GEM drivers
---------------------------------------------

``dev->struct_mutex`` is the Big DRM Lock from legacy days and infested
everything. Nowadays in modern drivers the only bit where it's mandatory is
serializing GEM buffer object destruction. Which unfortunately means drivers
have to keep track of that lock and either call ``unreference`` or
``unreference_locked`` depending upon context.

Core GEM doesn't have a need for ``struct_mutex`` any more since kernel 4.8,
and there's a GEM object ``free`` callback for any drivers which are
entirely ``struct_mutex`` free.

For drivers that need ``struct_mutex`` it should be replaced with a driver-
private lock. The tricky part is the BO free functions, since those can't
reliably take that lock any more. Instead state needs to be protected with
suitable subordinate locks or some cleanup work pushed to a worker thread. For
performance-critical drivers it might also be better to go with a more
fine-grained per-buffer object and per-context lockings scheme. Currently only
the ``msm`` and `i915` drivers use ``struct_mutex``.

Contact: Daniel Vetter, respective driver maintainers

Level: Advanced

Move Buffer Object Locking to dma_resv_lock()
---------------------------------------------

Many drivers have their own per-object locking scheme, usually using
mutex_lock(). This causes all kinds of trouble for buffer sharing, since
depending which driver is the exporter and importer, the locking hierarchy is
reversed.

To solve this we need one standard per-object locking mechanism, which is
dma_resv_lock(). This lock needs to be called as the outermost lock, with all
other driver specific per-object locks removed. The problem is tha rolling out
the actual change to the locking contract is a flag day, due to struct dma_buf
buffer sharing.

Level: Expert

Convert logging to drm_* functions with drm_device paramater
------------------------------------------------------------

For drivers which could have multiple instances, it is necessary to
differentiate between which is which in the logs. Since DRM_INFO/WARN/ERROR
don't do this, drivers used dev_info/warn/err to make this differentiation. We
now have drm_* variants of the drm print functions, so we can start to convert
those drivers back to using drm-formatted specific log messages.

Before you start this conversion please contact the relevant maintainers to make
sure your work will be merged - not everyone agrees that the DRM dmesg macros
are better.

Contact: Sean Paul, Maintainer of the driver you plan to convert

Level: Starter

Convert drivers to use simple modeset suspend/resume
----------------------------------------------------

Most drivers (except i915 and nouveau) that use
drm_atomic_helper_suspend/resume() can probably be converted to use
drm_mode_config_helper_suspend/resume(). Also there's still open-coded version
of the atomic suspend/resume code in older atomic modeset drivers.

Contact: Maintainer of the driver you plan to convert

Level: Intermediate

Convert drivers to use drm_fbdev_generic_setup()
------------------------------------------------

Most drivers can use drm_fbdev_generic_setup(). Driver have to implement
atomic modesetting and GEM vmap support. Historically, generic fbdev emulation
expected the framebuffer in system memory or system-like memory. By employing
struct iosys_map, drivers with frambuffers in I/O memory can be supported
as well.

Contact: Maintainer of the driver you plan to convert

Level: Intermediate

Reimplement functions in drm_fbdev_fb_ops without fbdev
-------------------------------------------------------

A number of callback functions in drm_fbdev_fb_ops could benefit from
being rewritten without dependencies on the fbdev module. Some of the
helpers could further benefit from using struct iosys_map instead of
raw pointers.

Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter

Level: Advanced

Benchmark and optimize blitting and format-conversion function
--------------------------------------------------------------

Drawing to dispay memory quickly is crucial for many applications'
performance.

On at least x86-64, sys_imageblit() is significantly slower than
cfb_imageblit(), even though both use the same blitting algorithm and
the latter is written for I/O memory. It turns out that cfb_imageblit()
uses movl instructions, while sys_imageblit apparently does not. This
seems to be a problem with gcc's optimizer. DRM's format-conversion
helpers might be subject to similar issues.

Benchmark and optimize fbdev's sys_() helpers and DRM's format-conversion
helpers. In cases that can be further optimized, maybe implement a different
algorithm. For micro-optimizations, use movl/movq instructions explicitly.
That might possibly require architecture-specific helpers (e.g., storel()
storeq()).

Contact: Thomas Zimmermann <tzimmermann@suse.de>

Level: Intermediate

drm_framebuffer_funcs and drm_mode_config_funcs.fb_create cleanup
-----------------------------------------------------------------

A lot more drivers could be switched over to the drm_gem_framebuffer helpers.
Various hold-ups:

- Need to switch over to the generic dirty tracking code using
  drm_atomic_helper_dirtyfb first (e.g. qxl).

- Need to switch to drm_fbdev_generic_setup(), otherwise a lot of the custom fb
  setup code can't be deleted.

- Many drivers wrap drm_gem_fb_create() only to check for valid formats. For
  atomic drivers we could check for valid formats by calling
  drm_plane_check_pixel_format() against all planes, and pass if any plane
  supports the format. For non-atomic that's not possible since like the format
  list for the primary plane is fake and we'd therefor reject valid formats.

- Many drivers subclass drm_framebuffer, we'd need a embedding compatible
  version of the varios drm_gem_fb_create functions. Maybe called
  drm_gem_fb_create/_with_dirty/_with_funcs as needed.

Contact: Daniel Vetter

Level: Intermediate

Generic fbdev defio support
---------------------------

The defio support code in the fbdev core has some very specific requirements,
which means drivers need to have a special framebuffer for fbdev. The main
issue is that it uses some fields in struct page itself, which breaks shmem
gem objects (and other things). To support defio, affected drivers require
the use of a shadow buffer, which may add CPU and memory overhead.

Possible solution would be to write our own defio mmap code in the drm fbdev
emulation. It would need to fully wrap the existing mmap ops, forwarding
everything after it has done the write-protect/mkwrite trickery:

- In the drm_fbdev_fb_mmap helper, if we need defio, change the
  default page prots to write-protected with something like this::

      vma->vm_page_prot = pgprot_wrprotect(vma->vm_page_prot);

- Set the mkwrite and fsync callbacks with similar implementions to the core
  fbdev defio stuff. These should all work on plain ptes, they don't actually
  require a struct page.  uff. These should all work on plain ptes, they don't
  actually require a struct page.

- Track the dirty pages in a separate structure (bitfield with one bit per page
  should work) to avoid clobbering struct page.

Might be good to also have some igt testcases for this.

Contact: Daniel Vetter, Noralf Tronnes

Level: Advanced

struct drm_gem_object_funcs
---------------------------

GEM objects can now have a function table instead of having the callbacks on the
DRM driver struct. This is now the preferred way. Callbacks in drivers have been
converted, except for struct drm_driver.gem_prime_mmap.

Level: Intermediate

connector register/unregister fixes
-----------------------------------

- For most connectors it's a no-op to call drm_connector_register/unregister
  directly from driver code, drm_dev_register/unregister take care of this
  already. We can remove all of them.

- For dp drivers it's a bit more a mess, since we need the connector to be
  registered when calling drm_dp_aux_register. Fix this by instead calling
  drm_dp_aux_init, and moving the actual registering into a late_register
  callback as recommended in the kerneldoc.

Level: Intermediate

Remove load/unload callbacks from all non-DRIVER_LEGACY drivers
---------------------------------------------------------------

The load/unload callbacks in struct &drm_driver are very much midlayers, plus
for historical reasons they get the ordering wrong (and we can't fix that)
between setting up the &drm_driver structure and calling drm_dev_register().

- Rework drivers to no longer use the load/unload callbacks, directly coding the
  load/unload sequence into the driver's probe function.

- Once all non-DRIVER_LEGACY drivers are converted, disallow the load/unload
  callbacks for all modern drivers.

Contact: Daniel Vetter

Level: Intermediate

Replace drm_detect_hdmi_monitor() with drm_display_info.is_hdmi
---------------------------------------------------------------

Once EDID is parsed, the monitor HDMI support information is available through
drm_display_info.is_hdmi. Many drivers still call drm_detect_hdmi_monitor() to
retrieve the same information, which is less efficient.

Audit each individual driver calling drm_detect_hdmi_monitor() and switch to
drm_display_info.is_hdmi if applicable.

Contact: Laurent Pinchart, respective driver maintainers

Level: Intermediate

Consolidate custom driver modeset properties
--------------------------------------------

Before atomic modeset took place, many drivers where creating their own
properties. Among other things, atomic brought the requirement that custom,
driver specific properties should not be used.

For this task, we aim to introduce core helpers or reuse the existing ones
if available:

A quick, unconfirmed, examples list.

Introduce core helpers:
- audio (amdgpu, intel, gma500, radeon)
- brightness, contrast, etc (armada, nouveau) - overlay only (?)
- broadcast rgb (gma500, intel)
- colorkey (armada, nouveau, rcar) - overlay only (?)
- dither (amdgpu, nouveau, radeon) - varies across drivers
- underscan family (amdgpu, radeon, nouveau)

Already in core:
- colorspace (sti)
- tv format names, enhancements (gma500, intel)
- tv overscan, margins, etc. (gma500, intel)
- zorder (omapdrm) - same as zpos (?)

Contact: Emil Velikov, respective driver maintainers

Level: Intermediate

Use struct iosys_map throughout codebase
----------------------------------------

Pointers to shared device memory are stored in struct iosys_map. Each
instance knows whether it refers to system or I/O memory. Most of the DRM-wide
interface have been converted to use struct iosys_map, but implementations
often still use raw pointers.

The task is to use struct iosys_map where it makes sense.

* Memory managers should use struct iosys_map for dma-buf-imported buffers.
* TTM might benefit from using struct iosys_map internally.
* Framebuffer copying and blitting helpers should operate on struct iosys_map.

Contact: Thomas Zimmermann <tzimmermann@suse.de>, Christian König, Daniel Vetter

Level: Intermediate

Review all drivers for setting struct drm_mode_config.{max_width,max_height} correctly
--------------------------------------------------------------------------------------

The values in struct drm_mode_config.{max_width,max_height} describe the
maximum supported framebuffer size. It's the virtual screen size, but many
drivers treat it like limitations of the physical resolution.

The maximum width depends on the hardware's maximum scanline pitch. The
maximum height depends on the amount of addressable video memory. Review all
drivers to initialize the fields to the correct values.

Contact: Thomas Zimmermann <tzimmermann@suse.de>

Level: Intermediate

Request memory regions in all drivers
-------------------------------------

Go through all drivers and add code to request the memory regions that the
driver uses. This requires adding calls to request_mem_region(),
pci_request_region() or similar functions. Use helpers for managed cleanup
where possible.

Drivers are pretty bad at doing this and there used to be conflicts among
DRM and fbdev drivers. Still, it's the correct thing to do.

Contact: Thomas Zimmermann <tzimmermann@suse.de>

Level: Starter

Core refactorings
=================

Make panic handling work
------------------------

This is a really varied tasks with lots of little bits and pieces:

* The panic path can't be tested currently, leading to constant breaking. The
  main issue here is that panics can be triggered from hardirq contexts and
  hence all panic related callback can run in hardirq context. It would be
  awesome if we could test at least the fbdev helper code and driver code by
  e.g. trigger calls through drm debugfs files. hardirq context could be
  achieved by using an IPI to the local processor.

* There's a massive confusion of different panic handlers. DRM fbdev emulation
  helpers had their own (long removed), but on top of that the fbcon code itself
  also has one. We need to make sure that they stop fighting over each other.
  This is worked around by checking ``oops_in_progress`` at various entry points
  into the DRM fbdev emulation helpers. A much cleaner approach here would be to
  switch fbcon to the `threaded printk support
  <https://lwn.net/Articles/800946/>`_.

* ``drm_can_sleep()`` is a mess. It hides real bugs in normal operations and
  isn't a full solution for panic paths. We need to make sure that it only
  returns true if there's a panic going on for real, and fix up all the
  fallout.

* The panic handler must never sleep, which also means it can't ever
  ``mutex_lock()``. Also it can't grab any other lock unconditionally, not
  even spinlocks (because NMI and hardirq can panic too). We need to either
  make sure to not call such paths, or trylock everything. Really tricky.

* A clean solution would be an entirely separate panic output support in KMS,
  bypassing the current fbcon support. See `[PATCH v2 0/3] drm: Add panic handling
  <https://lore.kernel.org/dri-devel/20190311174218.51899-1-noralf@tronnes.org/>`_.

* Encoding the actual oops and preceding dmesg in a QR might help with the
  dread "important stuff scrolled away" problem. See `[RFC][PATCH] Oops messages
  transfer using QR codes
  <https://lore.kernel.org/lkml/1446217392-11981-1-git-send-email-alexandru.murtaza@intel.com/>`_
  for some example code that could be reused.

Contact: Daniel Vetter

Level: Advanced

Clean up the debugfs support
----------------------------

There's a bunch of issues with it:

- The drm_info_list ->show() function doesn't even bother to cast to the drm
  structure for you. This is lazy.

- We probably want to have some support for debugfs files on crtc/connectors and
  maybe other kms objects directly in core. There's even drm_print support in
  the funcs for these objects to dump kms state, so it's all there. And then the
  ->show() functions should obviously give you a pointer to the right object.

- The drm_info_list stuff is centered on drm_minor instead of drm_device. For
  anything we want to print drm_device (or maybe drm_file) is the right thing.

- The drm_driver->debugfs_init hooks we have is just an artifact of the old
  midlayered load sequence. DRM debugfs should work more like sysfs, where you
  can create properties/files for an object anytime you want, and the core
  takes care of publishing/unpuplishing all the files at register/unregister
  time. Drivers shouldn't need to worry about these technicalities, and fixing
  this (together with the drm_minor->drm_device move) would allow us to remove
  debugfs_init.

Previous RFC that hasn't landed yet: https://lore.kernel.org/dri-devel/20200513114130.28641-2-wambui.karugax@gmail.com/

Contact: Daniel Vetter

Level: Intermediate

Object lifetime fixes
---------------------

There's two related issues here

- Cleanup up the various ->destroy callbacks, which often are all the same
  simple code.

- Lots of drivers erroneously allocate DRM modeset objects using devm_kzalloc,
  which results in use-after free issues on driver unload. This can be serious
  trouble even for drivers for hardware integrated on the SoC due to
  EPROBE_DEFERRED backoff.

Both these problems can be solved by switching over to drmm_kzalloc(), and the
various convenience wrappers provided, e.g. drmm_crtc_alloc_with_planes(),
drmm_universal_plane_alloc(), ... and so on.

Contact: Daniel Vetter

Level: Intermediate

Remove automatic page mapping from dma-buf importing
----------------------------------------------------

When importing dma-bufs, the dma-buf and PRIME frameworks automatically map
imported pages into the importer's DMA area. drm_gem_prime_fd_to_handle() and
drm_gem_prime_handle_to_fd() require that importers call dma_buf_attach()
even if they never do actual device DMA, but only CPU access through
dma_buf_vmap(). This is a problem for USB devices, which do not support DMA
operations.

To fix the issue, automatic page mappings should be removed from the
buffer-sharing code. Fixing this is a bit more involved, since the import/export
cache is also tied to &drm_gem_object.import_attach. Meanwhile we paper over
this problem for USB devices by fishing out the USB host controller device, as
long as that supports DMA. Otherwise importing can still needlessly fail.

Contact: Thomas Zimmermann <tzimmermann@suse.de>, Daniel Vetter

Level: Advanced

Better Testing
==============

Add unit tests using the Kernel Unit Testing (KUnit) framework
--------------------------------------------------------------

The `KUnit <https://www.kernel.org/doc/html/latest/dev-tools/kunit/index.html>`_
provides a common framework for unit tests within the Linux kernel. Having a
test suite would allow to identify regressions earlier.

A good candidate for the first unit tests are the format-conversion helpers in
``drm_format_helper.c``.

Contact: Javier Martinez Canillas <javierm@redhat.com>

Level: Intermediate

Enable trinity for DRM
----------------------

And fix up the fallout. Should be really interesting ...

Level: Advanced

Make KMS tests in i-g-t generic
-------------------------------

The i915 driver team maintains an extensive testsuite for the i915 DRM driver,
including tons of testcases for corner-cases in the modesetting API. It would
be awesome if those tests (at least the ones not relying on Intel-specific GEM
features) could be made to run on any KMS driver.

Basic work to run i-g-t tests on non-i915 is done, what's now missing is mass-
converting things over. For modeset tests we also first need a bit of
infrastructure to use dumb buffers for untiled buffers, to be able to run all
the non-i915 specific modeset tests.

Level: Advanced

Extend virtual test driver (VKMS)
---------------------------------

See the documentation of :ref:`VKMS <vkms>` for more details. This is an ideal
internship task, since it only requires a virtual machine and can be sized to
fit the available time.

Level: See details

Backlight Refactoring
---------------------

Backlight drivers have a triple enable/disable state, which is a bit overkill.
Plan to fix this:

1. Roll out backlight_enable() and backlight_disable() helpers everywhere. This
   has started already.
2. In all, only look at one of the three status bits set by the above helpers.
3. Remove the other two status bits.

Contact: Daniel Vetter

Level: Intermediate

Driver Specific
===============

AMD DC Display Driver
---------------------

AMD DC is the display driver for AMD devices starting with Vega. There has been
a bunch of progress cleaning it up but there's still plenty of work to be done.

See drivers/gpu/drm/amd/display/TODO for tasks.

Contact: Harry Wentland, Alex Deucher

Bootsplash
==========

There is support in place now for writing internal DRM clients making it
possible to pick up the bootsplash work that was rejected because it was written
for fbdev.

- [v6,8/8] drm/client: Hack: Add bootsplash example
  https://patchwork.freedesktop.org/patch/306579/

- [RFC PATCH v2 00/13] Kernel based bootsplash
  https://lore.kernel.org/r/20171213194755.3409-1-mstaudt@suse.de

Contact: Sam Ravnborg

Level: Advanced

Brightness handling on devices with multiple internal panels
============================================================

On x86/ACPI devices there can be multiple backlight firmware interfaces:
(ACPI) video, vendor specific and others. As well as direct/native (PWM)
register programming by the KMS driver.

To deal with this backlight drivers used on x86/ACPI call
acpi_video_get_backlight_type() which has heuristics (+quirks) to select
which backlight interface to use; and backlight drivers which do not match
the returned type will not register themselves, so that only one backlight
device gets registered (in a single GPU setup, see below).

At the moment this more or less assumes that there will only
be 1 (internal) panel on a system.

On systems with 2 panels this may be a problem, depending on
what interface acpi_video_get_backlight_type() selects:

1. native: in this case the KMS driver is expected to know which backlight
   device belongs to which output so everything should just work.
2. video: this does support controlling multiple backlights, but some work
   will need to be done to get the output <-> backlight device mapping

The above assumes both panels will require the same backlight interface type.
Things will break on systems with multiple panels where the 2 panels need
a different type of control. E.g. one panel needs ACPI video backlight control,
where as the other is using native backlight control. Currently in this case
only one of the 2 required backlight devices will get registered, based on
the acpi_video_get_backlight_type() return value.

If this (theoretical) case ever shows up, then supporting this will need some
work. A possible solution here would be to pass a device and connector-name
to acpi_video_get_backlight_type() so that it can deal with this.

Note in a way we already have a case where userspace sees 2 panels,
in dual GPU laptop setups with a mux. On those systems we may see
either 2 native backlight devices; or 2 native backlight devices.

Userspace already has code to deal with this by detecting if the related
panel is active (iow which way the mux between the GPU and the panels
points) and then uses that backlight device. Userspace here very much
assumes a single panel though. It picks only 1 of the 2 backlight devices
and then only uses that one.

Note that all userspace code (that I know off) is currently hardcoded
to assume a single panel.

Before the recent changes to not register multiple (e.g. video + native)
/sys/class/backlight devices for a single panel (on a single GPU laptop),
userspace would see multiple backlight devices all controlling the same
backlight.

To deal with this userspace had to always picks one preferred device under
/sys/class/backlight and will ignore the others. So to support brightness
control on multiple panels userspace will need to be updated too.

There are plans to allow brightness control through the KMS API by adding
a "display brightness" property to drm_connector objects for panels. This
solves a number of issues with the /sys/class/backlight API, including not
being able to map a sysfs backlight device to a specific connector. Any
userspace changes to add support for brightness control on devices with
multiple panels really should build on top of this new KMS property.

Contact: Hans de Goede

Level: Advanced

Outside DRM
===========

Convert fbdev drivers to DRM
----------------------------

There are plenty of fbdev drivers for older hardware. Some hardware has
become obsolete, but some still provides good(-enough) framebuffers. The
drivers that are still useful should be converted to DRM and afterwards
removed from fbdev.

Very simple fbdev drivers can best be converted by starting with a new
DRM driver. Simple KMS helpers and SHMEM should be able to handle any
existing hardware. The new driver's call-back functions are filled from
existing fbdev code.

More complex fbdev drivers can be refactored step-by-step into a DRM
driver with the help of the DRM fbconv helpers. [1] These helpers provide
the transition layer between the DRM core infrastructure and the fbdev
driver interface. Create a new DRM driver on top of the fbconv helpers,
copy over the fbdev driver, and hook it up to the DRM code. Examples for
several fbdev drivers are available at [1] and a tutorial of this process
available at [2]. The result is a primitive DRM driver that can run X11
and Weston.

 - [1] https://gitlab.freedesktop.org/tzimmermann/linux/tree/fbconv
 - [2] https://gitlab.freedesktop.org/tzimmermann/linux/blob/fbconv/drivers/gpu/drm/drm_fbconv_helper.c

Contact: Thomas Zimmermann <tzimmermann@suse.de>

Level: Advanced

repo_name: angery/linux


code:
=====================================
 drm/v3d Broadcom V3D Graphics Driver
=====================================

.. kernel-doc:: drivers/gpu/drm/v3d/v3d_drv.c
   :doc: Broadcom V3D Graphics Driver

GPU buffer object (BO) management
---------------------------------

.. kernel-doc:: drivers/gpu/drm/v3d/v3d_bo.c
   :doc: V3D GEM BO management support

Address space management
===========================================
.. kernel-doc:: drivers/gpu/drm/v3d/v3d_mmu.c
   :doc: Broadcom V3D MMU

GPU Scheduling
===========================================
.. kernel-doc:: drivers/gpu/drm/v3d/v3d_sched.c
   :doc: Broadcom V3D scheduling

Interrupts
--------------

.. kernel-doc:: drivers/gpu/drm/v3d/v3d_irq.c
   :doc: Interrupt management for the V3D engine


code:
=====================================
 drm/vc4 Broadcom VC4 Graphics Driver
=====================================

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_drv.c
   :doc: Broadcom VC4 Graphics Driver

Display Hardware Handling
=========================

This section covers everything related to the display hardware including
the mode setting infrastructure, plane, sprite and cursor handling and
display, output probing and related topics.

Pixel Valve (DRM CRTC)
----------------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_crtc.c
   :doc: VC4 CRTC module

HVS
---

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_hvs.c
   :doc: VC4 HVS module.

HVS planes
----------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_plane.c
   :doc: VC4 plane module

HDMI encoder
------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_hdmi.c
   :doc: VC4 Falcon HDMI module

DSI encoder
-----------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_dsi.c
   :doc: VC4 DSI0/DSI1 module

DPI encoder
-----------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_dpi.c
   :doc: VC4 DPI module

VEC (Composite TV out) encoder
------------------------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_vec.c
   :doc: VC4 SDTV module

Memory Management and 3D Command Submission
===========================================

This section covers the GEM implementation in the vc4 driver.

GPU buffer object (BO) management
---------------------------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_bo.c
   :doc: VC4 GEM BO management support

V3D binner command list (BCL) validation
----------------------------------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_validate.c
   :doc: Command list validator for VC4.

V3D render command list (RCL) generation
----------------------------------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_render_cl.c
   :doc: Render command list generation

Shader validator for VC4
---------------------------
.. kernel-doc:: drivers/gpu/drm/vc4/vc4_validate_shaders.c
   :doc: Shader validator for VC4.

V3D Interrupts
--------------

.. kernel-doc:: drivers/gpu/drm/vc4/vc4_irq.c
   :doc: Interrupt management for the V3D engine


code:
.. _vga_switcheroo:

==============
VGA Switcheroo
==============

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :doc: Overview

Modes of Use
============

Manual switching and manual power control
-----------------------------------------

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :doc: Manual switching and manual power control

Driver power control
--------------------

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :doc: Driver power control

API
===

Public functions
----------------

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :export:

Public structures
-----------------

.. kernel-doc:: include/linux/vga_switcheroo.h
   :functions: vga_switcheroo_handler

.. kernel-doc:: include/linux/vga_switcheroo.h
   :functions: vga_switcheroo_client_ops

Public constants
----------------

.. kernel-doc:: include/linux/vga_switcheroo.h
   :functions: vga_switcheroo_handler_flags_t

.. kernel-doc:: include/linux/vga_switcheroo.h
   :functions: vga_switcheroo_client_id

.. kernel-doc:: include/linux/vga_switcheroo.h
   :functions: vga_switcheroo_state

Private structures
------------------

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :functions: vgasr_priv

.. kernel-doc:: drivers/gpu/vga/vga_switcheroo.c
   :functions: vga_switcheroo_client

Handlers
========

apple-gmux Handler
------------------

.. kernel-doc:: drivers/platform/x86/apple-gmux.c
   :doc: Overview

.. kernel-doc:: drivers/platform/x86/apple-gmux.c
   :doc: Interrupt

Graphics mux
~~~~~~~~~~~~

.. kernel-doc:: drivers/platform/x86/apple-gmux.c
   :doc: Graphics mux

Power control
~~~~~~~~~~~~~

.. kernel-doc:: drivers/platform/x86/apple-gmux.c
   :doc: Power control

Backlight control
~~~~~~~~~~~~~~~~~

.. kernel-doc:: drivers/platform/x86/apple-gmux.c
   :doc: Backlight control

Public functions
~~~~~~~~~~~~~~~~

.. kernel-doc:: include/linux/apple-gmux.h
   :internal:


code:
===========
VGA Arbiter
===========

Graphic devices are accessed through ranges in I/O or memory space. While most
modern devices allow relocation of such ranges, some "Legacy" VGA devices
implemented on PCI will typically have the same "hard-decoded" addresses as
they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
Section 7, Legacy Devices.

The Resource Access Control (RAC) module inside the X server [0] existed for
the legacy VGA arbitration task (besides other bus management tasks) when more
than one legacy device co-exists on the same machine. But the problem happens
when these devices are trying to be accessed by different userspace clients
(e.g. two server in parallel). Their address assignments conflict. Moreover,
ideally, being a userspace application, it is not the role of the X server to
control bus resources. Therefore an arbitration scheme outside of the X server
is needed to control the sharing of these resources. This document introduces
the operation of the VGA arbiter implemented for the Linux kernel.

vgaarb kernel/userspace ABI
---------------------------

The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
scans all PCI devices and adds the VGA ones inside the arbitration. The
arbiter then enables/disables the decoding on different devices of the VGA
legacy instructions. Devices which do not want/need to use the arbiter may
explicitly tell it by calling vga_set_legacy_decoding().

The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
which has the following semantics:

open
        Opens a user instance of the arbiter. By default, it's attached to the
        default VGA device of the system.

close
        Close a user instance. Release locks made by the user

read
        Return a string indicating the status of the target like:

        "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"

        An IO state string is of the form {io,mem,io+mem,none}, mc and
        ic are respectively mem and io lock counts (for debugging/
        diagnostic only). "decodes" indicate what the card currently
        decodes, "owns" indicates what is currently enabled on it, and
        "locks" indicates what is locked by this card. If the card is
        unplugged, we get "invalid" then for card_ID and an -ENODEV
        error is returned for any command until a new card is targeted.

write
        Write a command to the arbiter. List of commands:

        target <card_ID>
                switch target to card <card_ID> (see below)
        lock <io_state>
                acquires locks on target ("none" is an invalid io_state)
        trylock <io_state>
                non-blocking acquire locks on target (returns EBUSY if
                unsuccessful)
        unlock <io_state>
                release locks on target
        unlock all
                release all locks on target held by this user (not implemented
                yet)
        decodes <io_state>
                set the legacy decoding attributes for the card

        poll
                event if something changes on any card (not just the target)

        card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
        to go back to the system default card (TODO: not implemented yet). Currently,
        only PCI is supported as a prefix, but the userland API may support other bus
        types in the future, even if the current kernel implementation doesn't.

Note about locks:

The driver keeps track of which user has which locks on which card. It
supports stacking, like the kernel one. This complexifies the implementation
a bit, but makes the arbiter more tolerant to user space problems and able
to properly cleanup in all cases when a process dies.
Currently, a max of 16 cards can have locks simultaneously issued from
user space for a given user (file descriptor instance) of the arbiter.

In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
notify them being added/removed in the system and automatically added/removed
in the arbiter.

There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
drivers want to use it.

In-kernel interface
-------------------

.. kernel-doc:: include/linux/vgaarb.h
   :internal:

.. kernel-doc:: drivers/pci/vgaarb.c
   :export:

libpciaccess
------------

To use the vga arbiter char device it was implemented an API inside the
libpciaccess library. One field was added to struct pci_device (each device
on the system)::

    /* the type of resource decoded by the device */
    int vgaarb_rsrc;

Besides it, in pci_system were added::

    int vgaarb_fd;
    int vga_count;
    struct pci_device *vga_target;
    struct pci_device *vga_default_dev;

The vga_count is used to track how many cards are being arbitrated, so for
instance, if there is only one card, then it can completely escape arbitration.

These functions below acquire VGA resources for the given card and mark those
resources as locked. If the resources requested are "normal" (and not legacy)
resources, the arbiter will first check whether the card is doing legacy
decoding for that type of resource. If yes, the lock is "converted" into a
legacy resource lock. The arbiter will first look for all VGA cards that
might conflict and disable their IOs and/or Memory access, including VGA
forwarding on P2P bridges if necessary, so that the requested resources can
be used. Then, the card is marked as locking these resources and the IO and/or
Memory access is enabled on the card (including VGA forwarding on parent
P2P bridges if any). In the case of vga_arb_lock(), the function will block
if some conflicting card is already locking one of the required resources (or
any resource on a different bus segment, since P2P bridges don't differentiate
VGA memory and IO afaik). If the card already owns the resources, the function
succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
calls are supported (a per-resource counter is maintained).

Set the target device of this client. ::

    int  pci_device_vgaarb_set_target   (struct pci_device *dev);

For instance, in x86 if two devices on the same bus want to lock different
resources, both will succeed (lock). If devices are in different buses and
trying to lock different resources, only the first who tried succeeds. ::

    int  pci_device_vgaarb_lock         (void);
    int  pci_device_vgaarb_trylock      (void);

Unlock resources of device. ::

    int  pci_device_vgaarb_unlock       (void);

Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
Memory, both, or none. All cards default to both, the card driver (fbdev for
example) should tell the arbiter if it has disabled legacy decoding, so the
card can be left out of the arbitration process (and can be safe to take
interrupts at any time. ::

    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);

Connects to the arbiter device, allocates the struct ::

    int  pci_device_vgaarb_init         (void);

Close the connection ::

    void pci_device_vgaarb_fini         (void);

xf86VGAArbiter (X server implementation)
----------------------------------------

X server basically wraps all the functions that touch VGA registers somehow.

References
----------

Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
enhancing the kernel code to adapt as a kernel module and also did the
implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.

0) https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
1) https://lists.freedesktop.org/archives/xorg/2005-March/006663.html
2) https://lists.freedesktop.org/archives/xorg/2005-March/006745.html
3) https://lists.freedesktop.org/archives/xorg/2007-October/029507.html


code:
.. _vkms:

==========================================
 drm/vkms Virtual Kernel Modesetting
==========================================

.. kernel-doc:: drivers/gpu/drm/vkms/vkms_drv.c
   :doc: vkms (Virtual Kernel Modesetting)

Setup
=====

The VKMS driver can be setup with the following steps:

To check if VKMS is loaded, run::

  lsmod | grep vkms

This should list the VKMS driver. If no output is obtained, then
you need to enable and/or load the VKMS driver.
Ensure that the VKMS driver has been set as a loadable module in your
kernel config file. Do::

  make nconfig

  Go to `Device Drivers> Graphics support`

  Enable `Virtual KMS (EXPERIMENTAL)`

Compile and build the kernel for the changes to get reflected.
Now, to load the driver, use::

  sudo modprobe vkms

On running the lsmod command now, the VKMS driver will appear listed.
You can also observe the driver being loaded in the dmesg logs.

The VKMS driver has optional features to simulate different kinds of hardware,
which are exposed as module options. You can use the `modinfo` command
to see the module options for vkms::

  modinfo vkms

Module options are helpful when testing, and enabling modules
can be done while loading vkms. For example, to load vkms with cursor enabled,
use::

  sudo modprobe vkms enable_cursor=1

To disable the driver, use ::

  sudo modprobe -r vkms

Testing With IGT
================

The IGT GPU Tools is a test suite used specifically for debugging and
development of the DRM drivers.
The IGT Tools can be installed from
`here <https://gitlab.freedesktop.org/drm/igt-gpu-tools>`_ .

The tests need to be run without a compositor, so you need to switch to text
only mode. You can do this by::

  sudo systemctl isolate multi-user.target

To return to graphical mode, do::

  sudo systemctl isolate graphical.target

Once you are in text only mode, you can run tests using the --device switch
or IGT_DEVICE variable to specify the device filter for the driver we want
to test. IGT_DEVICE can also be used with the run-test.sh script to run the
tests for a specific driver::

  sudo ./build/tests/<name of test> --device "sys:/sys/devices/platform/vkms"
  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/<name of test>
  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./scripts/run-tests.sh -t <name of test>

For example, to test the functionality of the writeback library,
we can run the kms_writeback test::

  sudo ./build/tests/kms_writeback --device "sys:/sys/devices/platform/vkms"
  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_writeback
  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./scripts/run-tests.sh -t kms_writeback

You can also run subtests if you do not want to run the entire test::

  sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device "sys:/sys/devices/platform/vkms"
  sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip --run-subtest basic-plain-flip

TODO
====

If you want to do any of the items listed below, please share your interest
with VKMS maintainers.

IGT better support
------------------

Debugging:

- kms_plane: some test cases are failing due to timeout on capturing CRC;

Virtual hardware (vblank-less) mode:

- VKMS already has support for vblanks simulated via hrtimers, which can be
  tested with kms_flip test; in some way, we can say that VKMS already mimics
  the real hardware vblank. However, we also have virtual hardware that does
  not support vblank interrupt and completes page_flip events right away; in
  this case, compositor developers may end up creating a busy loop on virtual
  hardware. It would be useful to support Virtual Hardware behavior in VKMS
  because this can help compositor developers to test their features in
  multiple scenarios.

Add Plane Features
------------------

There's lots of plane features we could add support for:

- ARGB format on primary plane: blend the primary plane into background with
  translucent alpha.

- Add background color KMS property[Good to get started].

- Full alpha blending on all planes.

- Rotation, scaling.

- Additional buffer formats, especially YUV formats for video like NV12.
  Low/high bpp RGB formats would also be interesting.

- Async updates (currently only possible on cursor plane using the legacy
  cursor api).

For all of these, we also want to review the igt test coverage and make sure
all relevant igt testcases work on vkms. They are good options for internship
project.

Runtime Configuration
---------------------

We want to be able to reconfigure vkms instance without having to reload the
module. Use/Test-cases:

- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling
  of compositors).

- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of
  them first).

- Change output configuration: Plug/unplug screens, change EDID, allow changing
  the refresh rate.

The currently proposed solution is to expose vkms configuration through
configfs. All existing module options should be supported through configfs
too.

Writeback support
-----------------

- The writeback and CRC capture operations share the use of composer_enabled
  boolean to ensure vblanks. Probably, when these operations work together,
  composer_enabled needs to refcounting the composer state to proper work.
  [Good to get started]

- Add support for cloned writeback outputs and related test cases using a
  cloned output in the IGT kms_writeback.

- As a v4l device. This is useful for debugging compositors on special vkms
  configurations, so that developers see what's really going on.

Output Features
---------------

- Variable refresh rate/freesync support. This probably needs prime buffer
  sharing support, so that we can use vgem fences to simulate rendering in
  testing. Also needs support to specify the EDID.

- Add support for link status, so that compositors can validate their runtime
  fallbacks when e.g. a Display Port link goes bad.

CRC API Improvements
--------------------

- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()``

Atomic Check using eBPF
-----------------------

Atomic drivers have lots of restrictions which are not exposed to userspace in
any explicit form through e.g. possible property values. Userspace can only
inquiry about these limits through the atomic IOCTL, possibly using the
TEST_ONLY flag. Trying to add configurable code for all these limits, to allow
compositors to be tested against them, would be rather futile exercise. Instead
we could add support for eBPF to validate any kind of atomic state, and
implement a library of different restrictions.

This needs a bunch of features (plane compositing, multiple outputs, ...)
enabled already to make sense.


code:
====================================================
 drm/xen-front Xen para-virtualized frontend driver
====================================================

This frontend driver implements Xen para-virtualized display
according to the display protocol described at
include/xen/interface/io/displif.h

Driver modes of operation in terms of display buffers used
==========================================================

.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h
   :doc: Driver modes of operation in terms of display buffers used

Buffers allocated by the frontend driver
----------------------------------------

.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h
   :doc: Buffers allocated by the frontend driver

Buffers allocated by the backend
--------------------------------

.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h
   :doc: Buffers allocated by the backend

Driver limitations
==================

.. kernel-doc:: drivers/gpu/drm/xen/xen_drm_front.h
   :doc: Driver limitations


code:
.. SPDX-License-Identifier: GPL-2.0

AMD Sensor Fusion Hub
=====================
AMD Sensor Fusion Hub (SFH) is part of an SOC starting from Ryzen-based platforms.
The solution is working well on several OEM products. AMD SFH uses HID over PCIe bus.
In terms of architecture it resembles ISH, however the major difference is all
the HID reports are generated as part of the kernel driver.

Block Diagram
-------------

::

	---------------------------------
	|  HID User Space Applications  |
	- -------------------------------

    ---------------------------------------------
	 ---------------------------------
	|		HID Core          |
	 ---------------------------------

	 ---------------------------------
	|     AMD HID Transport           |
	 ---------------------------------

	 --------------------------------
	|             AMD HID Client     |
	|	with HID Report Generator|
	 --------------------------------

	 --------------------------------
	|     AMD MP2 PCIe Driver        |
	 --------------------------------
    OS
    ---------------------------------------------
    Hardware + Firmware
         --------------------------------
         |     SFH MP2 Processor         |
         --------------------------------

AMD HID Transport Layer
-----------------------
AMD SFH transport is also implemented as a bus. Each client application executing in the AMD MP2 is
registered as a device on this bus. Here, MP2 is an ARM core connected to x86 for processing
sensor data. The layer, which binds each device (AMD SFH HID driver) identifies the device type and
registers with the HID core. Transport layer attaches a constant "struct hid_ll_driver" object with
each device. Once a device is registered with HID core, the callbacks provided via this struct are
used by HID core to communicate with the device. AMD HID Transport layer implements the synchronous calls.

AMD HID Client Layer
--------------------
This layer is responsible to implement HID requests and descriptors. As firmware is OS agnostic, HID
client layer fills the HID request structure and descriptors. HID client layer is complex as it is
interface between MP2 PCIe layer and HID. HID client layer initializes the MP2 PCIe layer and holds
the instance of MP2 layer. It identifies the number of sensors connected using MP2-PCIe layer. Based
on that allocates the DRAM address for each and every sensor and passes it to MP2-PCIe driver. On
enumeration of each sensor, client layer fills the HID Descriptor structure and HID input report
structure. HID Feature report structure is optional. The report descriptor structure varies from
sensor to sensor.

AMD MP2 PCIe layer
------------------
MP2 PCIe Layer is responsible for making all transactions with the firmware over PCIe.
The connection establishment between firmware and PCIe happens here.

The communication between X86 and MP2 is split into three parts.
1. Command transfer via the C2P mailbox registers.
2. Data transfer via DRAM.
3. Supported sensor info via P2C registers.

Commands are sent to MP2 using C2P Mailbox registers. Writing into C2P Message registers generates
interrupt to MP2. The client layer allocates the physical memory and the same is sent to MP2 via
the PCI layer. MP2 firmware writes the command output to the access DRAM memory which the client
layer has allocated. Firmware always writes minimum of 32 bytes into DRAM. So as a protocol driver
shall allocate minimum of 32 bytes DRAM space.

Enumeration and Probing flow
----------------------------
::

       HID             AMD            AMD                       AMD -PCIe             MP2
       Core         Transport      Client layer                   layer                FW
        |		|	       |                           |                 |
        |		|              |                 on Boot Driver Loaded       |
        |		|	       |                           |                 |
        |		|	       |                        MP2-PCIe Int         |
        |		|              |			   |                 |
        |		|	       |---Get Number of sensors-> |                 |
        |		|              |                       Read P2C              |
        |		|	       |			Register             |
        |		|              |                           |                 |
        |               |              | Loop(for No of Sensors)   |                 |
        |		|	       |----------------------|    |                 |
        |		|              | Create HID Descriptor|    |                 |
        |		|	       | Create Input  report |    |                 |
        |		|              |  Descriptor Map      |    |                 |
        |		|	       |  the MP2 FW Index to |    |                 |
        |		|              |   HID Index          |    |                 |
        |		|	       | Allocate the DRAM    |  Enable              |
        |		|	       |	address       |  Sensors             |
        |		|              |----------------------|    |                 |
        |		| HID transport|                           |    Enable       |
        |	        |<--Probe------|                           |---Sensor CMD--> |
        |		| Create the   |			   |                 |
        |		| HID device   |                           |                 |
        |               |    (MFD)     |                           |                 |
        |		| by Populating|			   |                 |
        |               |  the HID     |                           |                 |
        |               |  ll_driver   |                           |                 |
        | HID           |	       |			   |                 |
        |  add          |              |                           |                 |
        |Device         |              |                           |                 |
        |<------------- |	       |			   |                 |

Data Flow from Application to the AMD SFH Driver
------------------------------------------------

::

	        |	       |              |	  	 	          |		    |
                |	       |	      |			          |                 |
                |	       |	      |			          |                 |
                |              |              |                           |                 |
                |              |              |                           |                 |
                |HID_req       |              |                           |                 |
                |get_report    |              |                           |                 |
                |------------->|              |                           |                 |
	        |              | HID_get_input|                           |                 |
	        |              |  report      |                           |                 |
	        |              |------------->|------------------------|  |                 |
	        |              |              |  Read the DRAM data for|  |                 |
	        |              |              |  requested sensor and  |  |                 |
	        |              |              |  create the HID input  |  |                 |
	        |              |              |  report                |  |                 |
	        |              |              |------------------------|  |                 |
	        |              |Data received |                           |                 |
	        |              | in HID report|                           |                 |
    To	        |<-------------|<-------------|                           |                 |
    Applications|              |              |                           |                 |
        <-------|              |              |                           |                 |


code:
==========================
ALPS HID Touchpad Protocol
==========================

Introduction
------------
Currently ALPS HID driver supports U1 Touchpad device.

U1 device basic information.

==========	======
Vender ID	0x044E
Product ID	0x120B
Version ID	0x0121
==========	======

HID Descriptor
--------------

=======	====================	=====	=======================================
Byte	Field			Value	Notes
=======	====================	=====	=======================================
0	wHIDDescLength		001E	Length of HID Descriptor : 30 bytes
2	bcdVersion		0100	Compliant with Version 1.00
4	wReportDescLength	00B2	Report Descriptor is 178 Bytes (0x00B2)
6	wReportDescRegister	0002	Identifier to read Report Descriptor
8	wInputRegister		0003	Identifier to read Input Report
10	wMaxInputLength		0053	Input Report is 80 Bytes + 2
12	wOutputRegister		0000	Identifier to read Output Report
14	wMaxOutputLength	0000	No Output Reports
16	wCommandRegister	0005	Identifier for Command Register
18	wDataRegister		0006	Identifier for Data Register
20	wVendorID		044E	Vendor ID 0x044E
22	wProductID		120B	Product ID 0x120B
24	wVersionID		0121	Version 01.21
26	RESERVED		0000	RESERVED
=======	====================	=====	=======================================

Report ID
---------

==========	=================  =========================================
ReportID-1	(Input Reports)	   (HIDUsage-Mouse) for TP&SP
ReportID-2	(Input Reports)	   (HIDUsage-keyboard) for TP
ReportID-3	(Input Reports)	   (Vendor Usage: Max 10 finger data) for TP
ReportID-4	(Input Reports)	   (Vendor Usage: ON bit data) for GP
ReportID-5	(Feature Reports)  Feature Reports
ReportID-6	(Input Reports)	   (Vendor Usage: StickPointer data) for SP
ReportID-7	(Feature Reports)  Flash update (Bootloader)
==========	=================  =========================================

Data pattern
------------

=====	==========	=====	=================
Case1	ReportID_1	TP/SP	Relative/Relative
Case2	ReportID_3	TP	Absolute
	ReportID_6	SP	Absolute
=====	==========	=====	=================

Command Read/Write
------------------
To read/write to RAM, need to send a command to the device.

The command format is as below.

DataByte(SET_REPORT)

=====	======================
Byte1	Command Byte
Byte2	Address - Byte 0 (LSB)
Byte3	Address - Byte 1
Byte4	Address - Byte 2
Byte5	Address - Byte 3 (MSB)
Byte6	Value Byte
Byte7	Checksum
=====	======================

Command Byte is read=0xD1/write=0xD2.

Address is read/write RAM address.

Value Byte is writing data when you send the write commands.

When you read RAM, there is no meaning.

DataByte(GET_REPORT)

=====	======================
Byte1	Response Byte
Byte2	Address - Byte 0 (LSB)
Byte3	Address - Byte 1
Byte4	Address - Byte 2
Byte5	Address - Byte 3 (MSB)
Byte6	Value Byte
Byte7	Checksum
=====	======================

Read value is stored in Value Byte.

Packet Format
Touchpad data byte
------------------

======= ======= ======= ======= ======= ======= ======= ======= =====
-	b7	b6	b5	b4	b3	b2	b1	b0
======= ======= ======= ======= ======= ======= ======= ======= =====
1	0	0	SW6	SW5	SW4	SW3	SW2	SW1
2	0	0	0	Fcv	Fn3	Fn2	Fn1	Fn0
3	Xa0_7	Xa0_6	Xa0_5	Xa0_4	Xa0_3	Xa0_2	Xa0_1	Xa0_0
4	Xa0_15	Xa0_14	Xa0_13	Xa0_12	Xa0_11	Xa0_10	Xa0_9	Xa0_8
5	Ya0_7	Ya0_6	Ya0_5	Ya0_4	Ya0_3	Ya0_2	Ya0_1	Ya0_0
6	Ya0_15	Ya0_14	Ya0_13	Ya0_12	Ya0_11	Ya0_10	Ya0_9	Ya0_8
7	LFB0	Zs0_6	Zs0_5	Zs0_4	Zs0_3	Zs0_2	Zs0_1	Zs0_0

8	Xa1_7	Xa1_6	Xa1_5	Xa1_4	Xa1_3	Xa1_2	Xa1_1	Xa1_0
9	Xa1_15	Xa1_14	Xa1_13	Xa1_12	Xa1_11	Xa1_10	Xa1_9	Xa1_8
10	Ya1_7	Ya1_6	Ya1_5	Ya1_4	Ya1_3	Ya1_2	Ya1_1	Ya1_0
11	Ya1_15	Ya1_14	Ya1_13	Ya1_12	Ya1_11	Ya1_10	Ya1_9	Ya1_8
12	LFB1	Zs1_6	Zs1_5	Zs1_4	Zs1_3	Zs1_2	Zs1_1	Zs1_0

13	Xa2_7	Xa2_6	Xa2_5	Xa2_4	Xa2_3	Xa2_2	Xa2_1	Xa2_0
14	Xa2_15	Xa2_14	Xa2_13	Xa2_12	Xa2_11	Xa2_10	Xa2_9	Xa2_8
15	Ya2_7	Ya2_6	Ya2_5	Ya2_4	Ya2_3	Ya2_2	Ya2_1	Ya2_0
16	Ya2_15	Ya2_14	Ya2_13	Ya2_12	Ya2_11	Ya2_10	Ya2_9	Ya2_8
17	LFB2	Zs2_6	Zs2_5	Zs2_4	Zs2_3	Zs2_2	Zs2_1	Zs2_0

18	Xa3_7	Xa3_6	Xa3_5	Xa3_4	Xa3_3	Xa3_2	Xa3_1	Xa3_0
19	Xa3_15	Xa3_14	Xa3_13	Xa3_12	Xa3_11	Xa3_10	Xa3_9	Xa3_8
20	Ya3_7	Ya3_6	Ya3_5	Ya3_4	Ya3_3	Ya3_2	Ya3_1	Ya3_0
21	Ya3_15	Ya3_14	Ya3_13	Ya3_12	Ya3_11	Ya3_10	Ya3_9	Ya3_8
22	LFB3	Zs3_6	Zs3_5	Zs3_4	Zs3_3	Zs3_2	Zs3_1	Zs3_0

23	Xa4_7	Xa4_6	Xa4_5	Xa4_4	Xa4_3	Xa4_2	Xa4_1	Xa4_0
24	Xa4_15	Xa4_14	Xa4_13	Xa4_12	Xa4_11	Xa4_10	Xa4_9	Xa4_8
25	Ya4_7	Ya4_6	Ya4_5	Ya4_4	Ya4_3	Ya4_2	Ya4_1	Ya4_0
26	Ya4_15	Ya4_14	Ya4_13	Ya4_12	Ya4_11	Ya4_10	Ya4_9	Ya4_8
27	LFB4	Zs4_6	Zs4_5	Zs4_4	Zs4_3	Zs4_2	Zs4_1	Zs4_0
======= ======= ======= ======= ======= ======= ======= ======= =====

SW1-SW6:
	SW ON/OFF status
Xan_15-0(16bit):
	X Absolute data of the "n"th finger
Yan_15-0(16bit):
	Y Absolute data of the "n"th finger
Zsn_6-0(7bit):
	Operation area of the "n"th finger

StickPointer data byte
----------------------

======= ======= ======= ======= ======= ======= ======= ======= =====
-	b7	b6	b5	b4	b3	b2	b1	b0
======= ======= ======= ======= ======= ======= ======= ======= =====
Byte1	1	1	1	0	1	SW3	SW2	SW1
Byte2	X7	X6	X5	X4	X3	X2	X1	X0
Byte3	X15	X14	X13	X12	X11	X10	X9	X8
Byte4	Y7	Y6	Y5	Y4	Y3	Y2	Y1	Y0
Byte5	Y15	Y14	Y13	Y12	Y11	Y10	Y9	Y8
Byte6	Z7	Z6	Z5	Z4	Z3	Z2	Z1	Z0
Byte7	T&P	Z14	Z13	Z12	Z11	Z10	Z9	Z8
======= ======= ======= ======= ======= ======= ======= ======= =====

SW1-SW3:
	SW ON/OFF status
Xn_15-0(16bit):
	X Absolute data
Yn_15-0(16bit):
	Y Absolute data
Zn_14-0(15bit):
	Z


code:
=====================
HID Sensors Framework
=====================
HID sensor framework provides necessary interfaces to implement sensor drivers,
which are connected to a sensor hub. The sensor hub is a HID device and it provides
a report descriptor conforming to HID 1.12 sensor usage tables.

Description from the HID 1.12 "HID Sensor Usages" specification:
"Standardization of HID usages for sensors would allow (but not require) sensor
hardware vendors to provide a consistent Plug And Play interface at the USB boundary,
thereby enabling some operating systems to incorporate common device drivers that
could be reused between vendors, alleviating any need for the vendors to provide
the drivers themselves."

This specification describes many usage IDs, which describe the type of sensor
and also the individual data fields. Each sensor can have variable number of
data fields. The length and order is specified in the report descriptor. For
example a part of report descriptor can look like::

     INPUT(1)[INPUT]
   ..
      Field(2)
        Physical(0020.0073)
        Usage(1)
          0020.045f
        Logical Minimum(-32767)
        Logical Maximum(32767)
        Report Size(8)
        Report Count(1)
        Report Offset(16)
        Flags(Variable Absolute)
  ..
  ..

The report is indicating "sensor page (0x20)" contains an accelerometer-3D (0x73).
This accelerometer-3D has some fields. Here for example field 2 is motion intensity
(0x045f) with a logical minimum value of -32767 and logical maximum of 32767. The
order of fields and length of each field is important as the input event raw
data will use this format.

Implementation
==============

This specification defines many different types of sensors with different sets of
data fields. It is difficult to have a common input event to user space applications,
for different sensors. For example an accelerometer can send X,Y and Z data, whereas
an ambient light sensor can send illumination data.
So the implementation has two parts:

- Core HID driver
- Individual sensor processing part (sensor drivers)

Core driver
-----------
The core driver (hid-sensor-hub) registers as a HID driver. It parses
report descriptors and identifies all the sensors present. It adds an MFD device
with name HID-SENSOR-xxxx (where xxxx is usage id from the specification).

For example:

HID-SENSOR-200073 is registered for an Accelerometer 3D driver.

So if any driver with this name is inserted, then the probe routine for that
function will be called. So an accelerometer processing driver can register
with this name and will be probed if there is an accelerometer-3D detected.

The core driver provides a set of APIs which can be used by the processing
drivers to register and get events for that usage id. Also it provides parsing
functions, which get and set each input/feature/output report.

Individual sensor processing part (sensor drivers)
--------------------------------------------------

The processing driver will use an interface provided by the core driver to parse
the report and get the indexes of the fields and also can get events. This driver
can use IIO interface to use the standard ABI defined for a type of sensor.

Core driver Interface
=====================

Callback structure::

  Each processing driver can use this structure to set some callbacks.
	int (*suspend)(..): Callback when HID suspend is received
	int (*resume)(..): Callback when HID resume is received
	int (*capture_sample)(..): Capture a sample for one of its data fields
	int (*send_event)(..): One complete event is received which can have
                               multiple data fields.

Registration functions::

  int sensor_hub_register_callback(struct hid_sensor_hub_device *hsdev,
			u32 usage_id,
			struct hid_sensor_hub_callbacks *usage_callback):

Registers callbacks for a usage id. The callback functions are not allowed
to sleep::

  int sensor_hub_remove_callback(struct hid_sensor_hub_device *hsdev,
			u32 usage_id):

Removes callbacks for a usage id.

Parsing function::

  int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
			u8 type,
			u32 usage_id, u32 attr_usage_id,
			struct hid_sensor_hub_attribute_info *info);

A processing driver can look for some field of interest and check if it exists
in a report descriptor. If it exists it will store necessary information
so that fields can be set or get individually.
These indexes avoid searching every time and getting field index to get or set.

Set Feature report::

  int sensor_hub_set_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
			u32 field_index, s32 value);

This interface is used to set a value for a field in feature report. For example
if there is a field report_interval, which is parsed by a call to
sensor_hub_input_get_attribute_info before, then it can directly set that
individual field::

  int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
			u32 field_index, s32 *value);

This interface is used to get a value for a field in input report. For example
if there is a field report_interval, which is parsed by a call to
sensor_hub_input_get_attribute_info before, then it can directly get that
individual field value::

  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
			u32 usage_id,
			u32 attr_usage_id, u32 report_id);

This is used to get a particular field value through input reports. For example
accelerometer wants to poll X axis value, then it can call this function with
the usage id of X axis. HID sensors can provide events, so this is not necessary
to poll for any field. If there is some new sample, the core driver will call
registered callback function to process the sample.

----------

HID Custom and generic Sensors
------------------------------

HID Sensor specification defines two special sensor usage types. Since they
don't represent a standard sensor, it is not possible to define using Linux IIO
type interfaces.
The purpose of these sensors is to extend the functionality or provide a
way to obfuscate the data being communicated by a sensor. Without knowing the
mapping between the data and its encapsulated form, it is difficult for
an application/driver to determine what data is being communicated by the sensor.
This allows some differentiating use cases, where vendor can provide applications.
Some common use cases are debug other sensors or to provide some events like
keyboard attached/detached or lid open/close.

To allow application to utilize these sensors, here they are exported using sysfs
attribute groups, attributes and misc device interface.

An example of this representation on sysfs::

  /sys/devices/pci0000:00/INT33C2:00/i2c-0/i2c-INT33D1:00/0018:8086:09FA.0001/HID-SENSOR-2000e1.6.auto$ tree -R
  .
  │   ├──  enable_sensor
  │   │   ├── feature-0-200316
  │   │   │   ├── feature-0-200316-maximum
  │   │   │   ├── feature-0-200316-minimum
  │   │   │   ├── feature-0-200316-name
  │   │   │   ├── feature-0-200316-size
  │   │   │   ├── feature-0-200316-unit-expo
  │   │   │   ├── feature-0-200316-units
  │   │   │   ├── feature-0-200316-value
  │   │   ├── feature-1-200201
  │   │   │   ├── feature-1-200201-maximum
  │   │   │   ├── feature-1-200201-minimum
  │   │   │   ├── feature-1-200201-name
  │   │   │   ├── feature-1-200201-size
  │   │   │   ├── feature-1-200201-unit-expo
  │   │   │   ├── feature-1-200201-units
  │   │   │   ├── feature-1-200201-value
  │   │   ├── input-0-200201
  │   │   │   ├── input-0-200201-maximum
  │   │   │   ├── input-0-200201-minimum
  │   │   │   ├── input-0-200201-name
  │   │   │   ├── input-0-200201-size
  │   │   │   ├── input-0-200201-unit-expo
  │   │   │   ├── input-0-200201-units
  │   │   │   ├── input-0-200201-value
  │   │   ├── input-1-200202
  │   │   │   ├── input-1-200202-maximum
  │   │   │   ├── input-1-200202-minimum
  │   │   │   ├── input-1-200202-name
  │   │   │   ├── input-1-200202-size
  │   │   │   ├── input-1-200202-unit-expo
  │   │   │   ├── input-1-200202-units
  │   │   │   ├── input-1-200202-value

Here there is a custom sensor with four fields: two feature and two inputs.
Each field is represented by a set of attributes. All fields except the "value"
are read only. The value field is a read-write field.

Example::

  /sys/bus/platform/devices/HID-SENSOR-2000e1.6.auto/feature-0-200316$ grep -r . *
  feature-0-200316-maximum:6
  feature-0-200316-minimum:0
  feature-0-200316-name:property-reporting-state
  feature-0-200316-size:1
  feature-0-200316-unit-expo:0
  feature-0-200316-units:25
  feature-0-200316-value:1

How to enable such sensor?
^^^^^^^^^^^^^^^^^^^^^^^^^^

By default sensor can be power gated. To enable sysfs attribute "enable" can be
used::

	$ echo 1 > enable_sensor

Once enabled and powered on, sensor can report value using HID reports.
These reports are pushed using misc device interface in a FIFO order::

	/dev$ tree | grep HID-SENSOR-2000e1.6.auto
	│   │   │   ├── 10:53 -> ../HID-SENSOR-2000e1.6.auto
	│   ├──  HID-SENSOR-2000e1.6.auto

Each report can be of variable length preceded by a header. This header
consists of a 32-bit usage id, 64-bit time stamp and 32-bit length field of raw
data.


code:
=========================
HID I/O Transport Drivers
=========================

The HID subsystem is independent of the underlying transport driver. Initially,
only USB was supported, but other specifications adopted the HID design and
provided new transport drivers. The kernel includes at least support for USB,
Bluetooth, I2C and user-space I/O drivers.

1) HID Bus
==========

The HID subsystem is designed as a bus. Any I/O subsystem may provide HID
devices and register them with the HID bus. HID core then loads generic device
drivers on top of it. The transport drivers are responsible for raw data
transport and device setup/management. HID core is responsible for
report-parsing, report interpretation and the user-space API. Device specifics
and quirks are handled by all layers depending on the quirk.

::

 +-----------+  +-----------+            +-----------+  +-----------+
 | Device #1 |  | Device #i |            | Device #j |  | Device #k |
 +-----------+  +-----------+            +-----------+  +-----------+
          \\      //                              \\      //
        +------------+                          +------------+
        | I/O Driver |                          | I/O Driver |
        +------------+                          +------------+
              ||                                      ||
     +------------------+                    +------------------+
     | Transport Driver |                    | Transport Driver |
     +------------------+                    +------------------+
                       \___                ___/
                           \              /
                          +----------------+
                          |    HID Core    |
                          +----------------+
                           /  |        |  \
                          /   |        |   \
             ____________/    |        |    \_________________
            /                 |        |                      \
           /                  |        |                       \
 +----------------+  +-----------+  +------------------+  +------------------+
 | Generic Driver |  | MT Driver |  | Custom Driver #1 |  | Custom Driver #2 |
 +----------------+  +-----------+  +------------------+  +------------------+

Example Drivers:

  - I/O: USB, I2C, Bluetooth-l2cap
  - Transport: USB-HID, I2C-HID, BT-HIDP

Everything below "HID Core" is simplified in this graph as it is only of
interest to HID device drivers. Transport drivers do not need to know the
specifics.

1.1) Device Setup
-----------------

I/O drivers normally provide hotplug detection or device enumeration APIs to the
transport drivers. Transport drivers use this to find any suitable HID device.
They allocate HID device objects and register them with HID core. Transport
drivers are not required to register themselves with HID core. HID core is never
aware of which transport drivers are available and is not interested in it. It
is only interested in devices.

Transport drivers attach a constant "struct hid_ll_driver" object with each
device. Once a device is registered with HID core, the callbacks provided via
this struct are used by HID core to communicate with the device.

Transport drivers are responsible for detecting device failures and unplugging.
HID core will operate a device as long as it is registered regardless of any
device failures. Once transport drivers detect unplug or failure events, they
must unregister the device from HID core and HID core will stop using the
provided callbacks.

1.2) Transport Driver Requirements
----------------------------------

The terms "asynchronous" and "synchronous" in this document describe the
transmission behavior regarding acknowledgements. An asynchronous channel must
not perform any synchronous operations like waiting for acknowledgements or
verifications. Generally, HID calls operating on asynchronous channels must be
running in atomic-context just fine.
On the other hand, synchronous channels can be implemented by the transport
driver in whatever way they like. They might just be the same as asynchronous
channels, but they can also provide acknowledgement reports, automatic
retransmission on failure, etc. in a blocking manner. If such functionality is
required on asynchronous channels, a transport-driver must implement that via
its own worker threads.

HID core requires transport drivers to follow a given design. A Transport
driver must provide two bi-directional I/O channels to each HID device. These
channels must not necessarily be bi-directional in the hardware itself. A
transport driver might just provide 4 uni-directional channels. Or it might
multiplex all four on a single physical channel. However, in this document we
will describe them as two bi-directional channels as they have several
properties in common.

 - Interrupt Channel (intr): The intr channel is used for asynchronous data
   reports. No management commands or data acknowledgements are sent on this
   channel. Any unrequested incoming or outgoing data report must be sent on
   this channel and is never acknowledged by the remote side. Devices usually
   send their input events on this channel. Outgoing events are normally
   not sent via intr, except if high throughput is required.
 - Control Channel (ctrl): The ctrl channel is used for synchronous requests and
   device management. Unrequested data input events must not be sent on this
   channel and are normally ignored. Instead, devices only send management
   events or answers to host requests on this channel.
   The control-channel is used for direct blocking queries to the device
   independent of any events on the intr-channel.
   Outgoing reports are usually sent on the ctrl channel via synchronous
   SET_REPORT requests.

Communication between devices and HID core is mostly done via HID reports. A
report can be of one of three types:

 - INPUT Report: Input reports provide data from device to host. This
   data may include button events, axis events, battery status or more. This
   data is generated by the device and sent to the host with or without
   requiring explicit requests. Devices can choose to send data continuously or
   only on change.
 - OUTPUT Report: Output reports change device states. They are sent from host
   to device and may include LED requests, rumble requests or more. Output
   reports are never sent from device to host, but a host can retrieve their
   current state.
   Hosts may choose to send output reports either continuously or only on
   change.
 - FEATURE Report: Feature reports are used for specific static device features
   and never reported spontaneously. A host can read and/or write them to access
   data like battery-state or device-settings.
   Feature reports are never sent without requests. A host must explicitly set
   or retrieve a feature report. This also means, feature reports are never sent
   on the intr channel as this channel is asynchronous.

INPUT and OUTPUT reports can be sent as pure data reports on the intr channel.
For INPUT reports this is the usual operational mode. But for OUTPUT reports,
this is rarely done as OUTPUT reports are normally quite scarce. But devices are
free to make excessive use of asynchronous OUTPUT reports (for instance, custom
HID audio speakers make great use of it).

Plain reports must not be sent on the ctrl channel, though. Instead, the ctrl
channel provides synchronous GET/SET_REPORT requests. Plain reports are only
allowed on the intr channel and are the only means of data there.

 - GET_REPORT: A GET_REPORT request has a report ID as payload and is sent
   from host to device. The device must answer with a data report for the
   requested report ID on the ctrl channel as a synchronous acknowledgement.
   Only one GET_REPORT request can be pending for each device. This restriction
   is enforced by HID core as several transport drivers don't allow multiple
   simultaneous GET_REPORT requests.
   Note that data reports which are sent as answer to a GET_REPORT request are
   not handled as generic device events. That is, if a device does not operate
   in continuous data reporting mode, an answer to GET_REPORT does not replace
   the raw data report on the intr channel on state change.
   GET_REPORT is only used by custom HID device drivers to query device state.
   Normally, HID core caches any device state so this request is not necessary
   on devices that follow the HID specs except during device initialization to
   retrieve the current state.
   GET_REPORT requests can be sent for any of the 3 report types and shall
   return the current report state of the device. However, OUTPUT reports as
   payload may be blocked by the underlying transport driver if the
   specification does not allow them.
 - SET_REPORT: A SET_REPORT request has a report ID plus data as payload. It is
   sent from host to device and a device must update its current report state
   according to the given data. Any of the 3 report types can be used. However,
   INPUT reports as payload might be blocked by the underlying transport driver
   if the specification does not allow them.
   A device must answer with a synchronous acknowledgement. However, HID core
   does not require transport drivers to forward this acknowledgement to HID
   core.
   Same as for GET_REPORT, only one SET_REPORT can be pending at a time. This
   restriction is enforced by HID core as some transport drivers do not support
   multiple synchronous SET_REPORT requests.

Other ctrl-channel requests are supported by USB-HID but are not available
(or deprecated) in most other transport level specifications:

 - GET/SET_IDLE: Only used by USB-HID and I2C-HID.
 - GET/SET_PROTOCOL: Not used by HID core.
 - RESET: Used by I2C-HID, not hooked up in HID core.
 - SET_POWER: Used by I2C-HID, not hooked up in HID core.

2) HID API
==========

2.1) Initialization
-------------------

Transport drivers normally use the following procedure to register a new device
with HID core::

	struct hid_device *hid;
	int ret;

	hid = hid_allocate_device();
	if (IS_ERR(hid)) {
		ret = PTR_ERR(hid);
		goto err_<...>;
	}

	strscpy(hid->name, <device-name-src>, sizeof(hid->name));
	strscpy(hid->phys, <device-phys-src>, sizeof(hid->phys));
	strscpy(hid->uniq, <device-uniq-src>, sizeof(hid->uniq));

	hid->ll_driver = &custom_ll_driver;
	hid->bus = <device-bus>;
	hid->vendor = <device-vendor>;
	hid->product = <device-product>;
	hid->version = <device-version>;
	hid->country = <device-country>;
	hid->dev.parent = <pointer-to-parent-device>;
	hid->driver_data = <transport-driver-data-field>;

	ret = hid_add_device(hid);
	if (ret)
		goto err_<...>;

Once hid_add_device() is entered, HID core might use the callbacks provided in
"custom_ll_driver". Note that fields like "country" can be ignored by underlying
transport-drivers if not supported.

To unregister a device, use::

	hid_destroy_device(hid);

Once hid_destroy_device() returns, HID core will no longer make use of any
driver callbacks.

2.2) hid_ll_driver operations
-----------------------------

The available HID callbacks are:

   ::

      int (*start) (struct hid_device *hdev)

   Called from HID device drivers once they want to use the device. Transport
   drivers can choose to setup their device in this callback. However, normally
   devices are already set up before transport drivers register them to HID core
   so this is mostly only used by USB-HID.

   ::

      void (*stop) (struct hid_device *hdev)

   Called from HID device drivers once they are done with a device. Transport
   drivers can free any buffers and deinitialize the device. But note that
   ->start() might be called again if another HID device driver is loaded on the
   device.

   Transport drivers are free to ignore it and deinitialize devices after they
   destroyed them via hid_destroy_device().

   ::

      int (*open) (struct hid_device *hdev)

   Called from HID device drivers once they are interested in data reports.
   Usually, while user-space didn't open any input API/etc., device drivers are
   not interested in device data and transport drivers can put devices asleep.
   However, once ->open() is called, transport drivers must be ready for I/O.
   ->open() calls are nested for each client that opens the HID device.

   ::

      void (*close) (struct hid_device *hdev)

   Called from HID device drivers after ->open() was called but they are no
   longer interested in device reports. (Usually if user-space closed any input
   devices of the driver).

   Transport drivers can put devices asleep and terminate any I/O of all
   ->open() calls have been followed by a ->close() call. However, ->start() may
   be called again if the device driver is interested in input reports again.

   ::

      int (*parse) (struct hid_device *hdev)

   Called once during device setup after ->start() has been called. Transport
   drivers must read the HID report-descriptor from the device and tell HID core
   about it via hid_parse_report().

   ::

      int (*power) (struct hid_device *hdev, int level)

   Called by HID core to give PM hints to transport drivers. Usually this is
   analogical to the ->open() and ->close() hints and redundant.

   ::

      void (*request) (struct hid_device *hdev, struct hid_report *report,
		       int reqtype)

   Send a HID request on the ctrl channel. "report" contains the report that
   should be sent and "reqtype" the request type. Request-type can be
   HID_REQ_SET_REPORT or HID_REQ_GET_REPORT.

   This callback is optional. If not provided, HID core will assemble a raw
   report following the HID specs and send it via the ->raw_request() callback.
   The transport driver is free to implement this asynchronously.

   ::

      int (*wait) (struct hid_device *hdev)

   Used by HID core before calling ->request() again. A transport driver can use
   it to wait for any pending requests to complete if only one request is
   allowed at a time.

   ::

      int (*raw_request) (struct hid_device *hdev, unsigned char reportnum,
                          __u8 *buf, size_t count, unsigned char rtype,
                          int reqtype)

   Same as ->request() but provides the report as raw buffer. This request shall
   be synchronous. A transport driver must not use ->wait() to complete such
   requests. This request is mandatory and hid core will reject the device if
   it is missing.

   ::

      int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len)

   Send raw output report via intr channel. Used by some HID device drivers
   which require high throughput for outgoing requests on the intr channel. This
   must not cause SET_REPORT calls! This must be implemented as asynchronous
   output report on the intr channel!

   ::

      int (*idle) (struct hid_device *hdev, int report, int idle, int reqtype)

   Perform SET/GET_IDLE request. Only used by USB-HID, do not implement!

2.3) Data Path
--------------

Transport drivers are responsible of reading data from I/O devices. They must
handle any I/O-related state-tracking themselves. HID core does not implement
protocol handshakes or other management commands which can be required by the
given HID transport specification.

Every raw data packet read from a device must be fed into HID core via
hid_input_report(). You must specify the channel-type (intr or ctrl) and report
type (input/output/feature). Under normal conditions, only input reports are
provided via this API.

Responses to GET_REPORT requests via ->request() must also be provided via this
API. Responses to ->raw_request() are synchronous and must be intercepted by the
transport driver and not passed to hid_input_report().
Acknowledgements to SET_REPORT requests are not of interest to HID core.

----------------------------------------------------

Written 2013, David Herrmann <dh.herrmann@gmail.com>