mirror of https://gitee.com/openkylin/linux.git
Merge tag 'topic/drm-misc-2016-08-23' of git://anongit.freedesktop.org/drm-intel into drm-next
A few bigger things: - start of splitting drm_crtc.c into more manageable and better documneted chunks - DRM_DEV_* logging (Sean) * tag 'topic/drm-misc-2016-08-23' of git://anongit.freedesktop.org/drm-intel: (46 commits) drm/fb-helper: Make docs for fb_set_suspend wrappers consistent drm/rockchip: Delete unnecessary assignment for the field "owner" drm/bridge: dw-hdmi: Delete unnecessary assignment for the field "owner" drm/rockchip: Don't continue trying to enable crtc on failure drm/fb-helper: Add drm_fb_helper_set_suspend_unlocked() drm/fb-helper: Fix the dummy remove_conflicting_framebuffers drm/udl: Ensure channel is selected before using the device. drm: Avoid calling dev_printk(.dev = NULL) drm: avoid exposing kernel stack in compat_drm_getstats reservation: fix small comment typo drm: Don't implement empty prepare_fb()/cleanup_fb() virtio-gpu: Use memdup_user() rather than duplicating its implementation GPU-DRM-Savage: Use memdup_user() rather than duplicating drm: Allow drivers to modify plane_state in prepare_fb/cleanup_fb drm/rockchip: Use DRM_DEV_ERROR in vop drm: Introduce DRM_DEV_* log messages drm/edid: CEA mode 64 1080p100 vsync pulse width incorrect Revert "drm/hisilicon: Don't set drm_device->platformdev" dma-buf: fix kernel-doc warning and typos drm: Fix kerneldoc in drm_plane_helper.c ...
This commit is contained in:
commit
d804819605
|
@ -2,38 +2,45 @@
|
|||
Mode Setting Helper Functions
|
||||
=============================
|
||||
|
||||
The plane, CRTC, encoder and connector functions provided by the drivers
|
||||
implement the DRM API. They're called by the DRM core and ioctl handlers
|
||||
to handle device state changes and configuration request. As
|
||||
implementing those functions often requires logic not specific to
|
||||
drivers, mid-layer helper functions are available to avoid duplicating
|
||||
boilerplate code.
|
||||
The DRM subsystem aims for a strong separation between core code and helper
|
||||
libraries. Core code takes care of general setup and teardown and decoding
|
||||
userspace requests to kernel internal objects. Everything else is handled by a
|
||||
large set of helper libraries, which can be combined freely to pick and choose
|
||||
for each driver what fits, and avoid shared code where special behaviour is
|
||||
needed.
|
||||
|
||||
The DRM core contains one mid-layer implementation. The mid-layer
|
||||
provides implementations of several plane, CRTC, encoder and connector
|
||||
functions (called from the top of the mid-layer) that pre-process
|
||||
requests and call lower-level functions provided by the driver (at the
|
||||
bottom of the mid-layer). For instance, the
|
||||
:c:func:`drm_crtc_helper_set_config()` function can be used to
|
||||
fill the :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>`
|
||||
set_config field. When called, it will split the set_config operation
|
||||
in smaller, simpler operations and call the driver to handle them.
|
||||
This distinction between core code and helpers is especially strong in the
|
||||
modesetting code, where there's a shared userspace ABI for all drivers. This is
|
||||
in contrast to the render side, where pretty much everything (with very few
|
||||
exceptions) can be considered optional helper code.
|
||||
|
||||
To use the mid-layer, drivers call
|
||||
:c:func:`drm_crtc_helper_add()`,
|
||||
:c:func:`drm_encoder_helper_add()` and
|
||||
:c:func:`drm_connector_helper_add()` functions to install their
|
||||
mid-layer bottom operations handlers, and fill the :c:type:`struct
|
||||
drm_crtc_funcs <drm_crtc_funcs>`, :c:type:`struct
|
||||
drm_encoder_funcs <drm_encoder_funcs>` and :c:type:`struct
|
||||
drm_connector_funcs <drm_connector_funcs>` structures with
|
||||
pointers to the mid-layer top API functions. Installing the mid-layer
|
||||
bottom operation handlers is best done right after registering the
|
||||
corresponding KMS object.
|
||||
There are a few areas these helpers can grouped into:
|
||||
|
||||
The mid-layer is not split between CRTC, encoder and connector
|
||||
operations. To use it, a driver must provide bottom functions for all of
|
||||
the three KMS entities.
|
||||
* Helpers to implement modesetting. The important ones here are the atomic
|
||||
helpers. Old drivers still often use the legacy CRTC helpers. They both share
|
||||
the same set of common helper vtables. For really simple drivers (anything
|
||||
that would have been a great fit in the deprecated fbdev subsystem) there's
|
||||
also the simple display pipe helpers.
|
||||
|
||||
* There's a big pile of helpers for handling outputs. First the generic bridge
|
||||
helpers for handling encoder and transcoder IP blocks. Second the panel helpers
|
||||
for handling panel-related information and logic. Plus then a big set of
|
||||
helpers for the various sink standards (DisplayPort, HDMI, MIPI DSI). Finally
|
||||
there's also generic helpers for handling output probing, and for dealing with
|
||||
EDIDs.
|
||||
|
||||
* The last group of helpers concerns itself with the frontend side of a display
|
||||
pipeline: Planes, handling rectangles for visibility checking and scissoring,
|
||||
flip queues and assorted bits.
|
||||
|
||||
Modeset Helper Reference for Common Vtables
|
||||
===========================================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:doc: overview
|
||||
|
||||
Atomic Modeset Helper Functions Reference
|
||||
=========================================
|
||||
|
@ -62,33 +69,27 @@ Atomic State Reset and Initialization
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
|
||||
:export:
|
||||
|
||||
Modeset Helper Reference for Common Vtables
|
||||
===========================================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
|
||||
:doc: overview
|
||||
|
||||
Legacy CRTC/Modeset Helper Functions Reference
|
||||
==============================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:doc: overview
|
||||
|
||||
Output Probing Helper Functions Reference
|
||||
=========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
:doc: output probing helper overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
Simple KMS Helper Reference
|
||||
===========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_simple_kms_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:doc: overview
|
||||
|
||||
fbdev Helper Functions Reference
|
||||
================================
|
||||
|
||||
|
@ -110,6 +111,36 @@ Framebuffer CMA Helper Functions Reference
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
||||
:export:
|
||||
|
||||
Bridges
|
||||
=======
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: overview
|
||||
|
||||
Default bridge callback sequence
|
||||
--------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: bridge callbacks
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:export:
|
||||
|
||||
Panel Helper Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_panel.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:doc: drm panel
|
||||
|
||||
Display Port Helper Functions Reference
|
||||
=======================================
|
||||
|
||||
|
@ -158,6 +189,15 @@ MIPI DSI Helper Functions Reference
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
|
||||
:export:
|
||||
|
||||
Output Probing Helper Functions Reference
|
||||
=========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
:doc: output probing helper overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
|
||||
:export:
|
||||
|
||||
EDID Helper Functions Reference
|
||||
===============================
|
||||
|
||||
|
@ -176,18 +216,6 @@ Rectangle Utilities Reference
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_rect.c
|
||||
:export:
|
||||
|
||||
Flip-work Helper Reference
|
||||
==========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:doc: flip utils
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
|
||||
:export:
|
||||
|
||||
HDMI Infoframes Helper Reference
|
||||
================================
|
||||
|
||||
|
@ -202,59 +230,40 @@ libraries and hence is also included here.
|
|||
.. kernel-doc:: drivers/video/hdmi.c
|
||||
:export:
|
||||
|
||||
Flip-work Helper Reference
|
||||
==========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:doc: flip utils
|
||||
|
||||
.. kernel-doc:: include/drm/drm_flip_work.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
|
||||
:export:
|
||||
|
||||
Plane Helper Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
|
||||
:export:
|
||||
|
||||
Tile group
|
||||
----------
|
||||
==========
|
||||
|
||||
# FIXME: This should probably be moved into a property documentation section
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:doc: Tile group
|
||||
|
||||
Bridges
|
||||
=======
|
||||
Auxiliary Modeset Helpers
|
||||
=========================
|
||||
|
||||
Overview
|
||||
--------
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
|
||||
:doc: aux kms helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: overview
|
||||
|
||||
Default bridge callback sequence
|
||||
--------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
:doc: bridge callbacks
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
|
||||
:export:
|
||||
|
||||
Panel Helper Reference
|
||||
======================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_panel.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_panel.c
|
||||
:doc: drm panel
|
||||
|
||||
Simple KMS Helper Reference
|
||||
===========================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_simple_kms_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
|
||||
:doc: overview
|
||||
|
|
|
@ -2,9 +2,6 @@
|
|||
Kernel Mode Setting (KMS)
|
||||
=========================
|
||||
|
||||
Mode Setting
|
||||
============
|
||||
|
||||
Drivers must initialize the mode setting core by calling
|
||||
:c:func:`drm_mode_config_init()` on the DRM device. The function
|
||||
initializes the :c:type:`struct drm_device <drm_device>`
|
||||
|
@ -18,60 +15,50 @@ be setup by initializing the following fields.
|
|||
- struct drm_mode_config_funcs \*funcs;
|
||||
Mode setting functions.
|
||||
|
||||
Display Modes Function Reference
|
||||
--------------------------------
|
||||
KMS Data Structures
|
||||
===================
|
||||
|
||||
.. kernel-doc:: include/drm/drm_modes.h
|
||||
.. kernel-doc:: include/drm/drm_crtc.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_modes.c
|
||||
KMS API Functions
|
||||
=================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:export:
|
||||
|
||||
Atomic Mode Setting Function Reference
|
||||
--------------------------------------
|
||||
======================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
|
||||
.. kernel-doc:: include/drm/drm_atomic.h
|
||||
:internal:
|
||||
|
||||
Frame Buffer Abstraction
|
||||
------------------------
|
||||
========================
|
||||
|
||||
Frame buffers are abstract memory objects that provide a source of
|
||||
pixels to scanout to a CRTC. Applications explicitly request the
|
||||
creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls
|
||||
and receive an opaque handle that can be passed to the KMS CRTC control,
|
||||
plane configuration and page flip functions.
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
|
||||
:doc: overview
|
||||
|
||||
Frame buffers rely on the underneath memory manager for low-level memory
|
||||
operations. When creating a frame buffer applications pass a memory
|
||||
handle (or a list of memory handles for multi-planar formats) through
|
||||
the ``drm_mode_fb_cmd2`` argument. For drivers using GEM as their
|
||||
userspace buffer management interface this would be a GEM handle.
|
||||
Drivers are however free to use their own backing storage object
|
||||
handles, e.g. vmwgfx directly exposes special TTM handles to userspace
|
||||
and so expects TTM handles in the create ioctl and not GEM handles.
|
||||
Frame Buffer Functions Reference
|
||||
--------------------------------
|
||||
|
||||
The lifetime of a drm framebuffer is controlled with a reference count,
|
||||
drivers can grab additional references with
|
||||
:c:func:`drm_framebuffer_reference()`and drop them again with
|
||||
:c:func:`drm_framebuffer_unreference()`. For driver-private
|
||||
framebuffers for which the last reference is never dropped (e.g. for the
|
||||
fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
|
||||
<drm_framebuffer>` is embedded into the fbdev helper struct)
|
||||
drivers can manually clean up a framebuffer at module unload time with
|
||||
:c:func:`drm_framebuffer_unregister_private()`.
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_framebuffer.h
|
||||
:internal:
|
||||
|
||||
DRM Format Handling
|
||||
-------------------
|
||||
===================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fourcc.c
|
||||
:export:
|
||||
|
||||
Dumb Buffer Objects
|
||||
-------------------
|
||||
===================
|
||||
|
||||
The KMS API doesn't standardize backing storage object creation and
|
||||
leaves it to driver-specific ioctls. Furthermore actually creating a
|
||||
|
@ -114,14 +101,29 @@ Note that dumb objects may not be used for gpu acceleration, as has been
|
|||
attempted on some ARM embedded platforms. Such drivers really must have
|
||||
a hardware-specific ioctl to allocate suitable buffer objects.
|
||||
|
||||
Output Polling
|
||||
--------------
|
||||
Display Modes Function Reference
|
||||
================================
|
||||
|
||||
void (\*output_poll_changed)(struct drm_device \*dev);
|
||||
This operation notifies the driver that the status of one or more
|
||||
connectors has changed. Drivers that use the fb helper can just call the
|
||||
:c:func:`drm_fb_helper_hotplug_event()` function to handle this
|
||||
operation.
|
||||
.. kernel-doc:: include/drm/drm_modes.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_modes.c
|
||||
:export:
|
||||
|
||||
Connector Abstraction
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: overview
|
||||
|
||||
Connector Functions Reference
|
||||
-----------------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_connector.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:export:
|
||||
|
||||
KMS Initialization and Cleanup
|
||||
==============================
|
||||
|
@ -236,166 +238,6 @@ encoders unattached at initialization time. Applications (or the fbdev
|
|||
compatibility layer when implemented) are responsible for attaching the
|
||||
encoders they want to use to a CRTC.
|
||||
|
||||
Connectors (:c:type:`struct drm_connector <drm_connector>`)
|
||||
-----------------------------------------------------------
|
||||
|
||||
A connector is the final destination for pixel data on a device, and
|
||||
usually connects directly to an external display device like a monitor
|
||||
or laptop panel. A connector can only be attached to one encoder at a
|
||||
time. The connector is also the structure where information about the
|
||||
attached display is kept, so it contains fields for display data, EDID
|
||||
data, DPMS & connection status, and information about modes supported on
|
||||
the attached displays.
|
||||
|
||||
Connector Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Finally a KMS driver must create, initialize, register and attach at
|
||||
least one :c:type:`struct drm_connector <drm_connector>`
|
||||
instance. The instance is created as other KMS objects and initialized
|
||||
by setting the following fields.
|
||||
|
||||
interlace_allowed
|
||||
Whether the connector can handle interlaced modes.
|
||||
|
||||
doublescan_allowed
|
||||
Whether the connector can handle doublescan.
|
||||
|
||||
display_info
|
||||
Display information is filled from EDID information when a display
|
||||
is detected. For non hot-pluggable displays such as flat panels in
|
||||
embedded systems, the driver should initialize the
|
||||
display_info.width_mm and display_info.height_mm fields with the
|
||||
physical size of the display.
|
||||
|
||||
polled
|
||||
Connector polling mode, a combination of
|
||||
|
||||
DRM_CONNECTOR_POLL_HPD
|
||||
The connector generates hotplug events and doesn't need to be
|
||||
periodically polled. The CONNECT and DISCONNECT flags must not
|
||||
be set together with the HPD flag.
|
||||
|
||||
DRM_CONNECTOR_POLL_CONNECT
|
||||
Periodically poll the connector for connection.
|
||||
|
||||
DRM_CONNECTOR_POLL_DISCONNECT
|
||||
Periodically poll the connector for disconnection.
|
||||
|
||||
Set to 0 for connectors that don't support connection status
|
||||
discovery.
|
||||
|
||||
The connector is then registered with a call to
|
||||
:c:func:`drm_connector_init()` with a pointer to the connector
|
||||
functions and a connector type, and exposed through sysfs with a call to
|
||||
:c:func:`drm_connector_register()`.
|
||||
|
||||
Supported connector types are
|
||||
|
||||
- DRM_MODE_CONNECTOR_VGA
|
||||
- DRM_MODE_CONNECTOR_DVII
|
||||
- DRM_MODE_CONNECTOR_DVID
|
||||
- DRM_MODE_CONNECTOR_DVIA
|
||||
- DRM_MODE_CONNECTOR_Composite
|
||||
- DRM_MODE_CONNECTOR_SVIDEO
|
||||
- DRM_MODE_CONNECTOR_LVDS
|
||||
- DRM_MODE_CONNECTOR_Component
|
||||
- DRM_MODE_CONNECTOR_9PinDIN
|
||||
- DRM_MODE_CONNECTOR_DisplayPort
|
||||
- DRM_MODE_CONNECTOR_HDMIA
|
||||
- DRM_MODE_CONNECTOR_HDMIB
|
||||
- DRM_MODE_CONNECTOR_TV
|
||||
- DRM_MODE_CONNECTOR_eDP
|
||||
- DRM_MODE_CONNECTOR_VIRTUAL
|
||||
|
||||
Connectors must be attached to an encoder to be used. For devices that
|
||||
map connectors to encoders 1:1, the connector should be attached at
|
||||
initialization time with a call to
|
||||
:c:func:`drm_mode_connector_attach_encoder()`. The driver must
|
||||
also set the :c:type:`struct drm_connector <drm_connector>`
|
||||
encoder field to point to the attached encoder.
|
||||
|
||||
Finally, drivers must initialize the connectors state change detection
|
||||
with a call to :c:func:`drm_kms_helper_poll_init()`. If at least
|
||||
one connector is pollable but can't generate hotplug interrupts
|
||||
(indicated by the DRM_CONNECTOR_POLL_CONNECT and
|
||||
DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will
|
||||
automatically be queued to periodically poll for changes. Connectors
|
||||
that can generate hotplug interrupts must be marked with the
|
||||
DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must
|
||||
call :c:func:`drm_helper_hpd_irq_event()`. The function will
|
||||
queue a delayed work to check the state of all connectors, but no
|
||||
periodic polling will be done.
|
||||
|
||||
Connector Operations
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Note**
|
||||
|
||||
Unless otherwise state, all operations are mandatory.
|
||||
|
||||
DPMS
|
||||
''''
|
||||
|
||||
void (\*dpms)(struct drm_connector \*connector, int mode);
|
||||
The DPMS operation sets the power state of a connector. The mode
|
||||
argument is one of
|
||||
|
||||
- DRM_MODE_DPMS_ON
|
||||
|
||||
- DRM_MODE_DPMS_STANDBY
|
||||
|
||||
- DRM_MODE_DPMS_SUSPEND
|
||||
|
||||
- DRM_MODE_DPMS_OFF
|
||||
|
||||
In all but DPMS_ON mode the encoder to which the connector is attached
|
||||
should put the display in low-power mode by driving its signals
|
||||
appropriately. If more than one connector is attached to the encoder
|
||||
care should be taken not to change the power state of other displays as
|
||||
a side effect. Low-power mode should be propagated to the encoders and
|
||||
CRTCs when all related connectors are put in low-power mode.
|
||||
|
||||
Modes
|
||||
'''''
|
||||
|
||||
int (\*fill_modes)(struct drm_connector \*connector, uint32_t
|
||||
max_width, uint32_t max_height);
|
||||
Fill the mode list with all supported modes for the connector. If the
|
||||
``max_width`` and ``max_height`` arguments are non-zero, the
|
||||
implementation must ignore all modes wider than ``max_width`` or higher
|
||||
than ``max_height``.
|
||||
|
||||
The connector must also fill in this operation its display_info
|
||||
width_mm and height_mm fields with the connected display physical size
|
||||
in millimeters. The fields should be set to 0 if the value isn't known
|
||||
or is not applicable (for instance for projector devices).
|
||||
|
||||
Connection Status
|
||||
'''''''''''''''''
|
||||
|
||||
The connection status is updated through polling or hotplug events when
|
||||
supported (see ?). The status value is reported to userspace through
|
||||
ioctls and must not be used inside the driver, as it only gets
|
||||
initialized by a call to :c:func:`drm_mode_getconnector()` from
|
||||
userspace.
|
||||
|
||||
enum drm_connector_status (\*detect)(struct drm_connector
|
||||
\*connector, bool force);
|
||||
Check to see if anything is attached to the connector. The ``force``
|
||||
parameter is set to false whilst polling or to true when checking the
|
||||
connector due to user request. ``force`` can be used by the driver to
|
||||
avoid expensive, destructive operations during automated probing.
|
||||
|
||||
Return connector_status_connected if something is connected to the
|
||||
connector, connector_status_disconnected if nothing is connected and
|
||||
connector_status_unknown if the connection state isn't known.
|
||||
|
||||
Drivers should only return connector_status_connected if the
|
||||
connection status has really been probed as connected. Connectors that
|
||||
can't detect the connection status, or failed connection status probes,
|
||||
should return connector_status_unknown.
|
||||
|
||||
Cleanup
|
||||
-------
|
||||
|
||||
|
@ -463,20 +305,8 @@ created for fetching EDID data and performing monitor detection. Once
|
|||
the process is complete, the new connector is registered with sysfs to
|
||||
make its properties available to applications.
|
||||
|
||||
KMS API Functions
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:export:
|
||||
|
||||
KMS Data Structures
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_crtc.h
|
||||
:internal:
|
||||
|
||||
KMS Locking
|
||||
-----------
|
||||
===========
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c
|
||||
:doc: kms locking
|
||||
|
@ -575,6 +405,12 @@ connector and plane objects by calling the
|
|||
pointer to the target object, a pointer to the previously created
|
||||
property and an initial instance value.
|
||||
|
||||
Blending and Z-Position properties
|
||||
----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_blend.c
|
||||
:export:
|
||||
|
||||
Existing KMS Properties
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -26,12 +26,12 @@ TTM, but has no video RAM management capabilities and is thus limited to
|
|||
UMA devices.
|
||||
|
||||
The Translation Table Manager (TTM)
|
||||
-----------------------------------
|
||||
===================================
|
||||
|
||||
TTM design background and information belongs here.
|
||||
|
||||
TTM initialization
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
------------------
|
||||
|
||||
**Warning**
|
||||
|
||||
|
@ -77,7 +77,7 @@ object, ttm_global_item_ref() is used to create an initial reference
|
|||
count for the TTM, which will call your initialization function.
|
||||
|
||||
The Graphics Execution Manager (GEM)
|
||||
------------------------------------
|
||||
====================================
|
||||
|
||||
The GEM design approach has resulted in a memory manager that doesn't
|
||||
provide full coverage of all (or even all common) use cases in its
|
||||
|
@ -114,7 +114,7 @@ read & write, mapping, and domain ownership transfers are left to
|
|||
driver-specific ioctls.
|
||||
|
||||
GEM Initialization
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
------------------
|
||||
|
||||
Drivers that use GEM must set the DRIVER_GEM bit in the struct
|
||||
:c:type:`struct drm_driver <drm_driver>` driver_features
|
||||
|
@ -132,7 +132,7 @@ typically not managed by GEM, and must be initialized separately into
|
|||
its own DRM MM object.
|
||||
|
||||
GEM Objects Creation
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------
|
||||
|
||||
GEM splits creation of GEM objects and allocation of the memory that
|
||||
backs them in two distinct operations.
|
||||
|
@ -173,7 +173,7 @@ a call to :c:func:`drm_gem_private_object_init()` instead of
|
|||
must be managed by drivers.
|
||||
|
||||
GEM Objects Lifetime
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
--------------------
|
||||
|
||||
All GEM objects are reference-counted by the GEM core. References can be
|
||||
acquired and release by :c:func:`calling
|
||||
|
@ -196,7 +196,7 @@ resources created by the GEM core, which need to be released with
|
|||
:c:func:`drm_gem_object_release()`.
|
||||
|
||||
GEM Objects Naming
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
------------------
|
||||
|
||||
Communication between userspace and the kernel refers to GEM objects
|
||||
using local handles, global names or, more recently, file descriptors.
|
||||
|
@ -245,7 +245,7 @@ Furthermore PRIME also allows cross-device buffer sharing since it is
|
|||
based on dma-bufs.
|
||||
|
||||
GEM Objects Mapping
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
-------------------
|
||||
|
||||
Because mapping operations are fairly heavyweight GEM favours
|
||||
read/write-like access to buffers, implemented through driver-specific
|
||||
|
@ -304,7 +304,7 @@ Drivers that want to map the GEM object upfront instead of handling page
|
|||
faults can implement their own mmap file operation handler.
|
||||
|
||||
Memory Coherency
|
||||
~~~~~~~~~~~~~~~~
|
||||
----------------
|
||||
|
||||
When mapped to the device or used in a command buffer, backing pages for
|
||||
an object are flushed to memory and marked write combined so as to be
|
||||
|
@ -320,7 +320,7 @@ blocks the client and waits for rendering to complete before performing
|
|||
any necessary flushing operations).
|
||||
|
||||
Command Execution
|
||||
~~~~~~~~~~~~~~~~~
|
||||
-----------------
|
||||
|
||||
Perhaps the most important GEM function for GPU devices is providing a
|
||||
command execution interface to clients. Client programs construct
|
||||
|
@ -348,8 +348,20 @@ GEM Function Reference
|
|||
.. kernel-doc:: include/drm/drm_gem.h
|
||||
:internal:
|
||||
|
||||
GEM CMA Helper Functions Reference
|
||||
----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:doc: cma helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_cma_helper.h
|
||||
:internal:
|
||||
|
||||
VMA Offset Manager
|
||||
------------------
|
||||
==================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c
|
||||
:doc: vma offset manager
|
||||
|
@ -361,14 +373,14 @@ VMA Offset Manager
|
|||
:internal:
|
||||
|
||||
PRIME Buffer Sharing
|
||||
--------------------
|
||||
====================
|
||||
|
||||
PRIME is the cross device buffer sharing framework in drm, originally
|
||||
created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME
|
||||
buffers are dma-buf based file descriptors.
|
||||
|
||||
Overview and Driver Interface
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-----------------------------
|
||||
|
||||
Similar to GEM global names, PRIME file descriptors are also used to
|
||||
share buffer objects across processes. They offer additional security:
|
||||
|
@ -406,7 +418,7 @@ struct drm_gem_object \*obj, int flags); struct drm_gem_object \*
|
|||
support PRIME.
|
||||
|
||||
PRIME Helper Functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_prime.c
|
||||
:doc: PRIME Helpers
|
||||
|
@ -418,16 +430,16 @@ PRIME Function References
|
|||
:export:
|
||||
|
||||
DRM MM Range Allocator
|
||||
----------------------
|
||||
======================
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
|
||||
:doc: Overview
|
||||
|
||||
LRU Scan/Eviction Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_mm.c
|
||||
:doc: lru scan roaster
|
||||
|
@ -440,15 +452,3 @@ DRM MM Range Allocator Function References
|
|||
|
||||
.. kernel-doc:: include/drm/drm_mm.h
|
||||
:internal:
|
||||
|
||||
CMA Helper Functions Reference
|
||||
------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:doc: cma helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_cma_helper.h
|
||||
:internal:
|
||||
|
|
|
@ -33,6 +33,9 @@ Primary Nodes, DRM Master and Authentication
|
|||
.. kernel-doc:: include/drm/drm_auth.h
|
||||
:internal:
|
||||
|
||||
Open-Source Userspace Requirements
|
||||
==================================
|
||||
|
||||
Render nodes
|
||||
============
|
||||
|
||||
|
|
|
@ -12,3 +12,4 @@ Linux GPU Driver Developer's Guide
|
|||
drm-uapi
|
||||
i915
|
||||
vga-switcheroo
|
||||
vgaarbiter
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
.. _vga_switcheroo:
|
||||
|
||||
==============
|
||||
VGA Switcheroo
|
||||
==============
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
===========
|
||||
VGA Arbiter
|
||||
===========
|
||||
|
||||
|
@ -19,21 +19,8 @@ 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.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
I. Details and Theory of Operation
|
||||
I.1 vgaarb
|
||||
I.2 libpciaccess
|
||||
I.3 xf86VGAArbiter (X server implementation)
|
||||
II. Credits
|
||||
III.References
|
||||
|
||||
|
||||
I. Details and Theory of Operation
|
||||
==================================
|
||||
|
||||
I.1 vgaarb
|
||||
----------
|
||||
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
|
||||
|
@ -44,42 +31,52 @@ 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 : open user instance of the arbiter. By default, it's attached to
|
||||
the default VGA device of the system.
|
||||
open
|
||||
Opens a user instance of the arbiter. By default, it's attached to the
|
||||
default VGA device of the system.
|
||||
|
||||
close : close user instance. Release locks made by the user
|
||||
close
|
||||
Close a user instance. Release locks made by the user
|
||||
|
||||
read : return a string indicating the status of the target like:
|
||||
read
|
||||
Return a string indicating the status of the target like:
|
||||
|
||||
"<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
|
||||
"<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.
|
||||
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:
|
||||
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
|
||||
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)
|
||||
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.
|
||||
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:
|
||||
|
||||
|
@ -97,29 +94,35 @@ 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
|
||||
-------------------
|
||||
|
||||
I.2 libpciaccess
|
||||
----------------
|
||||
.. kernel-doc:: include/linux/vgaarb.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/vga/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):
|
||||
on the system)::
|
||||
|
||||
/* the type of resource decoded by the device */
|
||||
int vgaarb_rsrc;
|
||||
|
||||
Besides it, in pci_system were added:
|
||||
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
|
||||
|
@ -136,44 +139,44 @@ 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. ::
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
interrupts at any time. ::
|
||||
|
||||
int pci_device_vgaarb_decodes (int new_vgaarb_rsrc);
|
||||
|
||||
Connects to the arbiter device, allocates the struct
|
||||
Connects to the arbiter device, allocates the struct ::
|
||||
|
||||
int pci_device_vgaarb_init (void);
|
||||
|
||||
Close the connection
|
||||
Close the connection ::
|
||||
|
||||
void pci_device_vgaarb_fini (void);
|
||||
|
||||
|
||||
I.3 xf86VGAArbiter (X server implementation)
|
||||
--------------------------------------------
|
||||
|
||||
(TODO)
|
||||
xf86VGAArbiter (X server implementation)
|
||||
----------------------------------------
|
||||
|
||||
X server basically wraps all the functions that touch VGA registers somehow.
|
||||
|
||||
|
||||
II. Credits
|
||||
===========
|
||||
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
|
||||
|
@ -182,11 +185,7 @@ 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.
|
||||
|
||||
|
||||
III. References
|
||||
==============
|
||||
|
||||
[0] http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
|
||||
[1] http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
|
||||
[2] http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
|
||||
[3] http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
|
||||
0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
|
||||
1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
|
||||
2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
|
||||
3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
|
|
@ -586,6 +586,22 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment);
|
||||
|
||||
static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
bool write = (direction == DMA_BIDIRECTIONAL ||
|
||||
direction == DMA_TO_DEVICE);
|
||||
struct reservation_object *resv = dmabuf->resv;
|
||||
long ret;
|
||||
|
||||
/* Wait on any implicit rendering fences */
|
||||
ret = reservation_object_wait_timeout_rcu(resv, write, true,
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dma_buf_begin_cpu_access - Must be called before accessing a dma_buf from the
|
||||
|
@ -608,6 +624,13 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
|||
if (dmabuf->ops->begin_cpu_access)
|
||||
ret = dmabuf->ops->begin_cpu_access(dmabuf, direction);
|
||||
|
||||
/* Ensure that all fences are waited upon - but we first allow
|
||||
* the native handler the chance to do so more efficiently if it
|
||||
* chooses. A double invocation here will be reasonably cheap no-op.
|
||||
*/
|
||||
if (ret == 0)
|
||||
ret = __dma_buf_begin_cpu_access(dmabuf, direction);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access);
|
||||
|
|
|
@ -107,14 +107,14 @@ EXPORT_SYMBOL(fence_array_ops);
|
|||
* @fences: [in] array containing the fences
|
||||
* @context: [in] fence context to use
|
||||
* @seqno: [in] sequence number to use
|
||||
* @signal_on_any [in] signal on any fence in the array
|
||||
* @signal_on_any: [in] signal on any fence in the array
|
||||
*
|
||||
* Allocate a fence_array object and initialize the base fence with fence_init().
|
||||
* In case of error it returns NULL.
|
||||
*
|
||||
* The caller should allocte the fences array with num_fences size
|
||||
* The caller should allocate the fences array with num_fences size
|
||||
* and fill it with the fences it wants to add to the object. Ownership of this
|
||||
* array is take and fence_put() is used on each fence on release.
|
||||
* array is taken and fence_put() is used on each fence on release.
|
||||
*
|
||||
* If @signal_on_any is true the fence array signals if any fence in the array
|
||||
* signals, otherwise it signals when all fences in the array signal.
|
||||
|
|
|
@ -205,7 +205,7 @@ reservation_object_add_shared_replace(struct reservation_object *obj,
|
|||
* @fence: the shared fence to add
|
||||
*
|
||||
* Add a fence to a shared slot, obj->lock must be held, and
|
||||
* reservation_object_reserve_shared_fence has been called.
|
||||
* reservation_object_reserve_shared() has been called.
|
||||
*/
|
||||
void reservation_object_add_shared_fence(struct reservation_object *obj,
|
||||
struct fence *fence)
|
||||
|
|
|
@ -12,7 +12,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
|
|||
drm_info.o drm_debugfs.o drm_encoder_slave.o \
|
||||
drm_trace_points.o drm_global.o drm_prime.o \
|
||||
drm_rect.o drm_vma_manager.o drm_flip_work.o \
|
||||
drm_modeset_lock.o drm_atomic.o drm_bridge.o
|
||||
drm_modeset_lock.o drm_atomic.o drm_bridge.o \
|
||||
drm_framebuffer.o drm_connector.o drm_blend.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
||||
|
@ -24,7 +25,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
|
|||
drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
|
||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
||||
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
||||
drm_simple_kms_helper.o drm_blend.o
|
||||
drm_simple_kms_helper.o drm_modeset_helper.o
|
||||
|
||||
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||
|
|
|
@ -2071,6 +2071,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
u32 tmp, viewport_w, viewport_h;
|
||||
int r;
|
||||
bool bypass_lut = false;
|
||||
char *format_name;
|
||||
|
||||
/* no fb bound */
|
||||
if (!atomic && !crtc->primary->fb) {
|
||||
|
@ -2182,8 +2183,9 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
bypass_lut = true;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen format %s\n",
|
||||
drm_get_format_name(target_fb->pixel_format));
|
||||
format_name = drm_get_format_name(target_fb->pixel_format);
|
||||
DRM_ERROR("Unsupported screen format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -2046,6 +2046,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
u32 tmp, viewport_w, viewport_h;
|
||||
int r;
|
||||
bool bypass_lut = false;
|
||||
char *format_name;
|
||||
|
||||
/* no fb bound */
|
||||
if (!atomic && !crtc->primary->fb) {
|
||||
|
@ -2157,8 +2158,9 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
bypass_lut = true;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen format %s\n",
|
||||
drm_get_format_name(target_fb->pixel_format));
|
||||
format_name = drm_get_format_name(target_fb->pixel_format);
|
||||
DRM_ERROR("Unsupported screen format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1952,6 +1952,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
u32 viewport_w, viewport_h;
|
||||
int r;
|
||||
bool bypass_lut = false;
|
||||
char *format_name;
|
||||
|
||||
/* no fb bound */
|
||||
if (!atomic && !crtc->primary->fb) {
|
||||
|
@ -2056,8 +2057,9 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
bypass_lut = true;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen format %s\n",
|
||||
drm_get_format_name(target_fb->pixel_format));
|
||||
format_name = drm_get_format_name(target_fb->pixel_format);
|
||||
DRM_ERROR("Unsupported screen format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -183,8 +183,6 @@ static void arc_pgu_plane_atomic_update(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = {
|
||||
.prepare_fb = NULL,
|
||||
.cleanup_fb = NULL,
|
||||
.atomic_update = arc_pgu_plane_atomic_update,
|
||||
};
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ static struct drm_driver armada_drm_driver = {
|
|||
.desc = "Armada SoC DRM",
|
||||
.date = "20120730",
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET |
|
||||
DRIVER_HAVE_IRQ | DRIVER_PRIME,
|
||||
DRIVER_PRIME,
|
||||
.ioctls = armada_ioctls,
|
||||
.fops = &armada_drm_fops,
|
||||
};
|
||||
|
|
|
@ -755,7 +755,7 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
|
|||
}
|
||||
|
||||
static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
/*
|
||||
* FIXME: we should avoid this const -> non-const cast but it's
|
||||
|
@ -780,7 +780,7 @@ static int atmel_hlcdc_plane_prepare_fb(struct drm_plane *p,
|
|||
}
|
||||
|
||||
static void atmel_hlcdc_plane_cleanup_fb(struct drm_plane *p,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
/*
|
||||
* FIXME: we should avoid this const -> non-const cast but it's
|
||||
|
|
|
@ -640,7 +640,6 @@ static struct platform_driver snd_dw_hdmi_driver = {
|
|||
.remove = snd_dw_hdmi_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = PM_OPS,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -837,8 +837,9 @@ static int drm_atomic_plane_check(struct drm_plane *plane,
|
|||
/* Check whether this plane supports the fb pixel format. */
|
||||
ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format);
|
||||
if (ret) {
|
||||
DRM_DEBUG_ATOMIC("Invalid pixel format %s\n",
|
||||
drm_get_format_name(state->fb->pixel_format));
|
||||
char *format_name = drm_get_format_name(state->fb->pixel_format);
|
||||
DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -594,7 +594,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
|
|||
struct drm_plane_state *plane_state;
|
||||
int i, ret = 0;
|
||||
|
||||
ret = drm_atomic_helper_normalize_zpos(dev, state);
|
||||
ret = drm_atomic_normalize_zpos(dev, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -193,8 +193,7 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_normalize_zpos - calculate normalized zpos values for all
|
||||
* crtcs
|
||||
* drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs
|
||||
* @dev: DRM device
|
||||
* @state: atomic state of DRM device
|
||||
*
|
||||
|
@ -205,8 +204,8 @@ static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
|
|||
* RETURNS
|
||||
* Zero for success or -errno
|
||||
*/
|
||||
int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
int drm_atomic_normalize_zpos(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
@ -236,3 +235,4 @@ int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_normalize_zpos);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -74,35 +74,6 @@
|
|||
* &drm_connector_helper_funcs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_helper_move_panel_connectors_to_head() - move panels to the front in the
|
||||
* connector list
|
||||
* @dev: drm device to operate on
|
||||
*
|
||||
* Some userspace presumes that the first connected connector is the main
|
||||
* display, where it's supposed to display e.g. the login screen. For
|
||||
* laptops, this should be the main panel. Use this function to sort all
|
||||
* (eDP/LVDS) panels to the front of the connector list, instead of
|
||||
* painstakingly trying to initialize them in the right order.
|
||||
*/
|
||||
void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector, *tmp;
|
||||
struct list_head panel_list;
|
||||
|
||||
INIT_LIST_HEAD(&panel_list);
|
||||
|
||||
list_for_each_entry_safe(connector, tmp,
|
||||
&dev->mode_config.connector_list, head) {
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
list_move_tail(&connector->head, &panel_list);
|
||||
}
|
||||
|
||||
list_splice(&panel_list, &dev->mode_config.connector_list);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
|
||||
|
||||
/**
|
||||
* drm_helper_encoder_in_use - check if a given encoder is in use
|
||||
* @encoder: encoder to check
|
||||
|
@ -912,33 +883,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_helper_connector_dpms);
|
||||
|
||||
/**
|
||||
* drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
|
||||
* @fb: drm_framebuffer object to fill out
|
||||
* @mode_cmd: metadata from the userspace fb creation request
|
||||
*
|
||||
* This helper can be used in a drivers fb_create callback to pre-fill the fb's
|
||||
* metadata fields.
|
||||
*/
|
||||
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
fb->width = mode_cmd->width;
|
||||
fb->height = mode_cmd->height;
|
||||
for (i = 0; i < 4; i++) {
|
||||
fb->pitches[i] = mode_cmd->pitches[i];
|
||||
fb->offsets[i] = mode_cmd->offsets[i];
|
||||
fb->modifier[i] = mode_cmd->modifier[i];
|
||||
}
|
||||
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
|
||||
&fb->bits_per_pixel);
|
||||
fb->pixel_format = mode_cmd->pixel_format;
|
||||
fb->flags = mode_cmd->flags;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
|
||||
|
||||
/**
|
||||
* drm_helper_resume_force_mode - force-restore mode setting configuration
|
||||
* @dev: drm_device which should be restored
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2015 Intel Corporation
|
||||
* Copyright © 2016 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -8,37 +8,36 @@
|
|||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Rafael Antognolli <rafael.antognolli@intel.com>
|
||||
*
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef DRM_DP_AUX_DEV
|
||||
#define DRM_DP_AUX_DEV
|
||||
/*
|
||||
* This header file contains mode setting related functions and definitions
|
||||
* which are only used within the drm kms helper module as internal
|
||||
* implementation details and are not exported to drivers.
|
||||
*/
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
#ifdef CONFIG_DRM_DP_AUX_CHARDEV
|
||||
/* drm_fb_helper.c */
|
||||
int drm_fb_helper_modinit(void);
|
||||
|
||||
/* drm_dp_aux_dev.c */
|
||||
#ifdef CONFIG_DRM_DP_AUX_CHARDEV
|
||||
int drm_dp_aux_dev_init(void);
|
||||
void drm_dp_aux_dev_exit(void);
|
||||
int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
|
||||
void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
|
||||
|
||||
#else
|
||||
|
||||
static inline int drm_dp_aux_dev_init(void)
|
||||
{
|
||||
return 0;
|
||||
|
@ -56,7 +55,4 @@ static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
|
|||
static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -33,12 +33,23 @@
|
|||
|
||||
|
||||
/* drm_crtc.c */
|
||||
void drm_connector_ida_init(void);
|
||||
void drm_connector_ida_destroy(void);
|
||||
int drm_mode_object_get_reg(struct drm_device *dev,
|
||||
struct drm_mode_object *obj,
|
||||
uint32_t obj_type,
|
||||
bool register_obj,
|
||||
void (*obj_free_cb)(struct kref *kref));
|
||||
void drm_mode_object_register(struct drm_device *dev,
|
||||
struct drm_mode_object *obj);
|
||||
int drm_mode_object_get(struct drm_device *dev,
|
||||
struct drm_mode_object *obj, uint32_t obj_type);
|
||||
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
|
||||
uint32_t id, uint32_t type);
|
||||
void drm_mode_object_unregister(struct drm_device *dev,
|
||||
struct drm_mode_object *object);
|
||||
int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
|
||||
uint32_t __user *prop_ptr,
|
||||
uint64_t __user *prop_values,
|
||||
uint32_t *arg_count_props);
|
||||
bool drm_property_change_valid_get(struct drm_property *property,
|
||||
uint64_t value,
|
||||
struct drm_mode_object **ref);
|
||||
|
@ -64,18 +75,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
|
|||
int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* framebuffer IOCTLs */
|
||||
extern int drm_mode_addfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
extern int drm_mode_addfb2(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_rmfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* IOCTLs */
|
||||
int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
@ -88,8 +87,6 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv);
|
||||
int drm_mode_getcrtc(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getconnector(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_setcrtc(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getplane(struct drm_device *dev,
|
||||
|
@ -108,8 +105,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
|
|||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_destroyblob_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getencoder(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_gamma_get_ioctl(struct drm_device *dev,
|
||||
|
@ -120,6 +115,41 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
|
|||
int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* drm_connector.c */
|
||||
void drm_connector_ida_init(void);
|
||||
void drm_connector_ida_destroy(void);
|
||||
void drm_connector_unregister_all(struct drm_device *dev);
|
||||
int drm_connector_register_all(struct drm_device *dev);
|
||||
int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
|
||||
struct drm_property *property,
|
||||
uint64_t value);
|
||||
int drm_connector_create_standard_properties(struct drm_device *dev);
|
||||
|
||||
/* IOCTL */
|
||||
int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getconnector(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* drm_framebuffer.c */
|
||||
struct drm_framebuffer *
|
||||
drm_internal_framebuffer_create(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *r,
|
||||
struct drm_file *file_priv);
|
||||
void drm_framebuffer_free(struct kref *kref);
|
||||
|
||||
/* IOCTL */
|
||||
int drm_mode_addfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_addfb2(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_rmfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_getfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv);
|
||||
|
||||
/* drm_atomic.c */
|
||||
int drm_atomic_get_property(struct drm_mode_object *obj,
|
||||
struct drm_property *property, uint64_t *val);
|
||||
|
@ -130,5 +160,5 @@ int drm_modeset_register_all(struct drm_device *dev);
|
|||
void drm_modeset_unregister_all(struct drm_device *dev);
|
||||
|
||||
/* drm_blend.c */
|
||||
int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
int drm_atomic_normalize_zpos(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
struct drm_dp_aux_dev {
|
||||
unsigned index;
|
||||
struct drm_dp_aux *aux;
|
||||
|
@ -283,12 +285,7 @@ static int auxdev_wait_atomic_t(atomic_t *p)
|
|||
schedule();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* drm_dp_aux_unregister_devnode() - unregister a devnode for this aux channel
|
||||
* @aux: DisplayPort AUX channel
|
||||
*
|
||||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
|
||||
void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
struct drm_dp_aux_dev *aux_dev;
|
||||
|
@ -314,14 +311,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
|||
DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name);
|
||||
kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_aux_unregister_devnode);
|
||||
|
||||
/**
|
||||
* drm_dp_aux_register_devnode() - register a devnode for this aux channel
|
||||
* @aux: DisplayPort AUX channel
|
||||
*
|
||||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
struct drm_dp_aux_dev *aux_dev;
|
||||
|
@ -347,7 +337,6 @@ int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
|
|||
drm_dp_aux_unregister_devnode(aux);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_aux_register_devnode);
|
||||
|
||||
int drm_dp_aux_dev_init(void)
|
||||
{
|
||||
|
@ -369,11 +358,9 @@ int drm_dp_aux_dev_init(void)
|
|||
class_destroy(drm_dp_aux_dev_class);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_aux_dev_init);
|
||||
|
||||
void drm_dp_aux_dev_exit(void)
|
||||
{
|
||||
unregister_chrdev(drm_dev_major, "aux");
|
||||
class_destroy(drm_dp_aux_dev_class);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_aux_dev_exit);
|
||||
|
|
|
@ -28,9 +28,10 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_dp_aux_dev.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: dp helpers
|
||||
*
|
||||
|
|
|
@ -63,37 +63,51 @@ static struct idr drm_minors_idr;
|
|||
|
||||
static struct dentry *drm_debugfs_root;
|
||||
|
||||
void drm_err(const char *format, ...)
|
||||
#define DRM_PRINTK_FMT "[" DRM_NAME ":%s]%s %pV"
|
||||
|
||||
void drm_dev_printk(const struct device *dev, const char *level,
|
||||
unsigned int category, const char *function_name,
|
||||
const char *prefix, const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
|
||||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk(KERN_ERR "[" DRM_NAME ":%ps] *ERROR* %pV",
|
||||
__builtin_return_address(0), &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_err);
|
||||
|
||||
void drm_ut_debug_printk(const char *function_name, const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
if (category != DRM_UT_NONE && !(drm_debug & category))
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk(KERN_DEBUG "[" DRM_NAME ":%s] %pV", function_name, &vaf);
|
||||
if (dev)
|
||||
dev_printk(level, dev, DRM_PRINTK_FMT, function_name, prefix,
|
||||
&vaf);
|
||||
else
|
||||
printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ut_debug_printk);
|
||||
EXPORT_SYMBOL(drm_dev_printk);
|
||||
|
||||
void drm_printk(const char *level, unsigned int category,
|
||||
const char *function_name, const char *prefix,
|
||||
const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
||||
if (category != DRM_UT_NONE && !(drm_debug & category))
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_printk);
|
||||
|
||||
/*
|
||||
* DRM Minors
|
||||
|
|
|
@ -991,7 +991,7 @@ static const struct drm_display_mode edid_cea_modes[] = {
|
|||
.vrefresh = 120, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
/* 64 - 1920x1080@100Hz */
|
||||
{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2448,
|
||||
2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
|
||||
2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
|
||||
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
|
||||
.vrefresh = 100, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
|
||||
};
|
||||
|
@ -3721,14 +3721,7 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
|
||||
|
||||
/**
|
||||
* drm_assign_hdmi_deep_color_info - detect whether monitor supports
|
||||
* hdmi deep color modes and update drm_display_info if so.
|
||||
* @edid: monitor EDID information
|
||||
* @info: Updated with maximum supported deep color bpc and color format
|
||||
* if deep color supported.
|
||||
* @connector: DRM connector, used only for debug output
|
||||
*
|
||||
/*
|
||||
* Parse the CEA extension according to CEA-861-B.
|
||||
* Return true if HDMI deep color supported, false if not or unknown.
|
||||
*/
|
||||
|
@ -3822,16 +3815,6 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_add_display_info - pull display info out if present
|
||||
* @edid: EDID data
|
||||
* @info: display info (attached to connector)
|
||||
* @connector: connector whose edid is used to build display info
|
||||
*
|
||||
* Grab any available display info and stuff it into the drm_display_info
|
||||
* structure that's part of the connector. Useful for tracking bpp and
|
||||
* color spaces.
|
||||
*/
|
||||
static void drm_add_display_info(struct edid *edid,
|
||||
struct drm_display_info *info,
|
||||
struct drm_connector *connector)
|
||||
|
@ -4052,7 +4035,9 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
|
|||
* @connector: connector we're probing
|
||||
* @edid: EDID data
|
||||
*
|
||||
* Add the specified modes to the connector's mode list.
|
||||
* Add the specified modes to the connector's mode list. Also fills out the
|
||||
* &drm_display_info structure in @connector with any information which can be
|
||||
* derived from the edid.
|
||||
*
|
||||
* Return: The number of modes added or 0 if we couldn't find any.
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -617,6 +618,16 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
|
|||
kfree(helper->crtc_info);
|
||||
}
|
||||
|
||||
static void drm_fb_helper_resume_worker(struct work_struct *work)
|
||||
{
|
||||
struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
|
||||
resume_work);
|
||||
|
||||
console_lock();
|
||||
fb_set_suspend(helper->fbdev, 0);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
static void drm_fb_helper_dirty_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
|
||||
|
@ -648,6 +659,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
|||
{
|
||||
INIT_LIST_HEAD(&helper->kernel_fb_list);
|
||||
spin_lock_init(&helper->dirty_lock);
|
||||
INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker);
|
||||
INIT_WORK(&helper->dirty_work, drm_fb_helper_dirty_work);
|
||||
helper->dirty_clip.x1 = helper->dirty_clip.y1 = ~0;
|
||||
helper->funcs = funcs;
|
||||
|
@ -1023,17 +1035,65 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
|
|||
/**
|
||||
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
* @state: desired state, zero to resume, non-zero to suspend
|
||||
* @suspend: whether to suspend or resume
|
||||
*
|
||||
* A wrapper around fb_set_suspend implemented by fbdev core
|
||||
* A wrapper around fb_set_suspend implemented by fbdev core.
|
||||
* Use drm_fb_helper_set_suspend_unlocked() if you don't need to take
|
||||
* the lock yourself
|
||||
*/
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state)
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend)
|
||||
{
|
||||
if (fb_helper && fb_helper->fbdev)
|
||||
fb_set_suspend(fb_helper->fbdev, state);
|
||||
fb_set_suspend(fb_helper->fbdev, suspend);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_set_suspend);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_set_suspend_unlocked - wrapper around fb_set_suspend that also
|
||||
* takes the console lock
|
||||
* @fb_helper: driver-allocated fbdev helper
|
||||
* @suspend: whether to suspend or resume
|
||||
*
|
||||
* A wrapper around fb_set_suspend() that takes the console lock. If the lock
|
||||
* isn't available on resume, a worker is tasked with waiting for the lock
|
||||
* to become available. The console lock can be pretty contented on resume
|
||||
* due to all the printk activity.
|
||||
*
|
||||
* This function can be called multiple times with the same state since
|
||||
* &fb_info->state is checked to see if fbdev is running or not before locking.
|
||||
*
|
||||
* Use drm_fb_helper_set_suspend() if you need to take the lock yourself.
|
||||
*/
|
||||
void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
|
||||
bool suspend)
|
||||
{
|
||||
if (!fb_helper || !fb_helper->fbdev)
|
||||
return;
|
||||
|
||||
/* make sure there's no pending/ongoing resume */
|
||||
flush_work(&fb_helper->resume_work);
|
||||
|
||||
if (suspend) {
|
||||
if (fb_helper->fbdev->state != FBINFO_STATE_RUNNING)
|
||||
return;
|
||||
|
||||
console_lock();
|
||||
|
||||
} else {
|
||||
if (fb_helper->fbdev->state == FBINFO_STATE_RUNNING)
|
||||
return;
|
||||
|
||||
if (!console_trylock()) {
|
||||
schedule_work(&fb_helper->resume_work);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fb_set_suspend(fb_helper->fbdev, suspend);
|
||||
console_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked);
|
||||
|
||||
static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, u16 regno, struct fb_info *info)
|
||||
{
|
||||
|
@ -2193,7 +2253,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
|
|||
* @fb_helper: the drm_fb_helper
|
||||
*
|
||||
* Scan the connectors attached to the fb_helper and try to put together a
|
||||
* setup after *notification of a change in output configuration.
|
||||
* setup after notification of a change in output configuration.
|
||||
*
|
||||
* Called at runtime, takes the mode config locks to be able to check/change the
|
||||
* modeset configuration. Must be run from process context (which usually means
|
||||
|
|
|
@ -39,16 +39,14 @@ static char printable_char(int c)
|
|||
* drm_get_format_name - return a string for drm fourcc format
|
||||
* @format: format to compute name of
|
||||
*
|
||||
* Note that the buffer used by this function is globally shared and owned by
|
||||
* the function itself.
|
||||
*
|
||||
* FIXME: This isn't really multithreading safe.
|
||||
* Note that the buffer returned by this function is owned by the caller
|
||||
* and will need to be freed using kfree().
|
||||
*/
|
||||
const char *drm_get_format_name(uint32_t format)
|
||||
char *drm_get_format_name(uint32_t format)
|
||||
{
|
||||
static char buf[32];
|
||||
char *buf = kmalloc(32, GFP_KERNEL);
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
snprintf(buf, 32,
|
||||
"%c%c%c%c %s-endian (0x%08x)",
|
||||
printable_char(format & 0xff),
|
||||
printable_char((format >> 8) & 0xff),
|
||||
|
@ -73,6 +71,8 @@ EXPORT_SYMBOL(drm_get_format_name);
|
|||
void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
|
||||
int *bpp)
|
||||
{
|
||||
char *format_name;
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_C8:
|
||||
case DRM_FORMAT_RGB332:
|
||||
|
@ -127,8 +127,9 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
|
|||
*bpp = 32;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("unsupported pixel format %s\n",
|
||||
drm_get_format_name(format));
|
||||
format_name = drm_get_format_name(format);
|
||||
DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
*depth = 0;
|
||||
*bpp = 0;
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,831 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* Frame buffers are abstract memory objects that provide a source of pixels to
|
||||
* scanout to a CRTC. Applications explicitly request the creation of frame
|
||||
* buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and receive an opaque
|
||||
* handle that can be passed to the KMS CRTC control, plane configuration and
|
||||
* page flip functions.
|
||||
*
|
||||
* Frame buffers rely on the underlying memory manager for allocating backing
|
||||
* storage. When creating a frame buffer applications pass a memory handle
|
||||
* (or a list of memory handles for multi-planar formats) through the
|
||||
* struct &drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace
|
||||
* buffer management interface this would be a GEM handle. Drivers are however
|
||||
* free to use their own backing storage object handles, e.g. vmwgfx directly
|
||||
* exposes special TTM handles to userspace and so expects TTM handles in the
|
||||
* create ioctl and not GEM handles.
|
||||
*
|
||||
* Framebuffers are tracked with struct &drm_framebuffer. They are published
|
||||
* using drm_framebuffer_init() - after calling that function userspace can use
|
||||
* and access the framebuffer object. The helper function
|
||||
* drm_helper_mode_fill_fb_struct() can be used to pre-fill the required
|
||||
* metadata fields.
|
||||
*
|
||||
* The lifetime of a drm framebuffer is controlled with a reference count,
|
||||
* drivers can grab additional references with drm_framebuffer_reference() and
|
||||
* drop them again with drm_framebuffer_unreference(). For driver-private
|
||||
* framebuffers for which the last reference is never dropped (e.g. for the
|
||||
* fbdev framebuffer when the struct struct &drm_framebuffer is embedded into
|
||||
* the fbdev helper struct) drivers can manually clean up a framebuffer at
|
||||
* module unload time with drm_framebuffer_unregister_private(). But doing this
|
||||
* is not recommended, and it's better to have a normal free-standing struct
|
||||
* &drm_framebuffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_mode_addfb - add an FB to the graphics configuration
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Add a new FB to the specified CRTC, given a user request. This is the
|
||||
* original addfb ioctl which only supported RGB formats.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_addfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_fb_cmd *or = data;
|
||||
struct drm_mode_fb_cmd2 r = {};
|
||||
int ret;
|
||||
|
||||
/* convert to new format and call new ioctl */
|
||||
r.fb_id = or->fb_id;
|
||||
r.width = or->width;
|
||||
r.height = or->height;
|
||||
r.pitches[0] = or->pitch;
|
||||
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
|
||||
r.handles[0] = or->handle;
|
||||
|
||||
ret = drm_mode_addfb2(dev, &r, file_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
or->fb_id = r.fb_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int format_check(const struct drm_mode_fb_cmd2 *r)
|
||||
{
|
||||
uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
|
||||
char *format_name;
|
||||
|
||||
switch (format) {
|
||||
case DRM_FORMAT_C8:
|
||||
case DRM_FORMAT_RGB332:
|
||||
case DRM_FORMAT_BGR233:
|
||||
case DRM_FORMAT_XRGB4444:
|
||||
case DRM_FORMAT_XBGR4444:
|
||||
case DRM_FORMAT_RGBX4444:
|
||||
case DRM_FORMAT_BGRX4444:
|
||||
case DRM_FORMAT_ARGB4444:
|
||||
case DRM_FORMAT_ABGR4444:
|
||||
case DRM_FORMAT_RGBA4444:
|
||||
case DRM_FORMAT_BGRA4444:
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
case DRM_FORMAT_XBGR1555:
|
||||
case DRM_FORMAT_RGBX5551:
|
||||
case DRM_FORMAT_BGRX5551:
|
||||
case DRM_FORMAT_ARGB1555:
|
||||
case DRM_FORMAT_ABGR1555:
|
||||
case DRM_FORMAT_RGBA5551:
|
||||
case DRM_FORMAT_BGRA5551:
|
||||
case DRM_FORMAT_RGB565:
|
||||
case DRM_FORMAT_BGR565:
|
||||
case DRM_FORMAT_RGB888:
|
||||
case DRM_FORMAT_BGR888:
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
case DRM_FORMAT_RGBX8888:
|
||||
case DRM_FORMAT_BGRX8888:
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
case DRM_FORMAT_RGBA8888:
|
||||
case DRM_FORMAT_BGRA8888:
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
case DRM_FORMAT_RGBX1010102:
|
||||
case DRM_FORMAT_BGRX1010102:
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
case DRM_FORMAT_RGBA1010102:
|
||||
case DRM_FORMAT_BGRA1010102:
|
||||
case DRM_FORMAT_YUYV:
|
||||
case DRM_FORMAT_YVYU:
|
||||
case DRM_FORMAT_UYVY:
|
||||
case DRM_FORMAT_VYUY:
|
||||
case DRM_FORMAT_AYUV:
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_NV21:
|
||||
case DRM_FORMAT_NV16:
|
||||
case DRM_FORMAT_NV61:
|
||||
case DRM_FORMAT_NV24:
|
||||
case DRM_FORMAT_NV42:
|
||||
case DRM_FORMAT_YUV410:
|
||||
case DRM_FORMAT_YVU410:
|
||||
case DRM_FORMAT_YUV411:
|
||||
case DRM_FORMAT_YVU411:
|
||||
case DRM_FORMAT_YUV420:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_YUV422:
|
||||
case DRM_FORMAT_YVU422:
|
||||
case DRM_FORMAT_YUV444:
|
||||
case DRM_FORMAT_YVU444:
|
||||
return 0;
|
||||
default:
|
||||
format_name = drm_get_format_name(r->pixel_format);
|
||||
DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
||||
{
|
||||
int ret, hsub, vsub, num_planes, i;
|
||||
|
||||
ret = format_check(r);
|
||||
if (ret) {
|
||||
char *format_name = drm_get_format_name(r->pixel_format);
|
||||
DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
|
||||
vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
|
||||
num_planes = drm_format_num_planes(r->pixel_format);
|
||||
|
||||
if (r->width == 0 || r->width % hsub) {
|
||||
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->height == 0 || r->height % vsub) {
|
||||
DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_planes; i++) {
|
||||
unsigned int width = r->width / (i != 0 ? hsub : 1);
|
||||
unsigned int height = r->height / (i != 0 ? vsub : 1);
|
||||
unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
|
||||
|
||||
if (!r->handles[i]) {
|
||||
DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((uint64_t) width * cpp > UINT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (r->pitches[i] < width * cpp) {
|
||||
DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
|
||||
DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
|
||||
r->modifier[i], i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* modifier specific checks: */
|
||||
switch (r->modifier[i]) {
|
||||
case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
|
||||
/* NOTE: the pitch restriction may be lifted later if it turns
|
||||
* out that no hw has this restriction:
|
||||
*/
|
||||
if (r->pixel_format != DRM_FORMAT_NV12 ||
|
||||
width % 128 || height % 32 ||
|
||||
r->pitches[i] % 128) {
|
||||
DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = num_planes; i < 4; i++) {
|
||||
if (r->modifier[i]) {
|
||||
DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
|
||||
if (!(r->flags & DRM_MODE_FB_MODIFIERS))
|
||||
continue;
|
||||
|
||||
if (r->handles[i]) {
|
||||
DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->pitches[i]) {
|
||||
DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->offsets[i]) {
|
||||
DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_framebuffer *
|
||||
drm_internal_framebuffer_create(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *r,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
|
||||
DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if ((config->min_width > r->width) || (r->width > config->max_width)) {
|
||||
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
|
||||
r->width, config->min_width, config->max_width);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
if ((config->min_height > r->height) || (r->height > config->max_height)) {
|
||||
DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
|
||||
r->height, config->min_height, config->max_height);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (r->flags & DRM_MODE_FB_MODIFIERS &&
|
||||
!dev->mode_config.allow_fb_modifiers) {
|
||||
DRM_DEBUG_KMS("driver does not support fb modifiers\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ret = framebuffer_check(r);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_DEBUG_KMS("could not create framebuffer\n");
|
||||
return fb;
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_addfb2 - add an FB to the graphics configuration
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Add a new FB to the specified CRTC, given a user request with format. This is
|
||||
* the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
|
||||
* and uses fourcc codes as pixel format specifiers.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_addfb2(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_fb_cmd2 *r = data;
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
||||
fb = drm_internal_framebuffer_create(dev, r, file_priv);
|
||||
if (IS_ERR(fb))
|
||||
return PTR_ERR(fb);
|
||||
|
||||
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
|
||||
r->fb_id = fb->base.id;
|
||||
|
||||
/* Transfer ownership to the filp for reaping on close */
|
||||
mutex_lock(&file_priv->fbs_lock);
|
||||
list_add(&fb->filp_head, &file_priv->fbs);
|
||||
mutex_unlock(&file_priv->fbs_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_mode_rmfb_work {
|
||||
struct work_struct work;
|
||||
struct list_head fbs;
|
||||
};
|
||||
|
||||
static void drm_mode_rmfb_work_fn(struct work_struct *w)
|
||||
{
|
||||
struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
|
||||
|
||||
while (!list_empty(&arg->fbs)) {
|
||||
struct drm_framebuffer *fb =
|
||||
list_first_entry(&arg->fbs, typeof(*fb), filp_head);
|
||||
|
||||
list_del_init(&fb->filp_head);
|
||||
drm_framebuffer_remove(fb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_rmfb - remove an FB from the configuration
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Remove the FB specified by the user.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_rmfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
struct drm_framebuffer *fbl = NULL;
|
||||
uint32_t *id = data;
|
||||
int found = 0;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, *id);
|
||||
if (!fb)
|
||||
return -ENOENT;
|
||||
|
||||
mutex_lock(&file_priv->fbs_lock);
|
||||
list_for_each_entry(fbl, &file_priv->fbs, filp_head)
|
||||
if (fb == fbl)
|
||||
found = 1;
|
||||
if (!found) {
|
||||
mutex_unlock(&file_priv->fbs_lock);
|
||||
goto fail_unref;
|
||||
}
|
||||
|
||||
list_del_init(&fb->filp_head);
|
||||
mutex_unlock(&file_priv->fbs_lock);
|
||||
|
||||
/* drop the reference we picked up in framebuffer lookup */
|
||||
drm_framebuffer_unreference(fb);
|
||||
|
||||
/*
|
||||
* we now own the reference that was stored in the fbs list
|
||||
*
|
||||
* drm_framebuffer_remove may fail with -EINTR on pending signals,
|
||||
* so run this in a separate stack as there's no way to correctly
|
||||
* handle this after the fb is already removed from the lookup table.
|
||||
*/
|
||||
if (drm_framebuffer_read_refcount(fb) > 1) {
|
||||
struct drm_mode_rmfb_work arg;
|
||||
|
||||
INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
|
||||
INIT_LIST_HEAD(&arg.fbs);
|
||||
list_add_tail(&fb->filp_head, &arg.fbs);
|
||||
|
||||
schedule_work(&arg.work);
|
||||
flush_work(&arg.work);
|
||||
destroy_work_on_stack(&arg.work);
|
||||
} else
|
||||
drm_framebuffer_unreference(fb);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_unref:
|
||||
drm_framebuffer_unreference(fb);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_getfb - get FB info
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Lookup the FB given its ID and return info about it.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_getfb(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_fb_cmd *r = data;
|
||||
struct drm_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, r->fb_id);
|
||||
if (!fb)
|
||||
return -ENOENT;
|
||||
|
||||
r->height = fb->height;
|
||||
r->width = fb->width;
|
||||
r->depth = fb->depth;
|
||||
r->bpp = fb->bits_per_pixel;
|
||||
r->pitch = fb->pitches[0];
|
||||
if (fb->funcs->create_handle) {
|
||||
if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
|
||||
drm_is_control_client(file_priv)) {
|
||||
ret = fb->funcs->create_handle(fb, file_priv,
|
||||
&r->handle);
|
||||
} else {
|
||||
/* GET_FB() is an unprivileged ioctl so we must not
|
||||
* return a buffer-handle to non-master processes! For
|
||||
* backwards-compatibility reasons, we cannot make
|
||||
* GET_FB() privileged, so just return an invalid handle
|
||||
* for non-masters. */
|
||||
r->handle = 0;
|
||||
ret = 0;
|
||||
}
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
drm_framebuffer_unreference(fb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
|
||||
* @dev: drm device for the ioctl
|
||||
* @data: data pointer for the ioctl
|
||||
* @file_priv: drm file for the ioctl call
|
||||
*
|
||||
* Lookup the FB and flush out the damaged area supplied by userspace as a clip
|
||||
* rectangle list. Generic userspace which does frontbuffer rendering must call
|
||||
* this ioctl to flush out the changes on manual-update display outputs, e.g.
|
||||
* usb display-link, mipi manual update panels or edp panel self refresh modes.
|
||||
*
|
||||
* Modesetting drivers which always update the frontbuffer do not need to
|
||||
* implement the corresponding ->dirty framebuffer callback.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_clip_rect __user *clips_ptr;
|
||||
struct drm_clip_rect *clips = NULL;
|
||||
struct drm_mode_fb_dirty_cmd *r = data;
|
||||
struct drm_framebuffer *fb;
|
||||
unsigned flags;
|
||||
int num_clips;
|
||||
int ret;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, r->fb_id);
|
||||
if (!fb)
|
||||
return -ENOENT;
|
||||
|
||||
num_clips = r->num_clips;
|
||||
clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
|
||||
|
||||
if (!num_clips != !clips_ptr) {
|
||||
ret = -EINVAL;
|
||||
goto out_err1;
|
||||
}
|
||||
|
||||
flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
|
||||
|
||||
/* If userspace annotates copy, clips must come in pairs */
|
||||
if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
|
||||
ret = -EINVAL;
|
||||
goto out_err1;
|
||||
}
|
||||
|
||||
if (num_clips && clips_ptr) {
|
||||
if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
|
||||
ret = -EINVAL;
|
||||
goto out_err1;
|
||||
}
|
||||
clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
|
||||
if (!clips) {
|
||||
ret = -ENOMEM;
|
||||
goto out_err1;
|
||||
}
|
||||
|
||||
ret = copy_from_user(clips, clips_ptr,
|
||||
num_clips * sizeof(*clips));
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
goto out_err2;
|
||||
}
|
||||
}
|
||||
|
||||
if (fb->funcs->dirty) {
|
||||
ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
|
||||
clips, num_clips);
|
||||
} else {
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
out_err2:
|
||||
kfree(clips);
|
||||
out_err1:
|
||||
drm_framebuffer_unreference(fb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_release - remove and free the FBs on this file
|
||||
* @priv: drm file for the ioctl
|
||||
*
|
||||
* Destroy all the FBs associated with @filp.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
void drm_fb_release(struct drm_file *priv)
|
||||
{
|
||||
struct drm_framebuffer *fb, *tfb;
|
||||
struct drm_mode_rmfb_work arg;
|
||||
|
||||
INIT_LIST_HEAD(&arg.fbs);
|
||||
|
||||
/*
|
||||
* When the file gets released that means no one else can access the fb
|
||||
* list any more, so no need to grab fpriv->fbs_lock. And we need to
|
||||
* avoid upsetting lockdep since the universal cursor code adds a
|
||||
* framebuffer while holding mutex locks.
|
||||
*
|
||||
* Note that a real deadlock between fpriv->fbs_lock and the modeset
|
||||
* locks is impossible here since no one else but this function can get
|
||||
* at it any more.
|
||||
*/
|
||||
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
|
||||
if (drm_framebuffer_read_refcount(fb) > 1) {
|
||||
list_move_tail(&fb->filp_head, &arg.fbs);
|
||||
} else {
|
||||
list_del_init(&fb->filp_head);
|
||||
|
||||
/* This drops the fpriv->fbs reference. */
|
||||
drm_framebuffer_unreference(fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&arg.fbs)) {
|
||||
INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
|
||||
|
||||
schedule_work(&arg.work);
|
||||
flush_work(&arg.work);
|
||||
destroy_work_on_stack(&arg.work);
|
||||
}
|
||||
}
|
||||
|
||||
void drm_framebuffer_free(struct kref *kref)
|
||||
{
|
||||
struct drm_framebuffer *fb =
|
||||
container_of(kref, struct drm_framebuffer, base.refcount);
|
||||
struct drm_device *dev = fb->dev;
|
||||
|
||||
/*
|
||||
* The lookup idr holds a weak reference, which has not necessarily been
|
||||
* removed at this point. Check for that.
|
||||
*/
|
||||
drm_mode_object_unregister(dev, &fb->base);
|
||||
|
||||
fb->funcs->destroy(fb);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_init - initialize a framebuffer
|
||||
* @dev: DRM device
|
||||
* @fb: framebuffer to be initialized
|
||||
* @funcs: ... with these functions
|
||||
*
|
||||
* Allocates an ID for the framebuffer's parent mode object, sets its mode
|
||||
* functions & device file and adds it to the master fd list.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* This functions publishes the fb and makes it available for concurrent access
|
||||
* by other users. Which means by this point the fb _must_ be fully set up -
|
||||
* since all the fb attributes are invariant over its lifetime, no further
|
||||
* locking but only correct reference counting is required.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
|
||||
const struct drm_framebuffer_funcs *funcs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
INIT_LIST_HEAD(&fb->filp_head);
|
||||
fb->dev = dev;
|
||||
fb->funcs = funcs;
|
||||
|
||||
ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
|
||||
false, drm_framebuffer_free);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&dev->mode_config.fb_lock);
|
||||
dev->mode_config.num_fb++;
|
||||
list_add(&fb->head, &dev->mode_config.fb_list);
|
||||
mutex_unlock(&dev->mode_config.fb_lock);
|
||||
|
||||
drm_mode_object_register(dev, &fb->base);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_init);
|
||||
|
||||
/**
|
||||
* drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
|
||||
* @dev: drm device
|
||||
* @id: id of the fb object
|
||||
*
|
||||
* If successful, this grabs an additional reference to the framebuffer -
|
||||
* callers need to make sure to eventually unreference the returned framebuffer
|
||||
* again, using @drm_framebuffer_unreference.
|
||||
*/
|
||||
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
|
||||
uint32_t id)
|
||||
{
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
|
||||
obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB);
|
||||
if (obj)
|
||||
fb = obj_to_fb(obj);
|
||||
return fb;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_lookup);
|
||||
|
||||
/**
|
||||
* drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
|
||||
* @fb: fb to unregister
|
||||
*
|
||||
* Drivers need to call this when cleaning up driver-private framebuffers, e.g.
|
||||
* those used for fbdev. Note that the caller must hold a reference of it's own,
|
||||
* i.e. the object may not be destroyed through this call (since it'll lead to a
|
||||
* locking inversion).
|
||||
*/
|
||||
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
dev = fb->dev;
|
||||
|
||||
/* Mark fb as reaped and drop idr ref. */
|
||||
drm_mode_object_unregister(dev, &fb->base);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_unregister_private);
|
||||
|
||||
/**
|
||||
* drm_framebuffer_cleanup - remove a framebuffer object
|
||||
* @fb: framebuffer to remove
|
||||
*
|
||||
* Cleanup framebuffer. This function is intended to be used from the drivers
|
||||
* ->destroy callback. It can also be used to clean up driver private
|
||||
* framebuffers embedded into a larger structure.
|
||||
*
|
||||
* Note that this function does not remove the fb from active usuage - if it is
|
||||
* still used anywhere, hilarity can ensue since userspace could call getfb on
|
||||
* the id and get back -EINVAL. Obviously no concern at driver unload time.
|
||||
*
|
||||
* Also, the framebuffer will not be removed from the lookup idr - for
|
||||
* user-created framebuffers this will happen in in the rmfb ioctl. For
|
||||
* driver-private objects (e.g. for fbdev) drivers need to explicitly call
|
||||
* drm_framebuffer_unregister_private.
|
||||
*/
|
||||
void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev = fb->dev;
|
||||
|
||||
mutex_lock(&dev->mode_config.fb_lock);
|
||||
list_del(&fb->head);
|
||||
dev->mode_config.num_fb--;
|
||||
mutex_unlock(&dev->mode_config.fb_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_cleanup);
|
||||
|
||||
/**
|
||||
* drm_framebuffer_remove - remove and unreference a framebuffer object
|
||||
* @fb: framebuffer to remove
|
||||
*
|
||||
* Scans all the CRTCs and planes in @dev's mode_config. If they're
|
||||
* using @fb, removes it, setting it to NULL. Then drops the reference to the
|
||||
* passed-in framebuffer. Might take the modeset locks.
|
||||
*
|
||||
* Note that this function optimizes the cleanup away if the caller holds the
|
||||
* last reference to the framebuffer. It is also guaranteed to not take the
|
||||
* modeset locks in this case.
|
||||
*/
|
||||
void drm_framebuffer_remove(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
dev = fb->dev;
|
||||
|
||||
WARN_ON(!list_empty(&fb->filp_head));
|
||||
|
||||
/*
|
||||
* drm ABI mandates that we remove any deleted framebuffers from active
|
||||
* useage. But since most sane clients only remove framebuffers they no
|
||||
* longer need, try to optimize this away.
|
||||
*
|
||||
* Since we're holding a reference ourselves, observing a refcount of 1
|
||||
* means that we're the last holder and can skip it. Also, the refcount
|
||||
* can never increase from 1 again, so we don't need any barriers or
|
||||
* locks.
|
||||
*
|
||||
* Note that userspace could try to race with use and instate a new
|
||||
* usage _after_ we've cleared all current ones. End result will be an
|
||||
* in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
|
||||
* in this manner.
|
||||
*/
|
||||
if (drm_framebuffer_read_refcount(fb) > 1) {
|
||||
drm_modeset_lock_all(dev);
|
||||
/* remove from any CRTC */
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (crtc->primary->fb == fb) {
|
||||
/* should turn off the crtc */
|
||||
if (drm_crtc_force_disable(crtc))
|
||||
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
|
||||
}
|
||||
}
|
||||
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (plane->fb == fb)
|
||||
drm_plane_force_disable(plane);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
|
||||
drm_framebuffer_unreference(fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_remove);
|
|
@ -346,6 +346,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd,
|
|||
struct drm_stats __user *stats;
|
||||
int i, err;
|
||||
|
||||
memset(&s32, 0, sizeof(drm_stats32_t));
|
||||
stats = compat_alloc_user_space(sizeof(*stats));
|
||||
if (!stats)
|
||||
return -EFAULT;
|
||||
|
|
|
@ -713,10 +713,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
|
|||
* Negative value on error, failure or if not supported in current
|
||||
* video mode:
|
||||
*
|
||||
* -EINVAL - Invalid CRTC.
|
||||
* -EAGAIN - Temporary unavailable, e.g., called before initial modeset.
|
||||
* -ENOTSUPP - Function not supported in current display mode.
|
||||
* -EIO - Failed, e.g., due to failed scanout position query.
|
||||
* -EINVAL Invalid CRTC.
|
||||
* -EAGAIN Temporary unavailable, e.g., called before initial modeset.
|
||||
* -ENOTSUPP Function not supported in current display mode.
|
||||
* -EIO Failed, e.g., due to failed scanout position query.
|
||||
*
|
||||
* Returns or'ed positive status flags on success:
|
||||
*
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_dp_aux_dev.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
MODULE_AUTHOR("David Airlie, Jesse Barnes");
|
||||
MODULE_DESCRIPTION("DRM KMS helper");
|
||||
|
|
|
@ -657,6 +657,15 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
|
||||
|
||||
/**
|
||||
* drm_bus_flags_from_videomode - extract information about pixelclk and
|
||||
* DE polarity from videomode and store it in a separate variable
|
||||
* @vm: videomode structure to use
|
||||
* @bus_flags: information about pixelclk and DE polarity will be stored here
|
||||
*
|
||||
* Sets DRM_BUS_FLAG_DE_(LOW|HIGH) and DRM_BUS_FLAG_PIXDATA_(POS|NEG)EDGE
|
||||
* in @bus_flags according to DISPLAY_FLAGS found in @vm
|
||||
*/
|
||||
void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
|
||||
{
|
||||
*bus_flags = 0;
|
||||
|
@ -677,6 +686,7 @@ EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
|
|||
* of_get_drm_display_mode - get a drm_display_mode from devicetree
|
||||
* @np: device_node with the timing specification
|
||||
* @dmode: will be set to the return value
|
||||
* @bus_flags: information about pixelclk and DE polarity
|
||||
* @index: index into the list of display timings in devicetree
|
||||
*
|
||||
* This function is expensive and should only be used, if only one mode is to be
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
/**
|
||||
* DOC: aux kms helpers
|
||||
*
|
||||
* This helper library contains various one-off functions which don't really fit
|
||||
* anywhere else in the DRM modeset helper library.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_helper_move_panel_connectors_to_head() - move panels to the front in the
|
||||
* connector list
|
||||
* @dev: drm device to operate on
|
||||
*
|
||||
* Some userspace presumes that the first connected connector is the main
|
||||
* display, where it's supposed to display e.g. the login screen. For
|
||||
* laptops, this should be the main panel. Use this function to sort all
|
||||
* (eDP/LVDS) panels to the front of the connector list, instead of
|
||||
* painstakingly trying to initialize them in the right order.
|
||||
*/
|
||||
void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
|
||||
{
|
||||
struct drm_connector *connector, *tmp;
|
||||
struct list_head panel_list;
|
||||
|
||||
INIT_LIST_HEAD(&panel_list);
|
||||
|
||||
list_for_each_entry_safe(connector, tmp,
|
||||
&dev->mode_config.connector_list, head) {
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_eDP)
|
||||
list_move_tail(&connector->head, &panel_list);
|
||||
}
|
||||
|
||||
list_splice(&panel_list, &dev->mode_config.connector_list);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
|
||||
|
||||
/**
|
||||
* drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
|
||||
* @fb: drm_framebuffer object to fill out
|
||||
* @mode_cmd: metadata from the userspace fb creation request
|
||||
*
|
||||
* This helper can be used in a drivers fb_create callback to pre-fill the fb's
|
||||
* metadata fields.
|
||||
*/
|
||||
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
fb->width = mode_cmd->width;
|
||||
fb->height = mode_cmd->height;
|
||||
for (i = 0; i < 4; i++) {
|
||||
fb->pitches[i] = mode_cmd->pitches[i];
|
||||
fb->offsets[i] = mode_cmd->offsets[i];
|
||||
fb->modifier[i] = mode_cmd->modifier[i];
|
||||
}
|
||||
drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
|
||||
&fb->bits_per_pixel);
|
||||
fb->pixel_format = mode_cmd->pixel_format;
|
||||
fb->flags = mode_cmd->flags;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
|
||||
|
||||
/*
|
||||
* This is the minimal list of formats that seem to be safe for modeset use
|
||||
* with all current DRM drivers. Most hardware can actually support more
|
||||
* formats than this and drivers may specify a more accurate list when
|
||||
* creating the primary plane. However drivers that still call
|
||||
* drm_plane_init() will use this minimal format list as the default.
|
||||
*/
|
||||
static const uint32_t safe_modeset_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static struct drm_plane *create_primary_plane(struct drm_device *dev)
|
||||
{
|
||||
struct drm_plane *primary;
|
||||
int ret;
|
||||
|
||||
primary = kzalloc(sizeof(*primary), GFP_KERNEL);
|
||||
if (primary == NULL) {
|
||||
DRM_DEBUG_KMS("Failed to allocate primary plane\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the format_default field from drm_plane when dropping
|
||||
* this helper.
|
||||
*/
|
||||
primary->format_default = true;
|
||||
|
||||
/* possible_crtc's will be filled in later by crtc_init */
|
||||
ret = drm_universal_plane_init(dev, primary, 0,
|
||||
&drm_primary_helper_funcs,
|
||||
safe_modeset_formats,
|
||||
ARRAY_SIZE(safe_modeset_formats),
|
||||
DRM_PLANE_TYPE_PRIMARY, NULL);
|
||||
if (ret) {
|
||||
kfree(primary);
|
||||
primary = NULL;
|
||||
}
|
||||
|
||||
return primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_init - Legacy CRTC initialization function
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC object to init
|
||||
* @funcs: callbacks for the new CRTC
|
||||
*
|
||||
* Initialize a CRTC object with a default helper-provided primary plane and no
|
||||
* cursor plane.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs)
|
||||
{
|
||||
struct drm_plane *primary;
|
||||
|
||||
primary = create_primary_plane(dev);
|
||||
return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_init);
|
|
@ -63,18 +63,6 @@
|
|||
* the details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the minimal list of formats that seem to be safe for modeset use
|
||||
* with all current DRM drivers. Most hardware can actually support more
|
||||
* formats than this and drivers may specify a more accurate list when
|
||||
* creating the primary plane. However drivers that still call
|
||||
* drm_plane_init() will use this minimal format list as the default.
|
||||
*/
|
||||
static const uint32_t safe_modeset_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns the connectors currently associated with a CRTC. This function
|
||||
* should be called twice: once with a NULL connector list to retrieve
|
||||
|
@ -211,7 +199,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_state);
|
|||
* @crtc: owning CRTC of owning plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @src: source coordinates in 16.16 fixed point
|
||||
* @dest: integer destination coordinates
|
||||
* @dst: integer destination coordinates
|
||||
* @clip: integer clipping coordinates
|
||||
* @rotation: plane rotation
|
||||
* @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
|
||||
|
@ -438,60 +426,6 @@ const struct drm_plane_funcs drm_primary_helper_funcs = {
|
|||
};
|
||||
EXPORT_SYMBOL(drm_primary_helper_funcs);
|
||||
|
||||
static struct drm_plane *create_primary_plane(struct drm_device *dev)
|
||||
{
|
||||
struct drm_plane *primary;
|
||||
int ret;
|
||||
|
||||
primary = kzalloc(sizeof(*primary), GFP_KERNEL);
|
||||
if (primary == NULL) {
|
||||
DRM_DEBUG_KMS("Failed to allocate primary plane\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the format_default field from drm_plane when dropping
|
||||
* this helper.
|
||||
*/
|
||||
primary->format_default = true;
|
||||
|
||||
/* possible_crtc's will be filled in later by crtc_init */
|
||||
ret = drm_universal_plane_init(dev, primary, 0,
|
||||
&drm_primary_helper_funcs,
|
||||
safe_modeset_formats,
|
||||
ARRAY_SIZE(safe_modeset_formats),
|
||||
DRM_PLANE_TYPE_PRIMARY, NULL);
|
||||
if (ret) {
|
||||
kfree(primary);
|
||||
primary = NULL;
|
||||
}
|
||||
|
||||
return primary;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_init - Legacy CRTC initialization function
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC object to init
|
||||
* @funcs: callbacks for the new CRTC
|
||||
*
|
||||
* Initialize a CRTC object with a default helper-provided primary plane and no
|
||||
* cursor plane.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs)
|
||||
{
|
||||
struct drm_plane *primary;
|
||||
|
||||
primary = create_primary_plane(dev);
|
||||
return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
|
||||
NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_init);
|
||||
|
||||
int drm_plane_helper_commit(struct drm_plane *plane,
|
||||
struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *old_fb)
|
||||
|
|
|
@ -137,7 +137,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
|
|||
* @dev: DRM device
|
||||
* @pipe: simple display pipe object to initialize
|
||||
* @funcs: callbacks for the display pipe (optional)
|
||||
* @formats: array of supported formats (%DRM_FORMAT_*)
|
||||
* @formats: array of supported formats (DRM_FORMAT\_\*)
|
||||
* @format_count: number of elements in @formats
|
||||
* @connector: connector to attach and register
|
||||
*
|
||||
|
|
|
@ -488,8 +488,7 @@ static const struct file_operations fops = {
|
|||
};
|
||||
|
||||
static struct drm_driver etnaviv_drm_driver = {
|
||||
.driver_features = DRIVER_HAVE_IRQ |
|
||||
DRIVER_GEM |
|
||||
.driver_features = DRIVER_GEM |
|
||||
DRIVER_PRIME |
|
||||
DRIVER_RENDER,
|
||||
.open = etnaviv_open,
|
||||
|
@ -533,8 +532,6 @@ static int etnaviv_bind(struct device *dev)
|
|||
if (!drm)
|
||||
return -ENOMEM;
|
||||
|
||||
drm->platformdev = to_platform_device(dev);
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
dev_err(dev, "failed to allocate private data\n");
|
||||
|
|
|
@ -169,25 +169,10 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
|
|||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
fsl_dcu_drm_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
fsl_dcu_drm_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
|
||||
.atomic_check = fsl_dcu_drm_plane_atomic_check,
|
||||
.atomic_disable = fsl_dcu_drm_plane_atomic_disable,
|
||||
.atomic_update = fsl_dcu_drm_plane_atomic_update,
|
||||
.cleanup_fb = fsl_dcu_drm_plane_cleanup_fb,
|
||||
.prepare_fb = fsl_dcu_drm_plane_prepare_fb,
|
||||
};
|
||||
|
||||
static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
|
||||
|
|
|
@ -415,14 +415,6 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Didn't get an EDID, so
|
||||
* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
if (mode_dev->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
|
||||
|
|
|
@ -335,11 +335,6 @@ static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
|
|||
struct drm_display_mode *dup_mode = NULL;
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
|
||||
if (fixed_mode) {
|
||||
dev_dbg(dev->dev, "fixed_mode %dx%d\n",
|
||||
fixed_mode->hdisplay, fixed_mode->vdisplay);
|
||||
|
|
|
@ -530,15 +530,6 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Didn't get an EDID, so
|
||||
* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
|
||||
if (mode_dev->panel_fixed_mode != NULL) {
|
||||
struct drm_display_mode *mode =
|
||||
drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
|
||||
|
|
|
@ -608,15 +608,17 @@ static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
|
|||
u32 ch, u32 y, u32 in_h, u32 fmt)
|
||||
{
|
||||
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
char *format_name;
|
||||
u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
|
||||
u32 stride = fb->pitches[0];
|
||||
u32 addr = (u32)obj->paddr + y * stride;
|
||||
|
||||
DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
|
||||
ch + 1, y, in_h, stride, (u32)obj->paddr);
|
||||
format_name = drm_get_format_name(fb->pixel_format);
|
||||
DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n",
|
||||
addr, fb->width, fb->height, fmt,
|
||||
drm_get_format_name(fb->pixel_format));
|
||||
addr, fb->width, fb->height, fmt, format_name);
|
||||
kfree(format_name);
|
||||
|
||||
/* get reg offset */
|
||||
reg_ctrl = RD_CH_CTRL(ch);
|
||||
|
@ -815,19 +817,6 @@ static void ade_disable_channel(struct ade_plane *aplane)
|
|||
ade_compositor_routing_disable(base, ch);
|
||||
}
|
||||
|
||||
static int ade_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
{
|
||||
/* do nothing */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ade_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static int ade_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
|
@ -895,8 +884,6 @@ static void ade_plane_atomic_disable(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs ade_plane_helper_funcs = {
|
||||
.prepare_fb = ade_plane_prepare_fb,
|
||||
.cleanup_fb = ade_plane_cleanup_fb,
|
||||
.atomic_check = ade_plane_atomic_check,
|
||||
.atomic_update = ade_plane_atomic_update,
|
||||
.atomic_disable = ade_plane_atomic_disable,
|
||||
|
|
|
@ -169,7 +169,7 @@ static int kirin_gem_cma_dumb_create(struct drm_file *file,
|
|||
|
||||
static struct drm_driver kirin_drm_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
|
||||
DRIVER_ATOMIC | DRIVER_HAVE_IRQ,
|
||||
DRIVER_ATOMIC,
|
||||
.fops = &kirin_drm_fops,
|
||||
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
|
|
|
@ -3113,6 +3113,7 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
|
|||
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
|
||||
struct drm_plane_state *state;
|
||||
struct drm_plane *plane = &intel_plane->base;
|
||||
char *format_name;
|
||||
|
||||
if (!plane->state) {
|
||||
seq_puts(m, "plane->state is NULL!\n");
|
||||
|
@ -3121,6 +3122,12 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
|
|||
|
||||
state = plane->state;
|
||||
|
||||
if (state->fb) {
|
||||
format_name = drm_get_format_name(state->fb->pixel_format);
|
||||
} else {
|
||||
format_name = kstrdup("N/A", GFP_KERNEL);
|
||||
}
|
||||
|
||||
seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
|
||||
plane->base.id,
|
||||
plane_type(intel_plane->base.type),
|
||||
|
@ -3134,8 +3141,10 @@ static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
|
|||
((state->src_w & 0xffff) * 15625) >> 10,
|
||||
(state->src_h >> 16),
|
||||
((state->src_h & 0xffff) * 15625) >> 10,
|
||||
state->fb ? drm_get_format_name(state->fb->pixel_format) : "N/A",
|
||||
format_name,
|
||||
plane_rotation(state->rotation));
|
||||
|
||||
kfree(format_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,27 +156,27 @@ static int vgt_balloon_space(struct drm_mm *mm,
|
|||
* host point of view, the graphic address space is partitioned by multiple
|
||||
* vGPUs in different VMs. ::
|
||||
*
|
||||
* vGPU1 view Host view
|
||||
* 0 ------> +-----------+ +-----------+
|
||||
* ^ |###########| | vGPU3 |
|
||||
* | |###########| +-----------+
|
||||
* | |###########| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* mappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |###########| | |
|
||||
* v |###########| | Host |
|
||||
* +=======+===========+ +===========+
|
||||
* ^ |###########| | vGPU3 |
|
||||
* | |###########| +-----------+
|
||||
* | |###########| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* unmappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |###########| | |
|
||||
* | |###########| | Host |
|
||||
* v |###########| | |
|
||||
* total GM size ------> +-----------+ +-----------+
|
||||
* vGPU1 view Host view
|
||||
* 0 ------> +-----------+ +-----------+
|
||||
* ^ |###########| | vGPU3 |
|
||||
* | |###########| +-----------+
|
||||
* | |###########| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* mappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |###########| | |
|
||||
* v |###########| | Host |
|
||||
* +=======+===========+ +===========+
|
||||
* ^ |###########| | vGPU3 |
|
||||
* | |###########| +-----------+
|
||||
* | |###########| | vGPU2 |
|
||||
* | +-----------+ +-----------+
|
||||
* unmappable GM | available | ==> | vGPU1 |
|
||||
* | +-----------+ +-----------+
|
||||
* | |###########| | |
|
||||
* | |###########| | Host |
|
||||
* v |###########| | |
|
||||
* total GM size ------> +-----------+ +-----------+
|
||||
*
|
||||
* Returns:
|
||||
* zero on success, non-zero if configuration invalid or ballooning failed
|
||||
|
|
|
@ -143,6 +143,7 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
|
|||
crtc_state->base.enable ? crtc_state->pipe_src_h : 0;
|
||||
|
||||
if (state->fb && intel_rotation_90_or_270(state->rotation)) {
|
||||
char *format_name;
|
||||
if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
|
||||
state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) {
|
||||
DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
|
||||
|
@ -157,8 +158,9 @@ static int intel_plane_atomic_check(struct drm_plane *plane,
|
|||
switch (state->fb->pixel_format) {
|
||||
case DRM_FORMAT_C8:
|
||||
case DRM_FORMAT_RGB565:
|
||||
DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
|
||||
drm_get_format_name(state->fb->pixel_format));
|
||||
format_name = drm_get_format_name(state->fb->pixel_format);
|
||||
DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
|
|
|
@ -51,10 +51,10 @@
|
|||
* related registers. (The notable exception is the power management, not
|
||||
* covered here.)
|
||||
*
|
||||
* The struct i915_audio_component is used to interact between the graphics
|
||||
* and audio drivers. The struct i915_audio_component_ops *ops in it is
|
||||
* The struct &i915_audio_component is used to interact between the graphics
|
||||
* and audio drivers. The struct &i915_audio_component_ops @ops in it is
|
||||
* defined in graphics driver and called in audio driver. The
|
||||
* struct i915_audio_component_audio_ops *audio_ops is called from i915 driver.
|
||||
* struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver.
|
||||
*/
|
||||
|
||||
static const struct {
|
||||
|
|
|
@ -12258,6 +12258,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|||
|
||||
DRM_DEBUG_KMS("planes on this crtc\n");
|
||||
list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
|
||||
char *format_name;
|
||||
intel_plane = to_intel_plane(plane);
|
||||
if (intel_plane->pipe != crtc->pipe)
|
||||
continue;
|
||||
|
@ -12270,11 +12271,12 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|||
continue;
|
||||
}
|
||||
|
||||
format_name = drm_get_format_name(fb->pixel_format);
|
||||
|
||||
DRM_DEBUG_KMS("[PLANE:%d:%s] enabled",
|
||||
plane->base.id, plane->name);
|
||||
DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s",
|
||||
fb->base.id, fb->width, fb->height,
|
||||
drm_get_format_name(fb->pixel_format));
|
||||
fb->base.id, fb->width, fb->height, format_name);
|
||||
DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
|
||||
state->scaler_id,
|
||||
state->base.src.x1 >> 16,
|
||||
|
@ -12284,6 +12286,8 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
|
|||
state->base.dst.x1, state->base.dst.y1,
|
||||
drm_rect_width(&state->base.dst),
|
||||
drm_rect_height(&state->base.dst));
|
||||
|
||||
kfree(format_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13972,7 +13976,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {
|
|||
*/
|
||||
int
|
||||
intel_prepare_plane_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_framebuffer *fb = new_state->fb;
|
||||
|
@ -14054,7 +14058,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
|
|||
*/
|
||||
void
|
||||
intel_cleanup_plane_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct intel_plane_state *old_intel_state;
|
||||
|
@ -14911,6 +14915,7 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
unsigned int aligned_height;
|
||||
int ret;
|
||||
u32 pitch_limit, stride_alignment;
|
||||
char *format_name;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
|
||||
|
@ -14985,16 +14990,18 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
break;
|
||||
case DRM_FORMAT_XRGB1555:
|
||||
if (INTEL_INFO(dev)->gen > 3) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
INTEL_INFO(dev)->gen < 9) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
@ -15002,15 +15009,17 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
if (INTEL_INFO(dev)->gen < 4) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
@ -15019,14 +15028,16 @@ static int intel_framebuffer_init(struct drm_device *dev,
|
|||
case DRM_FORMAT_YVYU:
|
||||
case DRM_FORMAT_VYUY:
|
||||
if (INTEL_INFO(dev)->gen < 5) {
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("unsupported pixel format: %s\n",
|
||||
drm_get_format_name(mode_cmd->pixel_format));
|
||||
format_name = drm_get_format_name(mode_cmd->pixel_format);
|
||||
DRM_DEBUG("unsupported pixel format: %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -1225,9 +1225,9 @@ void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe);
|
|||
void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe);
|
||||
void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe);
|
||||
int intel_prepare_plane_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state);
|
||||
struct drm_plane_state *new_state);
|
||||
void intel_cleanup_plane_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state);
|
||||
struct drm_plane_state *old_state);
|
||||
int intel_plane_atomic_get_property(struct drm_plane *plane,
|
||||
const struct drm_plane_state *state,
|
||||
struct drm_property *property,
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
*
|
||||
* +-------------------------------+
|
||||
* | guc_css_header |
|
||||
* | |
|
||||
* | contains major/minor version |
|
||||
* +-------------------------------+
|
||||
* | uCode |
|
||||
|
@ -176,10 +177,10 @@
|
|||
*
|
||||
* 1. Header, uCode and RSA are must-have components.
|
||||
* 2. All firmware components, if they present, are in the sequence illustrated
|
||||
* in the layout table above.
|
||||
* in the layout table above.
|
||||
* 3. Length info of each component can be found in header, in dwords.
|
||||
* 4. Modulus and exponent key are not required by driver. They may not appear
|
||||
* in fw. So driver will load a truncated firmware in this case.
|
||||
* in fw. So driver will load a truncated firmware in this case.
|
||||
*/
|
||||
|
||||
struct guc_css_header {
|
||||
|
|
|
@ -1054,17 +1054,6 @@ void intel_lvds_init(struct drm_device *dev)
|
|||
}
|
||||
lvds_connector->base.edid = edid;
|
||||
|
||||
if (IS_ERR_OR_NULL(edid)) {
|
||||
/* Didn't get an EDID, so
|
||||
* Set wide sync ranges so we get all modes
|
||||
* handed to valid_mode for checking
|
||||
*/
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
}
|
||||
|
||||
list_for_each_entry(scan, &connector->probed_modes, head) {
|
||||
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
DRM_DEBUG_KMS("using preferred mode from EDID: ");
|
||||
|
|
|
@ -183,8 +183,10 @@ static int mgag200fb_create(struct drm_fb_helper *helper,
|
|||
}
|
||||
|
||||
sysram = vmalloc(size);
|
||||
if (!sysram)
|
||||
if (!sysram) {
|
||||
ret = -ENOMEM;
|
||||
goto err_sysram;
|
||||
}
|
||||
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
|
|
|
@ -99,7 +99,7 @@ static const struct drm_plane_funcs mdp4_plane_funcs = {
|
|||
};
|
||||
|
||||
static int mdp4_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
|
||||
struct mdp4_kms *mdp4_kms = get_kms(plane);
|
||||
|
@ -113,7 +113,7 @@ static int mdp4_plane_prepare_fb(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
|
||||
struct mdp4_kms *mdp4_kms = get_kms(plane);
|
||||
|
|
|
@ -250,7 +250,7 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
|
|||
};
|
||||
|
||||
static int mdp5_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
||||
|
@ -264,7 +264,7 @@ static int mdp5_plane_prepare_fb(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
|
||||
struct mdp5_kms *mdp5_kms = get_kms(plane);
|
||||
|
|
|
@ -60,7 +60,7 @@ to_omap_plane_state(struct drm_plane_state *state)
|
|||
}
|
||||
|
||||
static int omap_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
if (!new_state->fb)
|
||||
return 0;
|
||||
|
@ -69,7 +69,7 @@ static int omap_plane_prepare_fb(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static void omap_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
if (old_state->fb)
|
||||
omap_framebuffer_unpin(old_state->fb);
|
||||
|
|
|
@ -1154,6 +1154,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
u32 tmp, viewport_w, viewport_h;
|
||||
int r;
|
||||
bool bypass_lut = false;
|
||||
char *format_name;
|
||||
|
||||
/* no fb bound */
|
||||
if (!atomic && !crtc->primary->fb) {
|
||||
|
@ -1257,8 +1258,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
bypass_lut = true;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen format %s\n",
|
||||
drm_get_format_name(target_fb->pixel_format));
|
||||
format_name = drm_get_format_name(target_fb->pixel_format);
|
||||
DRM_ERROR("Unsupported screen format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1469,6 +1471,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
u32 viewport_w, viewport_h;
|
||||
int r;
|
||||
bool bypass_lut = false;
|
||||
char *format_name;
|
||||
|
||||
/* no fb bound */
|
||||
if (!atomic && !crtc->primary->fb) {
|
||||
|
@ -1558,8 +1561,9 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
|
|||
bypass_lut = true;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Unsupported screen format %s\n",
|
||||
drm_get_format_name(target_fb->pixel_format));
|
||||
format_name = drm_get_format_name(target_fb->pixel_format);
|
||||
DRM_ERROR("Unsupported screen format %s\n", format_name);
|
||||
kfree(format_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -445,7 +445,6 @@ static struct platform_driver rockchip_dp_driver = {
|
|||
.remove = rockchip_dp_remove,
|
||||
.driver = {
|
||||
.name = "rockchip-dp",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &rockchip_dp_pm_ops,
|
||||
.of_match_table = of_match_ptr(rockchip_dp_dt_ids),
|
||||
},
|
||||
|
|
|
@ -238,7 +238,7 @@ static enum vop_data_format vop_convert_format(uint32_t format)
|
|||
case DRM_FORMAT_NV24:
|
||||
return VOP_FMT_YUV444SP;
|
||||
default:
|
||||
DRM_ERROR("unsupport format[%08x]\n", format);
|
||||
DRM_ERROR("unsupported format[%08x]\n", format);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
|
|||
int vskiplines = 0;
|
||||
|
||||
if (dst_w > 3840) {
|
||||
DRM_ERROR("Maximum destination width (3840) exceeded\n");
|
||||
DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -353,11 +353,11 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
|
|||
VOP_SCL_SET_EXT(vop, win, lb_mode, lb_mode);
|
||||
if (lb_mode == LB_RGB_3840X2) {
|
||||
if (yrgb_ver_scl_mode != SCALE_NONE) {
|
||||
DRM_ERROR("ERROR : not allow yrgb ver scale\n");
|
||||
DRM_DEV_ERROR(vop->dev, "not allow yrgb ver scale\n");
|
||||
return;
|
||||
}
|
||||
if (cbcr_ver_scl_mode != SCALE_NONE) {
|
||||
DRM_ERROR("ERROR : not allow cbcr ver scale\n");
|
||||
DRM_DEV_ERROR(vop->dev, "not allow cbcr ver scale\n");
|
||||
return;
|
||||
}
|
||||
vsu_mode = SCALE_UP_BIL;
|
||||
|
@ -428,7 +428,7 @@ static void vop_dsp_hold_valid_irq_disable(struct vop *vop)
|
|||
spin_unlock_irqrestore(&vop->irq_lock, flags);
|
||||
}
|
||||
|
||||
static void vop_enable(struct drm_crtc *crtc)
|
||||
static int vop_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct vop *vop = to_vop(crtc);
|
||||
int ret;
|
||||
|
@ -436,26 +436,20 @@ static void vop_enable(struct drm_crtc *crtc)
|
|||
ret = pm_runtime_get_sync(vop->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(vop->dev, "failed to get pm runtime: %d\n", ret);
|
||||
return;
|
||||
goto err_put_pm_runtime;
|
||||
}
|
||||
|
||||
ret = clk_enable(vop->hclk);
|
||||
if (ret < 0) {
|
||||
dev_err(vop->dev, "failed to enable hclk - %d\n", ret);
|
||||
return;
|
||||
}
|
||||
if (WARN_ON(ret < 0))
|
||||
goto err_put_pm_runtime;
|
||||
|
||||
ret = clk_enable(vop->dclk);
|
||||
if (ret < 0) {
|
||||
dev_err(vop->dev, "failed to enable dclk - %d\n", ret);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto err_disable_hclk;
|
||||
}
|
||||
|
||||
ret = clk_enable(vop->aclk);
|
||||
if (ret < 0) {
|
||||
dev_err(vop->dev, "failed to enable aclk - %d\n", ret);
|
||||
if (WARN_ON(ret < 0))
|
||||
goto err_disable_dclk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Slave iommu shares power, irq and clock with vop. It was associated
|
||||
|
@ -485,7 +479,7 @@ static void vop_enable(struct drm_crtc *crtc)
|
|||
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
err_disable_aclk:
|
||||
clk_disable(vop->aclk);
|
||||
|
@ -493,6 +487,9 @@ static void vop_enable(struct drm_crtc *crtc)
|
|||
clk_disable(vop->dclk);
|
||||
err_disable_hclk:
|
||||
clk_disable(vop->hclk);
|
||||
err_put_pm_runtime:
|
||||
pm_runtime_put_sync(vop->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vop_crtc_disable(struct drm_crtc *crtc)
|
||||
|
@ -567,7 +564,7 @@ static void vop_plane_destroy(struct drm_plane *plane)
|
|||
}
|
||||
|
||||
static int vop_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
if (plane->state->fb)
|
||||
drm_framebuffer_reference(plane->state->fb);
|
||||
|
@ -576,7 +573,7 @@ static int vop_plane_prepare_fb(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static void vop_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state)
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
if (old_state->fb)
|
||||
drm_framebuffer_unreference(old_state->fb);
|
||||
|
@ -912,10 +909,16 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
|||
u16 vact_st = adjusted_mode->vtotal - adjusted_mode->vsync_start;
|
||||
u16 vact_end = vact_st + vdisplay;
|
||||
uint32_t val;
|
||||
int ret;
|
||||
|
||||
WARN_ON(vop->event);
|
||||
|
||||
vop_enable(crtc);
|
||||
ret = vop_enable(crtc);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If dclk rate is zero, mean that scanout is stop,
|
||||
* we don't need wait any more.
|
||||
|
@ -970,7 +973,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
|
|||
VOP_CTRL_SET(vop, mipi_en, 1);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("unsupport connector_type[%d]\n", s->output_type);
|
||||
DRM_DEV_ERROR(vop->dev, "unsupported connector_type [%d]\n",
|
||||
s->output_type);
|
||||
}
|
||||
VOP_CTRL_SET(vop, out_mode, s->output_mode);
|
||||
|
||||
|
@ -1154,7 +1158,8 @@ static irqreturn_t vop_isr(int irq, void *data)
|
|||
|
||||
/* Unhandled irqs are spurious. */
|
||||
if (active_irqs)
|
||||
DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs);
|
||||
DRM_DEV_ERROR(vop->dev, "Unknown VOP IRQs: %#02x\n",
|
||||
active_irqs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1189,7 +1194,8 @@ static int vop_create_crtc(struct vop *vop)
|
|||
win_data->phy->nformats,
|
||||
win_data->type, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize plane\n");
|
||||
DRM_DEV_ERROR(vop->dev, "failed to init plane %d\n",
|
||||
ret);
|
||||
goto err_cleanup_planes;
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1233,8 @@ static int vop_create_crtc(struct vop *vop)
|
|||
win_data->phy->nformats,
|
||||
win_data->type, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to initialize overlay plane\n");
|
||||
DRM_DEV_ERROR(vop->dev, "failed to init overlay %d\n",
|
||||
ret);
|
||||
goto err_cleanup_crtc;
|
||||
}
|
||||
drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
|
||||
|
@ -1235,8 +1242,8 @@ static int vop_create_crtc(struct vop *vop)
|
|||
|
||||
port = of_get_child_by_name(dev->of_node, "port");
|
||||
if (!port) {
|
||||
DRM_ERROR("no port node found in %s\n",
|
||||
dev->of_node->full_name);
|
||||
DRM_DEV_ERROR(vop->dev, "no port node found in %s\n",
|
||||
dev->of_node->full_name);
|
||||
ret = -ENOENT;
|
||||
goto err_cleanup_crtc;
|
||||
}
|
||||
|
|
|
@ -305,7 +305,6 @@ static struct platform_driver vop_platform_driver = {
|
|||
.remove = vop_remove,
|
||||
.driver = {
|
||||
.name = "rockchip-vop",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(vop_driver_dt_match),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1001,15 +1001,9 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_
|
|||
cmdbuf->cmd_addr = kcmd_addr;
|
||||
}
|
||||
if (cmdbuf->vb_size) {
|
||||
kvb_addr = kmalloc(cmdbuf->vb_size, GFP_KERNEL);
|
||||
if (kvb_addr == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (copy_from_user(kvb_addr, cmdbuf->vb_addr,
|
||||
cmdbuf->vb_size)) {
|
||||
ret = -EFAULT;
|
||||
kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size);
|
||||
if (IS_ERR(kvb_addr)) {
|
||||
ret = PTR_ERR(kvb_addr);
|
||||
goto done;
|
||||
}
|
||||
cmdbuf->vb_addr = kvb_addr;
|
||||
|
|
|
@ -282,7 +282,7 @@ static const struct file_operations sti_driver_fops = {
|
|||
};
|
||||
|
||||
static struct drm_driver sti_driver = {
|
||||
.driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET |
|
||||
.driver_features = DRIVER_MODESET |
|
||||
DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
|
|
|
@ -480,17 +480,6 @@ static const struct drm_plane_funcs tegra_primary_plane_funcs = {
|
|||
.atomic_destroy_state = tegra_plane_atomic_destroy_state,
|
||||
};
|
||||
|
||||
static int tegra_plane_prepare_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_plane_cleanup_fb(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_fb)
|
||||
{
|
||||
}
|
||||
|
||||
static int tegra_plane_state_add(struct tegra_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
|
@ -624,8 +613,6 @@ static void tegra_plane_atomic_disable(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = {
|
||||
.prepare_fb = tegra_plane_prepare_fb,
|
||||
.cleanup_fb = tegra_plane_cleanup_fb,
|
||||
.atomic_check = tegra_plane_atomic_check,
|
||||
.atomic_update = tegra_plane_atomic_update,
|
||||
.atomic_disable = tegra_plane_atomic_disable,
|
||||
|
@ -796,8 +783,6 @@ static const struct drm_plane_funcs tegra_cursor_plane_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = {
|
||||
.prepare_fb = tegra_plane_prepare_fb,
|
||||
.cleanup_fb = tegra_plane_cleanup_fb,
|
||||
.atomic_check = tegra_cursor_atomic_check,
|
||||
.atomic_update = tegra_cursor_atomic_update,
|
||||
.atomic_disable = tegra_cursor_atomic_disable,
|
||||
|
@ -866,8 +851,6 @@ static const uint32_t tegra_overlay_plane_formats[] = {
|
|||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs tegra_overlay_plane_helper_funcs = {
|
||||
.prepare_fb = tegra_plane_prepare_fb,
|
||||
.cleanup_fb = tegra_plane_cleanup_fb,
|
||||
.atomic_check = tegra_plane_atomic_check,
|
||||
.atomic_update = tegra_plane_atomic_update,
|
||||
.atomic_disable = tegra_plane_atomic_disable,
|
||||
|
|
|
@ -150,8 +150,5 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
|
|||
drm_connector_register(connector);
|
||||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev->mode_config.dirty_info_property,
|
||||
1);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
|
||||
#define BULK_SIZE 512
|
||||
|
||||
#define NR_USB_REQUEST_CHANNEL 0x12
|
||||
|
||||
#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
|
||||
#define WRITES_IN_FLIGHT (4)
|
||||
#define MAX_VENDOR_DESCRIPTOR_SIZE 256
|
||||
|
@ -90,6 +92,26 @@ static int udl_parse_vendor_descriptor(struct drm_device *dev,
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Need to ensure a channel is selected before submitting URBs
|
||||
*/
|
||||
static int udl_select_std_channel(struct udl_device *udl)
|
||||
{
|
||||
int ret;
|
||||
u8 set_def_chn[] = {0x57, 0xCD, 0xDC, 0xA7,
|
||||
0x1C, 0x88, 0x5E, 0x15,
|
||||
0x60, 0xFE, 0xC6, 0x97,
|
||||
0x16, 0x3D, 0x47, 0xF2};
|
||||
|
||||
ret = usb_control_msg(udl->udev,
|
||||
usb_sndctrlpipe(udl->udev, 0),
|
||||
NR_USB_REQUEST_CHANNEL,
|
||||
(USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
|
||||
set_def_chn, sizeof(set_def_chn),
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
return ret < 0 ? ret : 0;
|
||||
}
|
||||
|
||||
static void udl_release_urb_work(struct work_struct *work)
|
||||
{
|
||||
struct urb_node *unode = container_of(work, struct urb_node,
|
||||
|
@ -301,6 +323,9 @@ int udl_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (udl_select_std_channel(udl))
|
||||
DRM_ERROR("Selecting channel failed\n");
|
||||
|
||||
if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
|
||||
DRM_ERROR("udl_alloc_urb_list failed\n");
|
||||
goto err;
|
||||
|
|
|
@ -441,8 +441,6 @@ int udl_modeset_init(struct drm_device *dev)
|
|||
|
||||
dev->mode_config.funcs = &udl_mode_funcs;
|
||||
|
||||
drm_mode_create_dirty_info_property(dev);
|
||||
|
||||
udl_crtc_init(dev);
|
||||
|
||||
encoder = udl_encoder_init(dev);
|
||||
|
|
|
@ -735,8 +735,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs vc4_plane_helper_funcs = {
|
||||
.prepare_fb = NULL,
|
||||
.cleanup_fb = NULL,
|
||||
.atomic_check = vc4_plane_atomic_check,
|
||||
.atomic_update = vc4_plane_atomic_update,
|
||||
};
|
||||
|
|
|
@ -152,15 +152,10 @@ static int virtio_gpu_execbuffer(struct drm_device *dev,
|
|||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
buf = kmalloc(exbuf->size, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out_unresv;
|
||||
}
|
||||
if (copy_from_user(buf, (void __user *)(uintptr_t)exbuf->command,
|
||||
exbuf->size)) {
|
||||
kfree(buf);
|
||||
ret = -EFAULT;
|
||||
buf = memdup_user((void __user *)(uintptr_t)exbuf->command,
|
||||
exbuf->size);
|
||||
if (IS_ERR(buf)) {
|
||||
ret = PTR_ERR(buf);
|
||||
goto out_unresv;
|
||||
}
|
||||
virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
|
||||
|
|
|
@ -376,9 +376,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
|
|||
|
||||
drm_mode_crtc_set_gamma_size(crtc, 256);
|
||||
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev->mode_config.dirty_info_property,
|
||||
1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev_priv->hotplug_mode_update_property, 1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
|
@ -421,10 +418,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
|
|||
if (ret != 0)
|
||||
goto err_free;
|
||||
|
||||
ret = drm_mode_create_dirty_info_property(dev);
|
||||
if (ret != 0)
|
||||
goto err_vblank_cleanup;
|
||||
|
||||
vmw_kms_create_implicit_placement_property(dev_priv, true);
|
||||
|
||||
if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
|
||||
|
@ -439,8 +432,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
|
|||
|
||||
return 0;
|
||||
|
||||
err_vblank_cleanup:
|
||||
drm_vblank_cleanup(dev);
|
||||
err_free:
|
||||
kfree(dev_priv->ldu_priv);
|
||||
dev_priv->ldu_priv = NULL;
|
||||
|
|
|
@ -537,9 +537,6 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
|
|||
|
||||
drm_mode_crtc_set_gamma_size(crtc, 256);
|
||||
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev->mode_config.dirty_info_property,
|
||||
1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev_priv->hotplug_mode_update_property, 1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
|
@ -574,10 +571,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
|||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
||||
ret = drm_mode_create_dirty_info_property(dev);
|
||||
if (unlikely(ret != 0))
|
||||
goto err_vblank_cleanup;
|
||||
|
||||
vmw_kms_create_implicit_placement_property(dev_priv, false);
|
||||
|
||||
for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
|
||||
|
@ -588,10 +581,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
|||
DRM_INFO("Screen Objects Display Unit initialized\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_vblank_cleanup:
|
||||
drm_vblank_cleanup(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vmw_kms_sou_close_display(struct vmw_private *dev_priv)
|
||||
|
|
|
@ -1130,9 +1130,6 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
|
|||
|
||||
drm_mode_crtc_set_gamma_size(crtc, 256);
|
||||
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev->mode_config.dirty_info_property,
|
||||
1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
dev_priv->hotplug_mode_update_property, 1);
|
||||
drm_object_attach_property(&connector->base,
|
||||
|
@ -1202,10 +1199,6 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
|
|||
if (unlikely(ret != 0))
|
||||
return ret;
|
||||
|
||||
ret = drm_mode_create_dirty_info_property(dev);
|
||||
if (unlikely(ret != 0))
|
||||
goto err_vblank_cleanup;
|
||||
|
||||
dev_priv->active_display_unit = vmw_du_screen_target;
|
||||
|
||||
vmw_kms_create_implicit_placement_property(dev_priv, false);
|
||||
|
|
|
@ -131,7 +131,24 @@ static struct vga_device *vgadev_find(struct pci_dev *pdev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the default VGA device (vgacon's babe) */
|
||||
/**
|
||||
* vga_default_device - return the default VGA device, for vgacon
|
||||
*
|
||||
* This can be defined by the platform. The default implementation
|
||||
* is rather dumb and will probably only work properly on single
|
||||
* vga card setups and/or x86 platforms.
|
||||
*
|
||||
* If your VGA default device is not PCI, you'll have to return
|
||||
* NULL here. In this case, I assume it will not conflict with
|
||||
* any PCI card. If this is not true, I'll have to define two archs
|
||||
* hooks for enabling/disabling the VGA default device if that is
|
||||
* possible. This may be a problem with real _ISA_ VGA cards, in
|
||||
* addition to a PCI one. I don't know at this point how to deal
|
||||
* with that card. Can theirs IOs be disabled at all ? If not, then
|
||||
* I suppose it's a matter of having the proper arch hook telling
|
||||
* us about it, so we basically never allow anybody to succeed a
|
||||
* vga_get()...
|
||||
*/
|
||||
struct pci_dev *vga_default_device(void)
|
||||
{
|
||||
return vga_default;
|
||||
|
@ -356,6 +373,40 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
|
|||
wake_up_all(&vga_wait_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* vga_get - acquire & locks VGA resources
|
||||
* @pdev: pci device of the VGA card or NULL for the system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
* @interruptible: blocking should be interruptible by signals ?
|
||||
*
|
||||
* This function acquires VGA resources for the given card and mark those
|
||||
* resources locked. If the resource 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 accesses are
|
||||
* enabled on the card (including VGA forwarding on parent P2P bridges if any).
|
||||
*
|
||||
* This 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). You can indicate
|
||||
* whether this blocking should be interruptible by a signal (for userland
|
||||
* interface) or not.
|
||||
*
|
||||
* Must not be called at interrupt time or in atomic context. If the card
|
||||
* already owns the resources, the function succeeds. Nested calls are
|
||||
* supported (a per-resource counter is maintained)
|
||||
*
|
||||
* On success, release the VGA resource again with vga_put().
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
|
||||
{
|
||||
struct vga_device *vgadev, *conflict;
|
||||
|
@ -408,6 +459,21 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
|
|||
}
|
||||
EXPORT_SYMBOL(vga_get);
|
||||
|
||||
/**
|
||||
* vga_tryget - try to acquire & lock legacy VGA resources
|
||||
* @pdev: pci devivce of VGA card or NULL for system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
*
|
||||
* This function performs the same operation as vga_get(), but will return an
|
||||
* error (-EBUSY) instead of blocking if the resources are already locked by
|
||||
* another card. It can be called in any context
|
||||
*
|
||||
* On success, release the VGA resource again with vga_put().
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
|
||||
{
|
||||
struct vga_device *vgadev;
|
||||
|
@ -435,6 +501,16 @@ int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
|
|||
}
|
||||
EXPORT_SYMBOL(vga_tryget);
|
||||
|
||||
/**
|
||||
* vga_put - release lock on legacy VGA resources
|
||||
* @pdev: pci device of VGA card or NULL for system default
|
||||
* @rsrc: but mask of resource to release
|
||||
*
|
||||
* This fuction releases resources previously locked by vga_get() or
|
||||
* vga_tryget(). The resources aren't disabled right away, so that a subsequence
|
||||
* vga_get() on the same card will succeed immediately. Resources have a
|
||||
* counter, so locks are only released if the counter reaches 0.
|
||||
*/
|
||||
void vga_put(struct pci_dev *pdev, unsigned int rsrc)
|
||||
{
|
||||
struct vga_device *vgadev;
|
||||
|
@ -716,7 +792,37 @@ void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes)
|
|||
}
|
||||
EXPORT_SYMBOL(vga_set_legacy_decoding);
|
||||
|
||||
/* call with NULL to unregister */
|
||||
/**
|
||||
* vga_client_register - register or unregister a VGA arbitration client
|
||||
* @pdev: pci device of the VGA client
|
||||
* @cookie: client cookie to be used in callbacks
|
||||
* @irq_set_state: irq state change callback
|
||||
* @set_vga_decode: vga decode change callback
|
||||
*
|
||||
* Clients have two callback mechanisms they can use.
|
||||
*
|
||||
* @irq_set_state callback: If a client can't disable its GPUs VGA
|
||||
* resources, then we need to be able to ask it to turn off its irqs when we
|
||||
* turn off its mem and io decoding.
|
||||
*
|
||||
* @set_vga_decode callback: If a client can disable its GPU VGA resource, it
|
||||
* will get a callback from this to set the encode/decode state.
|
||||
*
|
||||
* Rationale: we cannot disable VGA decode resources unconditionally some single
|
||||
* GPU laptops seem to require ACPI or BIOS access to the VGA registers to
|
||||
* control things like backlights etc. Hopefully newer multi-GPU laptops do
|
||||
* something saner, and desktops won't have any special ACPI for this. The
|
||||
* driver will get a callback when VGA arbitration is first used by userspace
|
||||
* since some older X servers have issues.
|
||||
*
|
||||
* This function does not check whether a client for @pdev has been registered
|
||||
* already.
|
||||
*
|
||||
* To unregister just call this function with @irq_set_state and @set_vga_decode
|
||||
* both set to NULL for the same @pdev as originally used to register them.
|
||||
*
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int vga_client_register(struct pci_dev *pdev, void *cookie,
|
||||
void (*irq_set_state)(void *cookie, bool state),
|
||||
unsigned int (*set_vga_decode)(void *cookie,
|
||||
|
|
|
@ -127,6 +127,7 @@ struct dma_buf_attachment;
|
|||
* run-time by echoing the debug value in its sysfs node:
|
||||
* # echo 0xf > /sys/module/drm/parameters/debug
|
||||
*/
|
||||
#define DRM_UT_NONE 0x00
|
||||
#define DRM_UT_CORE 0x01
|
||||
#define DRM_UT_DRIVER 0x02
|
||||
#define DRM_UT_KMS 0x04
|
||||
|
@ -134,11 +135,15 @@ struct dma_buf_attachment;
|
|||
#define DRM_UT_ATOMIC 0x10
|
||||
#define DRM_UT_VBL 0x20
|
||||
|
||||
extern __printf(2, 3)
|
||||
void drm_ut_debug_printk(const char *function_name,
|
||||
const char *format, ...);
|
||||
extern __printf(1, 2)
|
||||
void drm_err(const char *format, ...);
|
||||
extern __printf(6, 7)
|
||||
void drm_dev_printk(const struct device *dev, const char *level,
|
||||
unsigned int category, const char *function_name,
|
||||
const char *prefix, const char *format, ...);
|
||||
|
||||
extern __printf(5, 6)
|
||||
void drm_printk(const char *level, unsigned int category,
|
||||
const char *function_name, const char *prefix,
|
||||
const char *format, ...);
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name DRM template customization defaults */
|
||||
|
@ -169,8 +174,12 @@ void drm_err(const char *format, ...);
|
|||
* \param fmt printf() like format string.
|
||||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_ERROR(fmt, ...) \
|
||||
drm_err(fmt, ##__VA_ARGS__)
|
||||
#define DRM_DEV_ERROR(dev, fmt, ...) \
|
||||
drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
|
||||
fmt, ##__VA_ARGS__)
|
||||
#define DRM_ERROR(fmt, ...) \
|
||||
drm_printk(KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*", fmt, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
||||
|
@ -178,21 +187,33 @@ void drm_err(const char *format, ...);
|
|||
* \param fmt printf() like format string.
|
||||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_ERROR_RATELIMITED(fmt, ...) \
|
||||
#define DRM_DEV_ERROR_RATELIMITED(dev, fmt, ...) \
|
||||
({ \
|
||||
static DEFINE_RATELIMIT_STATE(_rs, \
|
||||
DEFAULT_RATELIMIT_INTERVAL, \
|
||||
DEFAULT_RATELIMIT_BURST); \
|
||||
\
|
||||
if (__ratelimit(&_rs)) \
|
||||
drm_err(fmt, ##__VA_ARGS__); \
|
||||
DRM_DEV_ERROR(dev, fmt, ##__VA_ARGS__); \
|
||||
})
|
||||
#define DRM_ERROR_RATELIMITED(fmt, ...) \
|
||||
DRM_DEV_ERROR_RATELIMITED(NULL, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_INFO(fmt, ...) \
|
||||
printk(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
|
||||
#define DRM_DEV_INFO(dev, fmt, ...) \
|
||||
drm_dev_printk(dev, KERN_INFO, DRM_UT_NONE, __func__, "", fmt, \
|
||||
##__VA_ARGS__)
|
||||
#define DRM_INFO(fmt, ...) \
|
||||
drm_printk(KERN_INFO, DRM_UT_NONE, __func__, "", fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_INFO_ONCE(fmt, ...) \
|
||||
printk_once(KERN_INFO "[" DRM_NAME "] " fmt, ##__VA_ARGS__)
|
||||
#define DRM_DEV_INFO_ONCE(dev, fmt, ...) \
|
||||
({ \
|
||||
static bool __print_once __read_mostly; \
|
||||
if (!__print_once) { \
|
||||
__print_once = true; \
|
||||
DRM_DEV_INFO(dev, fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
})
|
||||
#define DRM_INFO_ONCE(fmt, ...) DRM_DEV_INFO_ONCE(NULL, fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Debug output.
|
||||
|
@ -200,52 +221,51 @@ void drm_err(const char *format, ...);
|
|||
* \param fmt printf() like format string.
|
||||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_DEV_DEBUG(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_CORE)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
drm_printk(KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, ##args)
|
||||
|
||||
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_DRIVER(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_KMS(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_KMS)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_PRIME(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_PRIME)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_ATOMIC(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_ATOMIC)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
#define DRM_DEBUG_VBL(fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_VBL)) \
|
||||
drm_ut_debug_printk(__func__, fmt, ##args); \
|
||||
} while (0)
|
||||
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, __func__, "", fmt, ##args)
|
||||
|
||||
#define _DRM_DEFINE_DEBUG_RATELIMITED(level, fmt, args...) \
|
||||
do { \
|
||||
if (unlikely(drm_debug & DRM_UT_ ## level)) { \
|
||||
static DEFINE_RATELIMIT_STATE( \
|
||||
_rs, \
|
||||
DEFAULT_RATELIMIT_INTERVAL, \
|
||||
DEFAULT_RATELIMIT_BURST); \
|
||||
\
|
||||
if (__ratelimit(&_rs)) { \
|
||||
drm_ut_debug_printk(__func__, fmt, \
|
||||
##args); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG_KMS(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, ##args)
|
||||
|
||||
#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_PRIME(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_PRIME, __func__, "", fmt, ##args)
|
||||
|
||||
#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_ATOMIC(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", fmt, ##args)
|
||||
|
||||
#define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG_VBL(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, ##args)
|
||||
|
||||
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
|
||||
({ \
|
||||
static DEFINE_RATELIMIT_STATE(_rs, \
|
||||
DEFAULT_RATELIMIT_INTERVAL, \
|
||||
DEFAULT_RATELIMIT_BURST); \
|
||||
if (__ratelimit(&_rs)) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ ## level, \
|
||||
__func__, "", fmt, ##args); \
|
||||
})
|
||||
|
||||
/**
|
||||
* Rate limited debug output. Like DRM_DEBUG() but won't flood the log.
|
||||
|
@ -253,14 +273,22 @@ void drm_err(const char *format, ...);
|
|||
* \param fmt printf() like format string.
|
||||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_DEV_DEBUG_RATELIMITED(dev, fmt, args...) \
|
||||
DEV__DRM_DEFINE_DEBUG_RATELIMITED(dev, CORE, fmt, ##args)
|
||||
#define DRM_DEBUG_RATELIMITED(fmt, args...) \
|
||||
_DRM_DEFINE_DEBUG_RATELIMITED(CORE, fmt, ##args)
|
||||
DRM_DEV_DEBUG_RATELIMITED(NULL, fmt, ##args)
|
||||
#define DRM_DEV_DEBUG_DRIVER_RATELIMITED(dev, fmt, args...) \
|
||||
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, DRIVER, fmt, ##args)
|
||||
#define DRM_DEBUG_DRIVER_RATELIMITED(fmt, args...) \
|
||||
_DRM_DEFINE_DEBUG_RATELIMITED(DRIVER, fmt, ##args)
|
||||
DRM_DEV_DEBUG_DRIVER_RATELIMITED(NULL, fmt, ##args)
|
||||
#define DRM_DEV_DEBUG_KMS_RATELIMITED(dev, fmt, args...) \
|
||||
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, KMS, fmt, ##args)
|
||||
#define DRM_DEBUG_KMS_RATELIMITED(fmt, args...) \
|
||||
_DRM_DEFINE_DEBUG_RATELIMITED(KMS, fmt, ##args)
|
||||
DRM_DEV_DEBUG_KMS_RATELIMITED(NULL, fmt, ##args)
|
||||
#define DRM_DEV_DEBUG_PRIME_RATELIMITED(dev, fmt, args...) \
|
||||
_DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, PRIME, fmt, ##args)
|
||||
#define DRM_DEBUG_PRIME_RATELIMITED(fmt, args...) \
|
||||
_DRM_DEFINE_DEBUG_RATELIMITED(PRIME, fmt, ##args)
|
||||
DRM_DEV_DEBUG_PRIME_RATELIMITED(NULL, fmt, ##args)
|
||||
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define DRM_ATOMIC_HELPER_H_
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
|
||||
struct drm_atomic_state;
|
||||
|
||||
|
|
|
@ -0,0 +1,747 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_CONNECTOR_H__
|
||||
#define __DRM_CONNECTOR_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <drm/drm_modeset.h>
|
||||
|
||||
struct drm_connector_helper_funcs;
|
||||
struct drm_device;
|
||||
struct drm_crtc;
|
||||
struct drm_encoder;
|
||||
struct drm_property;
|
||||
struct drm_property_blob;
|
||||
struct edid;
|
||||
|
||||
enum drm_connector_force {
|
||||
DRM_FORCE_UNSPECIFIED,
|
||||
DRM_FORCE_OFF,
|
||||
DRM_FORCE_ON, /* force on analog part normally */
|
||||
DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
|
||||
};
|
||||
|
||||
/**
|
||||
* enum drm_connector_status - status for a &drm_connector
|
||||
*
|
||||
* This enum is used to track the connector status. There are no separate
|
||||
* #defines for the uapi!
|
||||
*/
|
||||
enum drm_connector_status {
|
||||
/**
|
||||
* @connector_status_connected: The connector is definitely connected to
|
||||
* a sink device, and can be enabled.
|
||||
*/
|
||||
connector_status_connected = 1,
|
||||
/**
|
||||
* @connector_status_disconnected: The connector isn't connected to a
|
||||
* sink device which can be autodetect. For digital outputs like DP or
|
||||
* HDMI (which can be realiable probed) this means there's really
|
||||
* nothing there. It is driver-dependent whether a connector with this
|
||||
* status can be lit up or not.
|
||||
*/
|
||||
connector_status_disconnected = 2,
|
||||
/**
|
||||
* @connector_status_unknown: The connector's status could not be
|
||||
* reliably detected. This happens when probing would either cause
|
||||
* flicker (like load-detection when the connector is in use), or when a
|
||||
* hardware resource isn't available (like when load-detection needs a
|
||||
* free CRTC). It should be possible to light up the connector with one
|
||||
* of the listed fallback modes. For default configuration userspace
|
||||
* should only try to light up connectors with unknown status when
|
||||
* there's not connector with @connector_status_connected.
|
||||
*/
|
||||
connector_status_unknown = 3,
|
||||
};
|
||||
|
||||
enum subpixel_order {
|
||||
SubPixelUnknown = 0,
|
||||
SubPixelHorizontalRGB,
|
||||
SubPixelHorizontalBGR,
|
||||
SubPixelVerticalRGB,
|
||||
SubPixelVerticalBGR,
|
||||
SubPixelNone,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_display_info - runtime data about the connected sink
|
||||
*
|
||||
* Describes a given display (e.g. CRT or flat panel) and its limitations. For
|
||||
* fixed display sinks like built-in panels there's not much difference between
|
||||
* this and struct &drm_connector. But for sinks with a real cable this
|
||||
* structure is meant to describe all the things at the other end of the cable.
|
||||
*
|
||||
* For sinks which provide an EDID this can be filled out by calling
|
||||
* drm_add_edid_modes().
|
||||
*/
|
||||
struct drm_display_info {
|
||||
/**
|
||||
* @name: Name of the display.
|
||||
*/
|
||||
char name[DRM_DISPLAY_INFO_LEN];
|
||||
|
||||
/**
|
||||
* @width_mm: Physical width in mm.
|
||||
*/
|
||||
unsigned int width_mm;
|
||||
/**
|
||||
* @height_mm: Physical height in mm.
|
||||
*/
|
||||
unsigned int height_mm;
|
||||
|
||||
/**
|
||||
* @pixel_clock: Maximum pixel clock supported by the sink, in units of
|
||||
* 100Hz. This mismatches the clok in &drm_display_mode (which is in
|
||||
* kHZ), because that's what the EDID uses as base unit.
|
||||
*/
|
||||
unsigned int pixel_clock;
|
||||
/**
|
||||
* @bpc: Maximum bits per color channel. Used by HDMI and DP outputs.
|
||||
*/
|
||||
unsigned int bpc;
|
||||
|
||||
/**
|
||||
* @subpixel_order: Subpixel order of LCD panels.
|
||||
*/
|
||||
enum subpixel_order subpixel_order;
|
||||
|
||||
#define DRM_COLOR_FORMAT_RGB444 (1<<0)
|
||||
#define DRM_COLOR_FORMAT_YCRCB444 (1<<1)
|
||||
#define DRM_COLOR_FORMAT_YCRCB422 (1<<2)
|
||||
|
||||
/**
|
||||
* @color_formats: HDMI Color formats, selects between RGB and YCrCb
|
||||
* modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones
|
||||
* as used to describe the pixel format in framebuffers, and also don't
|
||||
* match the formats in @bus_formats which are shared with v4l.
|
||||
*/
|
||||
u32 color_formats;
|
||||
|
||||
/**
|
||||
* @bus_formats: Pixel data format on the wire, somewhat redundant with
|
||||
* @color_formats. Array of size @num_bus_formats encoded using
|
||||
* MEDIA_BUS_FMT\_ defines shared with v4l and media drivers.
|
||||
*/
|
||||
const u32 *bus_formats;
|
||||
/**
|
||||
* @num_bus_formats: Size of @bus_formats array.
|
||||
*/
|
||||
unsigned int num_bus_formats;
|
||||
|
||||
#define DRM_BUS_FLAG_DE_LOW (1<<0)
|
||||
#define DRM_BUS_FLAG_DE_HIGH (1<<1)
|
||||
/* drive data on pos. edge */
|
||||
#define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2)
|
||||
/* drive data on neg. edge */
|
||||
#define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3)
|
||||
|
||||
/**
|
||||
* @bus_flags: Additional information (like pixel signal polarity) for
|
||||
* the pixel data on the bus, using DRM_BUS_FLAGS\_ defines.
|
||||
*/
|
||||
u32 bus_flags;
|
||||
|
||||
/**
|
||||
* @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
|
||||
* more stuff redundant with @bus_formats.
|
||||
*/
|
||||
u8 edid_hdmi_dc_modes;
|
||||
|
||||
/**
|
||||
* @cea_rev: CEA revision of the HDMI sink.
|
||||
*/
|
||||
u8 cea_rev;
|
||||
};
|
||||
|
||||
int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
||||
const u32 *formats,
|
||||
unsigned int num_formats);
|
||||
|
||||
/**
|
||||
* struct drm_connector_state - mutable connector state
|
||||
* @connector: backpointer to the connector
|
||||
* @crtc: CRTC to connect connector to, NULL if disabled
|
||||
* @best_encoder: can be used by helpers and drivers to select the encoder
|
||||
* @state: backpointer to global drm_atomic_state
|
||||
*/
|
||||
struct drm_connector_state {
|
||||
struct drm_connector *connector;
|
||||
|
||||
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
|
||||
|
||||
struct drm_encoder *best_encoder;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_connector_funcs - control connectors on a given device
|
||||
*
|
||||
* Each CRTC may have one or more connectors attached to it. The functions
|
||||
* below allow the core DRM code to control connectors, enumerate available modes,
|
||||
* etc.
|
||||
*/
|
||||
struct drm_connector_funcs {
|
||||
/**
|
||||
* @dpms:
|
||||
*
|
||||
* Legacy entry point to set the per-connector DPMS state. Legacy DPMS
|
||||
* is exposed as a standard property on the connector, but diverted to
|
||||
* this callback in the drm core. Note that atomic drivers don't
|
||||
* implement the 4 level DPMS support on the connector any more, but
|
||||
* instead only have an on/off "ACTIVE" property on the CRTC object.
|
||||
*
|
||||
* Drivers implementing atomic modeset should use
|
||||
* drm_atomic_helper_connector_dpms() to implement this hook.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*dpms)(struct drm_connector *connector, int mode);
|
||||
|
||||
/**
|
||||
* @reset:
|
||||
*
|
||||
* Reset connector hardware and software state to off. This function isn't
|
||||
* called by the core directly, only through drm_mode_config_reset().
|
||||
* It's not a helper hook only for historical reasons.
|
||||
*
|
||||
* Atomic drivers can use drm_atomic_helper_connector_reset() to reset
|
||||
* atomic state using this hook.
|
||||
*/
|
||||
void (*reset)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @detect:
|
||||
*
|
||||
* Check to see if anything is attached to the connector. The parameter
|
||||
* force is set to false whilst polling, true when checking the
|
||||
* connector due to a user request. force can be used by the driver to
|
||||
* avoid expensive, destructive operations during automated probing.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Note that this hook is only called by the probe helper. It's not in
|
||||
* the helper library vtable purely for historical reasons. The only DRM
|
||||
* core entry point to probe connector state is @fill_modes.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* drm_connector_status indicating the connector's status.
|
||||
*/
|
||||
enum drm_connector_status (*detect)(struct drm_connector *connector,
|
||||
bool force);
|
||||
|
||||
/**
|
||||
* @force:
|
||||
*
|
||||
* This function is called to update internal encoder state when the
|
||||
* connector is forced to a certain state by userspace, either through
|
||||
* the sysfs interfaces or on the kernel cmdline. In that case the
|
||||
* @detect callback isn't called.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Note that this hook is only called by the probe helper. It's not in
|
||||
* the helper library vtable purely for historical reasons. The only DRM
|
||||
* core entry point to probe connector state is @fill_modes.
|
||||
*/
|
||||
void (*force)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @fill_modes:
|
||||
*
|
||||
* Entry point for output detection and basic mode validation. The
|
||||
* driver should reprobe the output if needed (e.g. when hotplug
|
||||
* handling is unreliable), add all detected modes to connector->modes
|
||||
* and filter out any the device can't support in any configuration. It
|
||||
* also needs to filter out any modes wider or higher than the
|
||||
* parameters max_width and max_height indicate.
|
||||
*
|
||||
* The drivers must also prune any modes no longer valid from
|
||||
* connector->modes. Furthermore it must update connector->status and
|
||||
* connector->edid. If no EDID has been received for this output
|
||||
* connector->edid must be NULL.
|
||||
*
|
||||
* Drivers using the probe helpers should use
|
||||
* drm_helper_probe_single_connector_modes() or
|
||||
* drm_helper_probe_single_connector_modes_nomerge() to implement this
|
||||
* function.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* The number of modes detected and filled into connector->modes.
|
||||
*/
|
||||
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
|
||||
|
||||
/**
|
||||
* @set_property:
|
||||
*
|
||||
* This is the legacy entry point to update a property attached to the
|
||||
* connector.
|
||||
*
|
||||
* Drivers implementing atomic modeset should use
|
||||
* drm_atomic_helper_connector_set_property() to implement this hook.
|
||||
*
|
||||
* This callback is optional if the driver does not support any legacy
|
||||
* driver-private properties.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*set_property)(struct drm_connector *connector, struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
/**
|
||||
* @late_register:
|
||||
*
|
||||
* This optional hook can be used to register additional userspace
|
||||
* interfaces attached to the connector, light backlight control, i2c,
|
||||
* DP aux or similar interfaces. It is called late in the driver load
|
||||
* sequence from drm_connector_register() when registering all the
|
||||
* core drm connector interfaces. Everything added from this callback
|
||||
* should be unregistered in the early_unregister callback.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int (*late_register)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @early_unregister:
|
||||
*
|
||||
* This optional hook should be used to unregister the additional
|
||||
* userspace interfaces attached to the connector from
|
||||
* late_unregister(). It is called from drm_connector_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @destroy:
|
||||
*
|
||||
* Clean up connector resources. This is called at driver unload time
|
||||
* through drm_mode_config_cleanup(). It can also be called at runtime
|
||||
* when a connector is being hot-unplugged for drivers that support
|
||||
* connector hotplugging (e.g. DisplayPort MST).
|
||||
*/
|
||||
void (*destroy)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @atomic_duplicate_state:
|
||||
*
|
||||
* Duplicate the current atomic state for this connector and return it.
|
||||
* The core and helpers gurantee that any atomic state duplicated with
|
||||
* this hook and still owned by the caller (i.e. not transferred to the
|
||||
* driver by calling ->atomic_commit() from struct
|
||||
* &drm_mode_config_funcs) will be cleaned up by calling the
|
||||
* @atomic_destroy_state hook in this structure.
|
||||
*
|
||||
* Atomic drivers which don't subclass struct &drm_connector_state should use
|
||||
* drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
|
||||
* state structure to extend it with driver-private state should use
|
||||
* __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
|
||||
* duplicated in a consistent fashion across drivers.
|
||||
*
|
||||
* It is an error to call this hook before connector->state has been
|
||||
* initialized correctly.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* If the duplicate state references refcounted resources this hook must
|
||||
* acquire a reference for each of them. The driver must release these
|
||||
* references again in @atomic_destroy_state.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* Duplicated atomic state or NULL when the allocation failed.
|
||||
*/
|
||||
struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @atomic_destroy_state:
|
||||
*
|
||||
* Destroy a state duplicated with @atomic_duplicate_state and release
|
||||
* or unreference all resources it references
|
||||
*/
|
||||
void (*atomic_destroy_state)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
|
||||
/**
|
||||
* @atomic_set_property:
|
||||
*
|
||||
* Decode a driver-private property value and store the decoded value
|
||||
* into the passed-in state structure. Since the atomic core decodes all
|
||||
* standardized properties (even for extensions beyond the core set of
|
||||
* properties which might not be implemented by all drivers) this
|
||||
* requires drivers to subclass the state structure.
|
||||
*
|
||||
* Such driver-private properties should really only be implemented for
|
||||
* truly hardware/vendor specific state. Instead it is preferred to
|
||||
* standardize atomic extension and decode the properties used to expose
|
||||
* such an extension in the core.
|
||||
*
|
||||
* Do not call this function directly, use
|
||||
* drm_atomic_connector_set_property() instead.
|
||||
*
|
||||
* This callback is optional if the driver does not support any
|
||||
* driver-private atomic properties.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This function is called in the state assembly phase of atomic
|
||||
* modesets, which can be aborted for any reason (including on
|
||||
* userspace's request to just check whether a configuration would be
|
||||
* possible). Drivers MUST NOT touch any persistent state (hardware or
|
||||
* software) or data structures except the passed in @state parameter.
|
||||
*
|
||||
* Also since userspace controls in which order properties are set this
|
||||
* function must not do any input validation (since the state update is
|
||||
* incomplete and hence likely inconsistent). Instead any such input
|
||||
* validation must be done in the various atomic_check callbacks.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 if the property has been found, -EINVAL if the property isn't
|
||||
* implemented by the driver (which shouldn't ever happen, the core only
|
||||
* asks for properties attached to this connector). No other validation
|
||||
* is allowed by the driver. The core already checks that the property
|
||||
* value is within the range (integer, valid enum value, ...) the driver
|
||||
* set when registering the property.
|
||||
*/
|
||||
int (*atomic_set_property)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
/**
|
||||
* @atomic_get_property:
|
||||
*
|
||||
* Reads out the decoded driver-private property. This is used to
|
||||
* implement the GETCONNECTOR IOCTL.
|
||||
*
|
||||
* Do not call this function directly, use
|
||||
* drm_atomic_connector_get_property() instead.
|
||||
*
|
||||
* This callback is optional if the driver does not support any
|
||||
* driver-private atomic properties.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success, -EINVAL if the property isn't implemented by the
|
||||
* driver (which shouldn't ever happen, the core only asks for
|
||||
* properties attached to this connector).
|
||||
*/
|
||||
int (*atomic_get_property)(struct drm_connector *connector,
|
||||
const struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t *val);
|
||||
};
|
||||
|
||||
/* mode specified on the command line */
|
||||
struct drm_cmdline_mode {
|
||||
bool specified;
|
||||
bool refresh_specified;
|
||||
bool bpp_specified;
|
||||
int xres, yres;
|
||||
int bpp;
|
||||
int refresh;
|
||||
bool rb;
|
||||
bool interlace;
|
||||
bool cvt;
|
||||
bool margins;
|
||||
enum drm_connector_force force;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_connector - central DRM connector control structure
|
||||
* @dev: parent DRM device
|
||||
* @kdev: kernel device for sysfs attributes
|
||||
* @attr: sysfs attributes
|
||||
* @head: list management
|
||||
* @base: base KMS object
|
||||
* @name: human readable name, can be overwritten by the driver
|
||||
* @connector_type: one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
|
||||
* @connector_type_id: index into connector type enum
|
||||
* @interlace_allowed: can this connector handle interlaced modes?
|
||||
* @doublescan_allowed: can this connector handle doublescan?
|
||||
* @stereo_allowed: can this connector handle stereo modes?
|
||||
* @registered: is this connector exposed (registered) with userspace?
|
||||
* @modes: modes available on this connector (from fill_modes() + user)
|
||||
* @status: one of the drm_connector_status enums (connected, not, or unknown)
|
||||
* @probed_modes: list of modes derived directly from the display
|
||||
* @funcs: connector control functions
|
||||
* @edid_blob_ptr: DRM property containing EDID if present
|
||||
* @properties: property tracking for this connector
|
||||
* @dpms: current dpms state
|
||||
* @helper_private: mid-layer private data
|
||||
* @cmdline_mode: mode line parsed from the kernel cmdline for this connector
|
||||
* @force: a DRM_FORCE_<foo> state for forced mode sets
|
||||
* @override_edid: has the EDID been overwritten through debugfs for testing?
|
||||
* @encoder_ids: valid encoders for this connector
|
||||
* @encoder: encoder driving this connector, if any
|
||||
* @eld: EDID-like data, if present
|
||||
* @dvi_dual: dual link DVI, if found
|
||||
* @max_tmds_clock: max clock rate, if found
|
||||
* @latency_present: AV delay info from ELD, if found
|
||||
* @video_latency: video latency info from ELD, if found
|
||||
* @audio_latency: audio latency info from ELD, if found
|
||||
* @null_edid_counter: track sinks that give us all zeros for the EDID
|
||||
* @bad_edid_counter: track sinks that give us an EDID with invalid checksum
|
||||
* @edid_corrupt: indicates whether the last read EDID was corrupt
|
||||
* @debugfs_entry: debugfs directory for this connector
|
||||
* @state: current atomic state for this connector
|
||||
* @has_tile: is this connector connected to a tiled monitor
|
||||
* @tile_group: tile group for the connected monitor
|
||||
* @tile_is_single_monitor: whether the tile is one monitor housing
|
||||
* @num_h_tile: number of horizontal tiles in the tile group
|
||||
* @num_v_tile: number of vertical tiles in the tile group
|
||||
* @tile_h_loc: horizontal location of this tile
|
||||
* @tile_v_loc: vertical location of this tile
|
||||
* @tile_h_size: horizontal size of this tile.
|
||||
* @tile_v_size: vertical size of this tile.
|
||||
*
|
||||
* Each connector may be connected to one or more CRTCs, or may be clonable by
|
||||
* another connector if they can share a CRTC. Each connector also has a specific
|
||||
* position in the broader display (referred to as a 'screen' though it could
|
||||
* span multiple monitors).
|
||||
*/
|
||||
struct drm_connector {
|
||||
struct drm_device *dev;
|
||||
struct device *kdev;
|
||||
struct device_attribute *attr;
|
||||
struct list_head head;
|
||||
|
||||
struct drm_mode_object base;
|
||||
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* @index: Compacted connector index, which matches the position inside
|
||||
* the mode_config.list for drivers not supporting hot-add/removing. Can
|
||||
* be used as an array index. It is invariant over the lifetime of the
|
||||
* connector.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
int connector_type;
|
||||
int connector_type_id;
|
||||
bool interlace_allowed;
|
||||
bool doublescan_allowed;
|
||||
bool stereo_allowed;
|
||||
bool registered;
|
||||
struct list_head modes; /* list of modes on this connector */
|
||||
|
||||
enum drm_connector_status status;
|
||||
|
||||
/* these are modes added by probing with DDC or the BIOS */
|
||||
struct list_head probed_modes;
|
||||
|
||||
/**
|
||||
* @display_info: Display information is filled from EDID information
|
||||
* when a display is detected. For non hot-pluggable displays such as
|
||||
* flat panels in embedded systems, the driver should initialize the
|
||||
* display_info.width_mm and display_info.height_mm fields with the
|
||||
* physical size of the display.
|
||||
*/
|
||||
struct drm_display_info display_info;
|
||||
const struct drm_connector_funcs *funcs;
|
||||
|
||||
struct drm_property_blob *edid_blob_ptr;
|
||||
struct drm_object_properties properties;
|
||||
|
||||
/**
|
||||
* @path_blob_ptr:
|
||||
*
|
||||
* DRM blob property data for the DP MST path property.
|
||||
*/
|
||||
struct drm_property_blob *path_blob_ptr;
|
||||
|
||||
/**
|
||||
* @tile_blob_ptr:
|
||||
*
|
||||
* DRM blob property data for the tile property (used mostly by DP MST).
|
||||
* This is meant for screens which are driven through separate display
|
||||
* pipelines represented by &drm_crtc, which might not be running with
|
||||
* genlocked clocks. For tiled panels which are genlocked, like
|
||||
* dual-link LVDS or dual-link DSI, the driver should try to not expose
|
||||
* the tiling and virtualize both &drm_crtc and &drm_plane if needed.
|
||||
*/
|
||||
struct drm_property_blob *tile_blob_ptr;
|
||||
|
||||
/* should we poll this connector for connects and disconnects */
|
||||
/* hot plug detectable */
|
||||
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
|
||||
/* poll for connections */
|
||||
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
|
||||
/* can cleanly poll for disconnections without flickering the screen */
|
||||
/* DACs should rarely do this without a lot of testing */
|
||||
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
|
||||
|
||||
/**
|
||||
* @polled:
|
||||
*
|
||||
* Connector polling mode, a combination of
|
||||
*
|
||||
* DRM_CONNECTOR_POLL_HPD
|
||||
* The connector generates hotplug events and doesn't need to be
|
||||
* periodically polled. The CONNECT and DISCONNECT flags must not
|
||||
* be set together with the HPD flag.
|
||||
*
|
||||
* DRM_CONNECTOR_POLL_CONNECT
|
||||
* Periodically poll the connector for connection.
|
||||
*
|
||||
* DRM_CONNECTOR_POLL_DISCONNECT
|
||||
* Periodically poll the connector for disconnection.
|
||||
*
|
||||
* Set to 0 for connectors that don't support connection status
|
||||
* discovery.
|
||||
*/
|
||||
uint8_t polled;
|
||||
|
||||
/* requested DPMS state */
|
||||
int dpms;
|
||||
|
||||
const struct drm_connector_helper_funcs *helper_private;
|
||||
|
||||
/* forced on connector */
|
||||
struct drm_cmdline_mode cmdline_mode;
|
||||
enum drm_connector_force force;
|
||||
bool override_edid;
|
||||
|
||||
#define DRM_CONNECTOR_MAX_ENCODER 3
|
||||
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
||||
struct drm_encoder *encoder; /* currently active encoder */
|
||||
|
||||
#define MAX_ELD_BYTES 128
|
||||
/* EDID bits */
|
||||
uint8_t eld[MAX_ELD_BYTES];
|
||||
bool dvi_dual;
|
||||
int max_tmds_clock; /* in MHz */
|
||||
bool latency_present[2];
|
||||
int video_latency[2]; /* [0]: progressive, [1]: interlaced */
|
||||
int audio_latency[2];
|
||||
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
|
||||
unsigned bad_edid_counter;
|
||||
|
||||
/* Flag for raw EDID header corruption - used in Displayport
|
||||
* compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
|
||||
*/
|
||||
bool edid_corrupt;
|
||||
|
||||
struct dentry *debugfs_entry;
|
||||
|
||||
struct drm_connector_state *state;
|
||||
|
||||
/* DisplayID bits */
|
||||
bool has_tile;
|
||||
struct drm_tile_group *tile_group;
|
||||
bool tile_is_single_monitor;
|
||||
|
||||
uint8_t num_h_tile, num_v_tile;
|
||||
uint8_t tile_h_loc, tile_v_loc;
|
||||
uint16_t tile_h_size, tile_v_size;
|
||||
};
|
||||
|
||||
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
|
||||
|
||||
int drm_connector_init(struct drm_device *dev,
|
||||
struct drm_connector *connector,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type);
|
||||
int drm_connector_register(struct drm_connector *connector);
|
||||
void drm_connector_unregister(struct drm_connector *connector);
|
||||
int drm_mode_connector_attach_encoder(struct drm_connector *connector,
|
||||
struct drm_encoder *encoder);
|
||||
|
||||
void drm_connector_cleanup(struct drm_connector *connector);
|
||||
static inline unsigned drm_connector_index(struct drm_connector *connector)
|
||||
{
|
||||
return connector->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_lookup - lookup connector object
|
||||
* @dev: DRM device
|
||||
* @id: connector object id
|
||||
*
|
||||
* This function looks up the connector object specified by id
|
||||
* add takes a reference to it.
|
||||
*/
|
||||
static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
|
||||
uint32_t id)
|
||||
{
|
||||
struct drm_mode_object *mo;
|
||||
mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
|
||||
return mo ? obj_to_connector(mo) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_reference - incr the connector refcnt
|
||||
* @connector: connector
|
||||
*
|
||||
* This function increments the connector's refcount.
|
||||
*/
|
||||
static inline void drm_connector_reference(struct drm_connector *connector)
|
||||
{
|
||||
drm_mode_object_reference(&connector->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_unreference - unref a connector
|
||||
* @connector: connector to unref
|
||||
*
|
||||
* This function decrements the connector's refcount and frees it if it drops to zero.
|
||||
*/
|
||||
static inline void drm_connector_unreference(struct drm_connector *connector)
|
||||
{
|
||||
drm_mode_object_unreference(&connector->base);
|
||||
}
|
||||
|
||||
const char *drm_get_connector_status_name(enum drm_connector_status status);
|
||||
const char *drm_get_subpixel_order_name(enum subpixel_order order);
|
||||
const char *drm_get_dpms_name(int val);
|
||||
const char *drm_get_dvi_i_subconnector_name(int val);
|
||||
const char *drm_get_dvi_i_select_name(int val);
|
||||
const char *drm_get_tv_subconnector_name(int val);
|
||||
const char *drm_get_tv_select_name(int val);
|
||||
|
||||
int drm_mode_create_dvi_i_properties(struct drm_device *dev);
|
||||
int drm_mode_create_tv_properties(struct drm_device *dev,
|
||||
unsigned int num_modes,
|
||||
const char * const modes[]);
|
||||
int drm_mode_create_scaling_mode_property(struct drm_device *dev);
|
||||
int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
|
||||
int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
|
||||
|
||||
int drm_mode_connector_set_path_property(struct drm_connector *connector,
|
||||
const char *path);
|
||||
int drm_mode_connector_set_tile_property(struct drm_connector *connector);
|
||||
int drm_mode_connector_update_edid_property(struct drm_connector *connector,
|
||||
const struct edid *edid);
|
||||
#endif
|
|
@ -36,40 +36,19 @@
|
|||
#include <uapi/drm/drm_fourcc.h>
|
||||
#include <drm/drm_modeset_lock.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_modeset.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_connector.h>
|
||||
|
||||
struct drm_device;
|
||||
struct drm_mode_set;
|
||||
struct drm_framebuffer;
|
||||
struct drm_object_properties;
|
||||
struct drm_file;
|
||||
struct drm_clip_rect;
|
||||
struct device_node;
|
||||
struct fence;
|
||||
struct edid;
|
||||
|
||||
struct drm_mode_object {
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
struct drm_object_properties *properties;
|
||||
struct kref refcount;
|
||||
void (*free_cb)(struct kref *kref);
|
||||
};
|
||||
|
||||
#define DRM_OBJECT_MAX_PROPERTY 24
|
||||
struct drm_object_properties {
|
||||
int count, atomic_count;
|
||||
/* NOTE: if we ever start dynamically destroying properties (ie.
|
||||
* not at drm_mode_config_cleanup() time), then we'd have to do
|
||||
* a better job of detaching property from mode objects to avoid
|
||||
* dangling property pointers:
|
||||
*/
|
||||
struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
|
||||
/* do not read/write values directly, but use drm_object_property_get_value()
|
||||
* and drm_object_property_set_value():
|
||||
*/
|
||||
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
|
||||
};
|
||||
|
||||
static inline int64_t U642I64(uint64_t val)
|
||||
{
|
||||
return (int64_t)*((int64_t *)&val);
|
||||
|
@ -94,70 +73,6 @@ static inline uint64_t I642U64(int64_t val)
|
|||
#define DRM_REFLECT_Y BIT(5)
|
||||
#define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
|
||||
|
||||
enum drm_connector_force {
|
||||
DRM_FORCE_UNSPECIFIED,
|
||||
DRM_FORCE_OFF,
|
||||
DRM_FORCE_ON, /* force on analog part normally */
|
||||
DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
|
||||
};
|
||||
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
enum drm_connector_status {
|
||||
connector_status_connected = 1,
|
||||
connector_status_disconnected = 2,
|
||||
connector_status_unknown = 3,
|
||||
};
|
||||
|
||||
enum subpixel_order {
|
||||
SubPixelUnknown = 0,
|
||||
SubPixelHorizontalRGB,
|
||||
SubPixelHorizontalBGR,
|
||||
SubPixelVerticalRGB,
|
||||
SubPixelVerticalBGR,
|
||||
SubPixelNone,
|
||||
};
|
||||
|
||||
#define DRM_COLOR_FORMAT_RGB444 (1<<0)
|
||||
#define DRM_COLOR_FORMAT_YCRCB444 (1<<1)
|
||||
#define DRM_COLOR_FORMAT_YCRCB422 (1<<2)
|
||||
|
||||
#define DRM_BUS_FLAG_DE_LOW (1<<0)
|
||||
#define DRM_BUS_FLAG_DE_HIGH (1<<1)
|
||||
/* drive data on pos. edge */
|
||||
#define DRM_BUS_FLAG_PIXDATA_POSEDGE (1<<2)
|
||||
/* drive data on neg. edge */
|
||||
#define DRM_BUS_FLAG_PIXDATA_NEGEDGE (1<<3)
|
||||
|
||||
/*
|
||||
* Describes a given display (e.g. CRT or flat panel) and its limitations.
|
||||
*/
|
||||
struct drm_display_info {
|
||||
char name[DRM_DISPLAY_INFO_LEN];
|
||||
|
||||
/* Physical size */
|
||||
unsigned int width_mm;
|
||||
unsigned int height_mm;
|
||||
|
||||
/* Clock limits FIXME: storage format */
|
||||
unsigned int min_vfreq, max_vfreq;
|
||||
unsigned int min_hfreq, max_hfreq;
|
||||
unsigned int pixel_clock;
|
||||
unsigned int bpc;
|
||||
|
||||
enum subpixel_order subpixel_order;
|
||||
u32 color_formats;
|
||||
|
||||
const u32 *bus_formats;
|
||||
unsigned int num_bus_formats;
|
||||
u32 bus_flags;
|
||||
|
||||
/* Mask of supported hdmi deep color modes */
|
||||
u8 edid_hdmi_dc_modes;
|
||||
|
||||
u8 cea_rev;
|
||||
};
|
||||
|
||||
/* data corresponds to displayid vend/prod/serial */
|
||||
struct drm_tile_group {
|
||||
struct kref refcount;
|
||||
|
@ -166,101 +81,6 @@ struct drm_tile_group {
|
|||
u8 group_data[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_framebuffer_funcs - framebuffer hooks
|
||||
*/
|
||||
struct drm_framebuffer_funcs {
|
||||
/**
|
||||
* @destroy:
|
||||
*
|
||||
* Clean up framebuffer resources, specifically also unreference the
|
||||
* backing storage. The core guarantees to call this function for every
|
||||
* framebuffer successfully created by ->fb_create() in
|
||||
* &drm_mode_config_funcs. Drivers must also call
|
||||
* drm_framebuffer_cleanup() to release DRM core resources for this
|
||||
* framebuffer.
|
||||
*/
|
||||
void (*destroy)(struct drm_framebuffer *framebuffer);
|
||||
|
||||
/**
|
||||
* @create_handle:
|
||||
*
|
||||
* Create a buffer handle in the driver-specific buffer manager (either
|
||||
* GEM or TTM) valid for the passed-in struct &drm_file. This is used by
|
||||
* the core to implement the GETFB IOCTL, which returns (for
|
||||
* sufficiently priviledged user) also a native buffer handle. This can
|
||||
* be used for seamless transitions between modesetting clients by
|
||||
* copying the current screen contents to a private buffer and blending
|
||||
* between that and the new contents.
|
||||
*
|
||||
* GEM based drivers should call drm_gem_handle_create() to create the
|
||||
* handle.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*create_handle)(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle);
|
||||
/**
|
||||
* @dirty:
|
||||
*
|
||||
* Optional callback for the dirty fb IOCTL.
|
||||
*
|
||||
* Userspace can notify the driver via this callback that an area of the
|
||||
* framebuffer has changed and should be flushed to the display
|
||||
* hardware. This can also be used internally, e.g. by the fbdev
|
||||
* emulation, though that's not the case currently.
|
||||
*
|
||||
* See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
|
||||
* for more information as all the semantics and arguments have a one to
|
||||
* one mapping on this function.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*dirty)(struct drm_framebuffer *framebuffer,
|
||||
struct drm_file *file_priv, unsigned flags,
|
||||
unsigned color, struct drm_clip_rect *clips,
|
||||
unsigned num_clips);
|
||||
};
|
||||
|
||||
struct drm_framebuffer {
|
||||
struct drm_device *dev;
|
||||
/*
|
||||
* Note that the fb is refcounted for the benefit of driver internals,
|
||||
* for example some hw, disabling a CRTC/plane is asynchronous, and
|
||||
* scanout does not actually complete until the next vblank. So some
|
||||
* cleanup (like releasing the reference(s) on the backing GEM bo(s))
|
||||
* should be deferred. In cases like this, the driver would like to
|
||||
* hold a ref to the fb even though it has already been removed from
|
||||
* userspace perspective.
|
||||
* The refcount is stored inside the mode object.
|
||||
*/
|
||||
/*
|
||||
* Place on the dev->mode_config.fb_list, access protected by
|
||||
* dev->mode_config.fb_lock.
|
||||
*/
|
||||
struct list_head head;
|
||||
struct drm_mode_object base;
|
||||
const struct drm_framebuffer_funcs *funcs;
|
||||
unsigned int pitches[4];
|
||||
unsigned int offsets[4];
|
||||
uint64_t modifier[4];
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
/* depth can be 15 or 16 */
|
||||
unsigned int depth;
|
||||
int bits_per_pixel;
|
||||
int flags;
|
||||
uint32_t pixel_format; /* fourcc format */
|
||||
int hot_x;
|
||||
int hot_y;
|
||||
struct list_head filp_head;
|
||||
};
|
||||
|
||||
struct drm_property_blob {
|
||||
struct drm_mode_object base;
|
||||
struct drm_device *dev;
|
||||
|
@ -289,7 +109,6 @@ struct drm_property {
|
|||
};
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_connector;
|
||||
struct drm_encoder;
|
||||
struct drm_pending_vblank_event;
|
||||
struct drm_plane;
|
||||
|
@ -298,7 +117,6 @@ struct drm_atomic_state;
|
|||
|
||||
struct drm_crtc_helper_funcs;
|
||||
struct drm_encoder_helper_funcs;
|
||||
struct drm_connector_helper_funcs;
|
||||
struct drm_plane_helper_funcs;
|
||||
|
||||
/**
|
||||
|
@ -547,16 +365,6 @@ struct drm_crtc_funcs {
|
|||
* counter and timestamp tracking though, e.g. if they have accurate
|
||||
* timestamp registers in hardware.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Up to that point drivers need to manage events themselves and can use
|
||||
* even->base.list freely for that. Specifically they need to ensure
|
||||
* that they don't send out page flip (or vblank) events for which the
|
||||
* corresponding drm file has been closed already. The drm core
|
||||
* unfortunately does not (yet) take care of that. Therefore drivers
|
||||
* currently must clean up and release pending events in their
|
||||
* ->preclose driver function.
|
||||
*
|
||||
* This callback is optional.
|
||||
*
|
||||
* NOTE:
|
||||
|
@ -853,291 +661,6 @@ struct drm_crtc {
|
|||
struct drm_modeset_acquire_ctx *acquire_ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_connector_state - mutable connector state
|
||||
* @connector: backpointer to the connector
|
||||
* @crtc: CRTC to connect connector to, NULL if disabled
|
||||
* @best_encoder: can be used by helpers and drivers to select the encoder
|
||||
* @state: backpointer to global drm_atomic_state
|
||||
*/
|
||||
struct drm_connector_state {
|
||||
struct drm_connector *connector;
|
||||
|
||||
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_connector() */
|
||||
|
||||
struct drm_encoder *best_encoder;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_connector_funcs - control connectors on a given device
|
||||
*
|
||||
* Each CRTC may have one or more connectors attached to it. The functions
|
||||
* below allow the core DRM code to control connectors, enumerate available modes,
|
||||
* etc.
|
||||
*/
|
||||
struct drm_connector_funcs {
|
||||
/**
|
||||
* @dpms:
|
||||
*
|
||||
* Legacy entry point to set the per-connector DPMS state. Legacy DPMS
|
||||
* is exposed as a standard property on the connector, but diverted to
|
||||
* this callback in the drm core. Note that atomic drivers don't
|
||||
* implement the 4 level DPMS support on the connector any more, but
|
||||
* instead only have an on/off "ACTIVE" property on the CRTC object.
|
||||
*
|
||||
* Drivers implementing atomic modeset should use
|
||||
* drm_atomic_helper_connector_dpms() to implement this hook.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*dpms)(struct drm_connector *connector, int mode);
|
||||
|
||||
/**
|
||||
* @reset:
|
||||
*
|
||||
* Reset connector hardware and software state to off. This function isn't
|
||||
* called by the core directly, only through drm_mode_config_reset().
|
||||
* It's not a helper hook only for historical reasons.
|
||||
*
|
||||
* Atomic drivers can use drm_atomic_helper_connector_reset() to reset
|
||||
* atomic state using this hook.
|
||||
*/
|
||||
void (*reset)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @detect:
|
||||
*
|
||||
* Check to see if anything is attached to the connector. The parameter
|
||||
* force is set to false whilst polling, true when checking the
|
||||
* connector due to a user request. force can be used by the driver to
|
||||
* avoid expensive, destructive operations during automated probing.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Note that this hook is only called by the probe helper. It's not in
|
||||
* the helper library vtable purely for historical reasons. The only DRM
|
||||
* core entry point to probe connector state is @fill_modes.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* drm_connector_status indicating the connector's status.
|
||||
*/
|
||||
enum drm_connector_status (*detect)(struct drm_connector *connector,
|
||||
bool force);
|
||||
|
||||
/**
|
||||
* @force:
|
||||
*
|
||||
* This function is called to update internal encoder state when the
|
||||
* connector is forced to a certain state by userspace, either through
|
||||
* the sysfs interfaces or on the kernel cmdline. In that case the
|
||||
* @detect callback isn't called.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Note that this hook is only called by the probe helper. It's not in
|
||||
* the helper library vtable purely for historical reasons. The only DRM
|
||||
* core entry point to probe connector state is @fill_modes.
|
||||
*/
|
||||
void (*force)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @fill_modes:
|
||||
*
|
||||
* Entry point for output detection and basic mode validation. The
|
||||
* driver should reprobe the output if needed (e.g. when hotplug
|
||||
* handling is unreliable), add all detected modes to connector->modes
|
||||
* and filter out any the device can't support in any configuration. It
|
||||
* also needs to filter out any modes wider or higher than the
|
||||
* parameters max_width and max_height indicate.
|
||||
*
|
||||
* The drivers must also prune any modes no longer valid from
|
||||
* connector->modes. Furthermore it must update connector->status and
|
||||
* connector->edid. If no EDID has been received for this output
|
||||
* connector->edid must be NULL.
|
||||
*
|
||||
* Drivers using the probe helpers should use
|
||||
* drm_helper_probe_single_connector_modes() or
|
||||
* drm_helper_probe_single_connector_modes_nomerge() to implement this
|
||||
* function.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* The number of modes detected and filled into connector->modes.
|
||||
*/
|
||||
int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
|
||||
|
||||
/**
|
||||
* @set_property:
|
||||
*
|
||||
* This is the legacy entry point to update a property attached to the
|
||||
* connector.
|
||||
*
|
||||
* Drivers implementing atomic modeset should use
|
||||
* drm_atomic_helper_connector_set_property() to implement this hook.
|
||||
*
|
||||
* This callback is optional if the driver does not support any legacy
|
||||
* driver-private properties.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*set_property)(struct drm_connector *connector, struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
/**
|
||||
* @late_register:
|
||||
*
|
||||
* This optional hook can be used to register additional userspace
|
||||
* interfaces attached to the connector, light backlight control, i2c,
|
||||
* DP aux or similar interfaces. It is called late in the driver load
|
||||
* sequence from drm_connector_register() when registering all the
|
||||
* core drm connector interfaces. Everything added from this callback
|
||||
* should be unregistered in the early_unregister callback.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* 0 on success, or a negative error code on failure.
|
||||
*/
|
||||
int (*late_register)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @early_unregister:
|
||||
*
|
||||
* This optional hook should be used to unregister the additional
|
||||
* userspace interfaces attached to the connector from
|
||||
* late_unregister(). It is called from drm_connector_unregister(),
|
||||
* early in the driver unload sequence to disable userspace access
|
||||
* before data structures are torndown.
|
||||
*/
|
||||
void (*early_unregister)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @destroy:
|
||||
*
|
||||
* Clean up connector resources. This is called at driver unload time
|
||||
* through drm_mode_config_cleanup(). It can also be called at runtime
|
||||
* when a connector is being hot-unplugged for drivers that support
|
||||
* connector hotplugging (e.g. DisplayPort MST).
|
||||
*/
|
||||
void (*destroy)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @atomic_duplicate_state:
|
||||
*
|
||||
* Duplicate the current atomic state for this connector and return it.
|
||||
* The core and helpers gurantee that any atomic state duplicated with
|
||||
* this hook and still owned by the caller (i.e. not transferred to the
|
||||
* driver by calling ->atomic_commit() from struct
|
||||
* &drm_mode_config_funcs) will be cleaned up by calling the
|
||||
* @atomic_destroy_state hook in this structure.
|
||||
*
|
||||
* Atomic drivers which don't subclass struct &drm_connector_state should use
|
||||
* drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
|
||||
* state structure to extend it with driver-private state should use
|
||||
* __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
|
||||
* duplicated in a consistent fashion across drivers.
|
||||
*
|
||||
* It is an error to call this hook before connector->state has been
|
||||
* initialized correctly.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* If the duplicate state references refcounted resources this hook must
|
||||
* acquire a reference for each of them. The driver must release these
|
||||
* references again in @atomic_destroy_state.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* Duplicated atomic state or NULL when the allocation failed.
|
||||
*/
|
||||
struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
|
||||
|
||||
/**
|
||||
* @atomic_destroy_state:
|
||||
*
|
||||
* Destroy a state duplicated with @atomic_duplicate_state and release
|
||||
* or unreference all resources it references
|
||||
*/
|
||||
void (*atomic_destroy_state)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
|
||||
/**
|
||||
* @atomic_set_property:
|
||||
*
|
||||
* Decode a driver-private property value and store the decoded value
|
||||
* into the passed-in state structure. Since the atomic core decodes all
|
||||
* standardized properties (even for extensions beyond the core set of
|
||||
* properties which might not be implemented by all drivers) this
|
||||
* requires drivers to subclass the state structure.
|
||||
*
|
||||
* Such driver-private properties should really only be implemented for
|
||||
* truly hardware/vendor specific state. Instead it is preferred to
|
||||
* standardize atomic extension and decode the properties used to expose
|
||||
* such an extension in the core.
|
||||
*
|
||||
* Do not call this function directly, use
|
||||
* drm_atomic_connector_set_property() instead.
|
||||
*
|
||||
* This callback is optional if the driver does not support any
|
||||
* driver-private atomic properties.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
* This function is called in the state assembly phase of atomic
|
||||
* modesets, which can be aborted for any reason (including on
|
||||
* userspace's request to just check whether a configuration would be
|
||||
* possible). Drivers MUST NOT touch any persistent state (hardware or
|
||||
* software) or data structures except the passed in @state parameter.
|
||||
*
|
||||
* Also since userspace controls in which order properties are set this
|
||||
* function must not do any input validation (since the state update is
|
||||
* incomplete and hence likely inconsistent). Instead any such input
|
||||
* validation must be done in the various atomic_check callbacks.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 if the property has been found, -EINVAL if the property isn't
|
||||
* implemented by the driver (which shouldn't ever happen, the core only
|
||||
* asks for properties attached to this connector). No other validation
|
||||
* is allowed by the driver. The core already checks that the property
|
||||
* value is within the range (integer, valid enum value, ...) the driver
|
||||
* set when registering the property.
|
||||
*/
|
||||
int (*atomic_set_property)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
/**
|
||||
* @atomic_get_property:
|
||||
*
|
||||
* Reads out the decoded driver-private property. This is used to
|
||||
* implement the GETCONNECTOR IOCTL.
|
||||
*
|
||||
* Do not call this function directly, use
|
||||
* drm_atomic_connector_get_property() instead.
|
||||
*
|
||||
* This callback is optional if the driver does not support any
|
||||
* driver-private atomic properties.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success, -EINVAL if the property isn't implemented by the
|
||||
* driver (which shouldn't ever happen, the core only asks for
|
||||
* properties attached to this connector).
|
||||
*/
|
||||
int (*atomic_get_property)(struct drm_connector *connector,
|
||||
const struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t *val);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_encoder_funcs - encoder controls
|
||||
*
|
||||
|
@ -1189,15 +712,13 @@ struct drm_encoder_funcs {
|
|||
void (*early_unregister)(struct drm_encoder *encoder);
|
||||
};
|
||||
|
||||
#define DRM_CONNECTOR_MAX_ENCODER 3
|
||||
|
||||
/**
|
||||
* struct drm_encoder - central DRM encoder structure
|
||||
* @dev: parent DRM device
|
||||
* @head: list management
|
||||
* @base: base KMS object
|
||||
* @name: human readable name, can be overwritten by the driver
|
||||
* @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h
|
||||
* @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
|
||||
* @possible_crtcs: bitmask of potential CRTC bindings
|
||||
* @possible_clones: bitmask of potential sibling encoders for cloning
|
||||
* @crtc: currently bound CRTC
|
||||
|
@ -1231,171 +752,6 @@ struct drm_encoder {
|
|||
const struct drm_encoder_helper_funcs *helper_private;
|
||||
};
|
||||
|
||||
/* should we poll this connector for connects and disconnects */
|
||||
/* hot plug detectable */
|
||||
#define DRM_CONNECTOR_POLL_HPD (1 << 0)
|
||||
/* poll for connections */
|
||||
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
|
||||
/* can cleanly poll for disconnections without flickering the screen */
|
||||
/* DACs should rarely do this without a lot of testing */
|
||||
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
|
||||
|
||||
#define MAX_ELD_BYTES 128
|
||||
|
||||
/**
|
||||
* struct drm_connector - central DRM connector control structure
|
||||
* @dev: parent DRM device
|
||||
* @kdev: kernel device for sysfs attributes
|
||||
* @attr: sysfs attributes
|
||||
* @head: list management
|
||||
* @base: base KMS object
|
||||
* @name: human readable name, can be overwritten by the driver
|
||||
* @connector_type: one of the %DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
|
||||
* @connector_type_id: index into connector type enum
|
||||
* @interlace_allowed: can this connector handle interlaced modes?
|
||||
* @doublescan_allowed: can this connector handle doublescan?
|
||||
* @stereo_allowed: can this connector handle stereo modes?
|
||||
* @registered: is this connector exposed (registered) with userspace?
|
||||
* @modes: modes available on this connector (from fill_modes() + user)
|
||||
* @status: one of the drm_connector_status enums (connected, not, or unknown)
|
||||
* @probed_modes: list of modes derived directly from the display
|
||||
* @display_info: information about attached display (e.g. from EDID)
|
||||
* @funcs: connector control functions
|
||||
* @edid_blob_ptr: DRM property containing EDID if present
|
||||
* @properties: property tracking for this connector
|
||||
* @polled: a %DRM_CONNECTOR_POLL_<foo> value for core driven polling
|
||||
* @dpms: current dpms state
|
||||
* @helper_private: mid-layer private data
|
||||
* @cmdline_mode: mode line parsed from the kernel cmdline for this connector
|
||||
* @force: a %DRM_FORCE_<foo> state for forced mode sets
|
||||
* @override_edid: has the EDID been overwritten through debugfs for testing?
|
||||
* @encoder_ids: valid encoders for this connector
|
||||
* @encoder: encoder driving this connector, if any
|
||||
* @eld: EDID-like data, if present
|
||||
* @dvi_dual: dual link DVI, if found
|
||||
* @max_tmds_clock: max clock rate, if found
|
||||
* @latency_present: AV delay info from ELD, if found
|
||||
* @video_latency: video latency info from ELD, if found
|
||||
* @audio_latency: audio latency info from ELD, if found
|
||||
* @null_edid_counter: track sinks that give us all zeros for the EDID
|
||||
* @bad_edid_counter: track sinks that give us an EDID with invalid checksum
|
||||
* @edid_corrupt: indicates whether the last read EDID was corrupt
|
||||
* @debugfs_entry: debugfs directory for this connector
|
||||
* @state: current atomic state for this connector
|
||||
* @has_tile: is this connector connected to a tiled monitor
|
||||
* @tile_group: tile group for the connected monitor
|
||||
* @tile_is_single_monitor: whether the tile is one monitor housing
|
||||
* @num_h_tile: number of horizontal tiles in the tile group
|
||||
* @num_v_tile: number of vertical tiles in the tile group
|
||||
* @tile_h_loc: horizontal location of this tile
|
||||
* @tile_v_loc: vertical location of this tile
|
||||
* @tile_h_size: horizontal size of this tile.
|
||||
* @tile_v_size: vertical size of this tile.
|
||||
*
|
||||
* Each connector may be connected to one or more CRTCs, or may be clonable by
|
||||
* another connector if they can share a CRTC. Each connector also has a specific
|
||||
* position in the broader display (referred to as a 'screen' though it could
|
||||
* span multiple monitors).
|
||||
*/
|
||||
struct drm_connector {
|
||||
struct drm_device *dev;
|
||||
struct device *kdev;
|
||||
struct device_attribute *attr;
|
||||
struct list_head head;
|
||||
|
||||
struct drm_mode_object base;
|
||||
|
||||
char *name;
|
||||
|
||||
/**
|
||||
* @index: Compacted connector index, which matches the position inside
|
||||
* the mode_config.list for drivers not supporting hot-add/removing. Can
|
||||
* be used as an array index. It is invariant over the lifetime of the
|
||||
* connector.
|
||||
*/
|
||||
unsigned index;
|
||||
|
||||
int connector_type;
|
||||
int connector_type_id;
|
||||
bool interlace_allowed;
|
||||
bool doublescan_allowed;
|
||||
bool stereo_allowed;
|
||||
bool registered;
|
||||
struct list_head modes; /* list of modes on this connector */
|
||||
|
||||
enum drm_connector_status status;
|
||||
|
||||
/* these are modes added by probing with DDC or the BIOS */
|
||||
struct list_head probed_modes;
|
||||
|
||||
struct drm_display_info display_info;
|
||||
const struct drm_connector_funcs *funcs;
|
||||
|
||||
struct drm_property_blob *edid_blob_ptr;
|
||||
struct drm_object_properties properties;
|
||||
|
||||
/**
|
||||
* @path_blob_ptr:
|
||||
*
|
||||
* DRM blob property data for the DP MST path property.
|
||||
*/
|
||||
struct drm_property_blob *path_blob_ptr;
|
||||
|
||||
/**
|
||||
* @tile_blob_ptr:
|
||||
*
|
||||
* DRM blob property data for the tile property (used mostly by DP MST).
|
||||
* This is meant for screens which are driven through separate display
|
||||
* pipelines represented by &drm_crtc, which might not be running with
|
||||
* genlocked clocks. For tiled panels which are genlocked, like
|
||||
* dual-link LVDS or dual-link DSI, the driver should try to not expose
|
||||
* the tiling and virtualize both &drm_crtc and &drm_plane if needed.
|
||||
*/
|
||||
struct drm_property_blob *tile_blob_ptr;
|
||||
|
||||
uint8_t polled; /* DRM_CONNECTOR_POLL_* */
|
||||
|
||||
/* requested DPMS state */
|
||||
int dpms;
|
||||
|
||||
const struct drm_connector_helper_funcs *helper_private;
|
||||
|
||||
/* forced on connector */
|
||||
struct drm_cmdline_mode cmdline_mode;
|
||||
enum drm_connector_force force;
|
||||
bool override_edid;
|
||||
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
|
||||
struct drm_encoder *encoder; /* currently active encoder */
|
||||
|
||||
/* EDID bits */
|
||||
uint8_t eld[MAX_ELD_BYTES];
|
||||
bool dvi_dual;
|
||||
int max_tmds_clock; /* in MHz */
|
||||
bool latency_present[2];
|
||||
int video_latency[2]; /* [0]: progressive, [1]: interlaced */
|
||||
int audio_latency[2];
|
||||
int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
|
||||
unsigned bad_edid_counter;
|
||||
|
||||
/* Flag for raw EDID header corruption - used in Displayport
|
||||
* compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
|
||||
*/
|
||||
bool edid_corrupt;
|
||||
|
||||
struct dentry *debugfs_entry;
|
||||
|
||||
struct drm_connector_state *state;
|
||||
|
||||
/* DisplayID bits */
|
||||
bool has_tile;
|
||||
struct drm_tile_group *tile_group;
|
||||
bool tile_is_single_monitor;
|
||||
|
||||
uint8_t num_h_tile, num_v_tile;
|
||||
uint8_t tile_h_loc, tile_v_loc;
|
||||
uint16_t tile_h_size, tile_v_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_plane_state - mutable plane state
|
||||
* @plane: backpointer to the plane
|
||||
|
@ -2649,12 +2005,6 @@ struct drm_mode_config {
|
|||
* HDMI infoframe aspect ratio setting.
|
||||
*/
|
||||
struct drm_property *aspect_ratio_property;
|
||||
/**
|
||||
* @dirty_info_property: Optional connector property to give userspace a
|
||||
* hint that the DIRTY_FB ioctl should be used.
|
||||
*/
|
||||
struct drm_property *dirty_info_property;
|
||||
|
||||
/**
|
||||
* @degamma_lut_property: Optional CRTC property to set the LUT used to
|
||||
* convert the framebuffer's colors to linear gamma.
|
||||
|
@ -2741,7 +2091,6 @@ struct drm_mode_config {
|
|||
for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
|
||||
|
||||
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
|
||||
#define obj_to_connector(x) container_of(x, struct drm_connector, base)
|
||||
#define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
|
||||
#define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
|
||||
#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
|
||||
|
@ -2787,19 +2136,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
|
|||
return 1 << drm_crtc_index(crtc);
|
||||
}
|
||||
|
||||
int drm_connector_init(struct drm_device *dev,
|
||||
struct drm_connector *connector,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type);
|
||||
int drm_connector_register(struct drm_connector *connector);
|
||||
void drm_connector_unregister(struct drm_connector *connector);
|
||||
|
||||
extern void drm_connector_cleanup(struct drm_connector *connector);
|
||||
static inline unsigned drm_connector_index(struct drm_connector *connector)
|
||||
{
|
||||
return connector->index;
|
||||
}
|
||||
|
||||
extern __printf(5, 6)
|
||||
int drm_encoder_init(struct drm_device *dev,
|
||||
struct drm_encoder *encoder,
|
||||
|
@ -2868,27 +2204,10 @@ extern int drm_crtc_force_disable_all(struct drm_device *dev);
|
|||
|
||||
extern void drm_encoder_cleanup(struct drm_encoder *encoder);
|
||||
|
||||
extern const char *drm_get_connector_status_name(enum drm_connector_status status);
|
||||
extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
|
||||
extern const char *drm_get_dpms_name(int val);
|
||||
extern const char *drm_get_dvi_i_subconnector_name(int val);
|
||||
extern const char *drm_get_dvi_i_select_name(int val);
|
||||
extern const char *drm_get_tv_subconnector_name(int val);
|
||||
extern const char *drm_get_tv_select_name(int val);
|
||||
extern void drm_mode_config_init(struct drm_device *dev);
|
||||
extern void drm_mode_config_reset(struct drm_device *dev);
|
||||
extern void drm_mode_config_cleanup(struct drm_device *dev);
|
||||
|
||||
extern int drm_mode_connector_set_path_property(struct drm_connector *connector,
|
||||
const char *path);
|
||||
int drm_mode_connector_set_tile_property(struct drm_connector *connector);
|
||||
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
|
||||
const struct edid *edid);
|
||||
|
||||
extern int drm_display_info_set_bus_formats(struct drm_display_info *info,
|
||||
const u32 *formats,
|
||||
unsigned int num_formats);
|
||||
|
||||
static inline bool drm_property_type_is(struct drm_property *property,
|
||||
uint32_t type)
|
||||
{
|
||||
|
@ -2904,14 +2223,6 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,
|
|||
extern int drm_object_property_get_value(struct drm_mode_object *obj,
|
||||
struct drm_property *property,
|
||||
uint64_t *value);
|
||||
extern int drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb,
|
||||
const struct drm_framebuffer_funcs *funcs);
|
||||
extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
|
||||
uint32_t id);
|
||||
extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
|
||||
extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
|
||||
extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
|
||||
|
||||
extern void drm_object_attach_property(struct drm_mode_object *obj,
|
||||
struct drm_property *property,
|
||||
|
@ -2942,22 +2253,17 @@ struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
|
|||
const void *data);
|
||||
struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
|
||||
uint32_t id);
|
||||
int drm_property_replace_global_blob(struct drm_device *dev,
|
||||
struct drm_property_blob **replace,
|
||||
size_t length,
|
||||
const void *data,
|
||||
struct drm_mode_object *obj_holds_id,
|
||||
struct drm_property *prop_holds_id);
|
||||
struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
|
||||
void drm_property_unreference_blob(struct drm_property_blob *blob);
|
||||
extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
|
||||
extern int drm_property_add_enum(struct drm_property *property, int index,
|
||||
uint64_t value, const char *name);
|
||||
extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
|
||||
extern int drm_mode_create_tv_properties(struct drm_device *dev,
|
||||
unsigned int num_modes,
|
||||
const char * const modes[]);
|
||||
extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
|
||||
extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
|
||||
extern int drm_mode_create_dirty_info_property(struct drm_device *dev);
|
||||
extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
|
||||
|
||||
extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
|
||||
struct drm_encoder *encoder);
|
||||
extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
|
||||
int gamma_size);
|
||||
|
||||
|
@ -2993,11 +2299,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
|
|||
unsigned int zpos);
|
||||
|
||||
/* Helpers */
|
||||
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
|
||||
uint32_t id, uint32_t type);
|
||||
void drm_mode_object_reference(struct drm_mode_object *obj);
|
||||
void drm_mode_object_unreference(struct drm_mode_object *obj);
|
||||
|
||||
static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
|
||||
uint32_t id)
|
||||
{
|
||||
|
@ -3022,22 +2323,6 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
|
|||
return mo ? obj_to_encoder(mo) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_lookup - lookup connector object
|
||||
* @dev: DRM device
|
||||
* @id: connector object id
|
||||
*
|
||||
* This function looks up the connector object specified by id
|
||||
* add takes a reference to it.
|
||||
*/
|
||||
static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
|
||||
uint32_t id)
|
||||
{
|
||||
struct drm_mode_object *mo;
|
||||
mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
|
||||
return mo ? obj_to_connector(mo) : NULL;
|
||||
}
|
||||
|
||||
static inline struct drm_property *drm_property_find(struct drm_device *dev,
|
||||
uint32_t id)
|
||||
{
|
||||
|
@ -3065,61 +2350,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
|
|||
return clamp_val(val, 0, max);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_reference - incr the fb refcnt
|
||||
* @fb: framebuffer
|
||||
*
|
||||
* This functions increments the fb's refcount.
|
||||
*/
|
||||
static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
|
||||
{
|
||||
drm_mode_object_reference(&fb->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_unreference - unref a framebuffer
|
||||
* @fb: framebuffer to unref
|
||||
*
|
||||
* This functions decrements the fb's refcount and frees it if it drops to zero.
|
||||
*/
|
||||
static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
|
||||
{
|
||||
drm_mode_object_unreference(&fb->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_read_refcount - read the framebuffer reference count.
|
||||
* @fb: framebuffer
|
||||
*
|
||||
* This functions returns the framebuffer's reference count.
|
||||
*/
|
||||
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
|
||||
{
|
||||
return atomic_read(&fb->base.refcount.refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_reference - incr the connector refcnt
|
||||
* @connector: connector
|
||||
*
|
||||
* This function increments the connector's refcount.
|
||||
*/
|
||||
static inline void drm_connector_reference(struct drm_connector *connector)
|
||||
{
|
||||
drm_mode_object_reference(&connector->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_unreference - unref a connector
|
||||
* @connector: connector to unref
|
||||
*
|
||||
* This function decrements the connector's refcount and frees it if it drops to zero.
|
||||
*/
|
||||
static inline void drm_connector_unreference(struct drm_connector *connector)
|
||||
{
|
||||
drm_mode_object_unreference(&connector->base);
|
||||
}
|
||||
|
||||
/* Plane list iterator for legacy (overlay only) planes. */
|
||||
#define drm_for_each_legacy_plane(plane, dev) \
|
||||
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
|
||||
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
|
||||
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
|
||||
|
@ -53,11 +54,6 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
|
|||
|
||||
extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
|
||||
|
||||
extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
|
||||
|
||||
extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
extern void drm_helper_resume_force_mode(struct drm_device *dev);
|
||||
|
||||
int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
|
|
|
@ -177,6 +177,7 @@ struct drm_fb_helper_connector {
|
|||
* the screen buffer
|
||||
* @dirty_lock: spinlock protecting @dirty_clip
|
||||
* @dirty_work: worker used to flush the framebuffer
|
||||
* @resume_work: worker used during resume if the console lock is already taken
|
||||
*
|
||||
* This is the main structure used by the fbdev helpers. Drivers supporting
|
||||
* fbdev emulation should embedded this into their overall driver structure.
|
||||
|
@ -197,6 +198,7 @@ struct drm_fb_helper {
|
|||
struct drm_clip_rect dirty_clip;
|
||||
spinlock_t dirty_lock;
|
||||
struct work_struct dirty_work;
|
||||
struct work_struct resume_work;
|
||||
|
||||
/**
|
||||
* @kernel_fb_list:
|
||||
|
@ -216,7 +218,6 @@ struct drm_fb_helper {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
int drm_fb_helper_modinit(void);
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
const struct drm_fb_helper_funcs *funcs);
|
||||
int drm_fb_helper_init(struct drm_device *dev,
|
||||
|
@ -264,7 +265,9 @@ void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
|||
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image);
|
||||
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, int state);
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
|
||||
void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
|
||||
bool suspend);
|
||||
|
||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info);
|
||||
|
||||
|
@ -283,12 +286,6 @@ drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
|
|||
int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_connector *connector);
|
||||
int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
||||
struct drm_connector *connector);
|
||||
static inline int
|
||||
drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
|
||||
const char *name, bool primary)
|
||||
{
|
||||
return remove_conflicting_framebuffers(a, name, primary);
|
||||
}
|
||||
#else
|
||||
static inline int drm_fb_helper_modinit(void)
|
||||
{
|
||||
|
@ -424,7 +421,12 @@ static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
|||
}
|
||||
|
||||
static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
|
||||
int state)
|
||||
bool suspend)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper, bool suspend)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -483,11 +485,17 @@ drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
|
||||
const char *name, bool primary)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_FB)
|
||||
return remove_conflicting_framebuffers(a, name, primary);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,6 @@ int drm_format_horz_chroma_subsampling(uint32_t format);
|
|||
int drm_format_vert_chroma_subsampling(uint32_t format);
|
||||
int drm_format_plane_width(int width, uint32_t format, int plane);
|
||||
int drm_format_plane_height(int height, uint32_t format, int plane);
|
||||
const char *drm_get_format_name(uint32_t format);
|
||||
char *drm_get_format_name(uint32_t format) __malloc;
|
||||
|
||||
#endif /* __DRM_FOURCC_H__ */
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_FRAMEBUFFER_H__
|
||||
#define __DRM_FRAMEBUFFER_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <drm/drm_modeset.h>
|
||||
|
||||
struct drm_framebuffer;
|
||||
struct drm_file;
|
||||
struct drm_device;
|
||||
|
||||
/**
|
||||
* struct drm_framebuffer_funcs - framebuffer hooks
|
||||
*/
|
||||
struct drm_framebuffer_funcs {
|
||||
/**
|
||||
* @destroy:
|
||||
*
|
||||
* Clean up framebuffer resources, specifically also unreference the
|
||||
* backing storage. The core guarantees to call this function for every
|
||||
* framebuffer successfully created by ->fb_create() in
|
||||
* &drm_mode_config_funcs. Drivers must also call
|
||||
* drm_framebuffer_cleanup() to release DRM core resources for this
|
||||
* framebuffer.
|
||||
*/
|
||||
void (*destroy)(struct drm_framebuffer *framebuffer);
|
||||
|
||||
/**
|
||||
* @create_handle:
|
||||
*
|
||||
* Create a buffer handle in the driver-specific buffer manager (either
|
||||
* GEM or TTM) valid for the passed-in struct &drm_file. This is used by
|
||||
* the core to implement the GETFB IOCTL, which returns (for
|
||||
* sufficiently priviledged user) also a native buffer handle. This can
|
||||
* be used for seamless transitions between modesetting clients by
|
||||
* copying the current screen contents to a private buffer and blending
|
||||
* between that and the new contents.
|
||||
*
|
||||
* GEM based drivers should call drm_gem_handle_create() to create the
|
||||
* handle.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*create_handle)(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle);
|
||||
/**
|
||||
* @dirty:
|
||||
*
|
||||
* Optional callback for the dirty fb IOCTL.
|
||||
*
|
||||
* Userspace can notify the driver via this callback that an area of the
|
||||
* framebuffer has changed and should be flushed to the display
|
||||
* hardware. This can also be used internally, e.g. by the fbdev
|
||||
* emulation, though that's not the case currently.
|
||||
*
|
||||
* See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
|
||||
* for more information as all the semantics and arguments have a one to
|
||||
* one mapping on this function.
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*dirty)(struct drm_framebuffer *framebuffer,
|
||||
struct drm_file *file_priv, unsigned flags,
|
||||
unsigned color, struct drm_clip_rect *clips,
|
||||
unsigned num_clips);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_framebuffer - frame buffer object
|
||||
*
|
||||
* Note that the fb is refcounted for the benefit of driver internals,
|
||||
* for example some hw, disabling a CRTC/plane is asynchronous, and
|
||||
* scanout does not actually complete until the next vblank. So some
|
||||
* cleanup (like releasing the reference(s) on the backing GEM bo(s))
|
||||
* should be deferred. In cases like this, the driver would like to
|
||||
* hold a ref to the fb even though it has already been removed from
|
||||
* userspace perspective. See drm_framebuffer_reference() and
|
||||
* drm_framebuffer_unreference().
|
||||
*
|
||||
* The refcount is stored inside the mode object @base.
|
||||
*/
|
||||
struct drm_framebuffer {
|
||||
/**
|
||||
* @dev: DRM device this framebuffer belongs to
|
||||
*/
|
||||
struct drm_device *dev;
|
||||
/**
|
||||
* @head: Place on the dev->mode_config.fb_list, access protected by
|
||||
* dev->mode_config.fb_lock.
|
||||
*/
|
||||
struct list_head head;
|
||||
|
||||
/**
|
||||
* @base: base modeset object structure, contains the reference count.
|
||||
*/
|
||||
struct drm_mode_object base;
|
||||
/**
|
||||
* @funcs: framebuffer vfunc table
|
||||
*/
|
||||
const struct drm_framebuffer_funcs *funcs;
|
||||
/**
|
||||
* @pitches: Line stride per buffer. For userspace created object this
|
||||
* is copied from drm_mode_fb_cmd2.
|
||||
*/
|
||||
unsigned int pitches[4];
|
||||
/**
|
||||
* @offsets: Offset from buffer start to the actual pixel data in bytes,
|
||||
* per buffer. For userspace created object this is copied from
|
||||
* drm_mode_fb_cmd2.
|
||||
*
|
||||
* Note that this is a linear offset and does not take into account
|
||||
* tiling or buffer laytou per @modifier. It meant to be used when the
|
||||
* actual pixel data for this framebuffer plane starts at an offset,
|
||||
* e.g. when multiple planes are allocated within the same backing
|
||||
* storage buffer object. For tiled layouts this generally means it
|
||||
* @offsets must at least be tile-size aligned, but hardware often has
|
||||
* stricter requirements.
|
||||
*
|
||||
* This should not be used to specifiy x/y pixel offsets into the buffer
|
||||
* data (even for linear buffers). Specifying an x/y pixel offset is
|
||||
* instead done through the source rectangle in struct &drm_plane_state.
|
||||
*/
|
||||
unsigned int offsets[4];
|
||||
/**
|
||||
* @modifier: Data layout modifier, per buffer. This is used to describe
|
||||
* tiling, or also special layouts (like compression) of auxiliary
|
||||
* buffers. For userspace created object this is copied from
|
||||
* drm_mode_fb_cmd2.
|
||||
*/
|
||||
uint64_t modifier[4];
|
||||
/**
|
||||
* @width: Logical width of the visible area of the framebuffer, in
|
||||
* pixels.
|
||||
*/
|
||||
unsigned int width;
|
||||
/**
|
||||
* @height: Logical height of the visible area of the framebuffer, in
|
||||
* pixels.
|
||||
*/
|
||||
unsigned int height;
|
||||
/**
|
||||
* @depth: Depth in bits per pixel for RGB formats. 0 for everything
|
||||
* else. Legacy information derived from @pixel_format, it's suggested to use
|
||||
* the DRM FOURCC codes and helper functions directly instead.
|
||||
*/
|
||||
unsigned int depth;
|
||||
/**
|
||||
* @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for
|
||||
* everything else. Legacy information derived from @pixel_format, it's
|
||||
* suggested to use the DRM FOURCC codes and helper functions directly
|
||||
* instead.
|
||||
*/
|
||||
int bits_per_pixel;
|
||||
/**
|
||||
* @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
|
||||
* DRM_MODE_FB_MODIFIERS.
|
||||
*/
|
||||
int flags;
|
||||
/**
|
||||
* @pixel_format: DRM FOURCC code describing the pixel format.
|
||||
*/
|
||||
uint32_t pixel_format; /* fourcc format */
|
||||
/**
|
||||
* @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
|
||||
* IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
|
||||
* universal plane.
|
||||
*/
|
||||
int hot_x;
|
||||
/**
|
||||
* @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor
|
||||
* IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
|
||||
* universal plane.
|
||||
*/
|
||||
int hot_y;
|
||||
/**
|
||||
* @filp_head: Placed on struct &drm_file fbs list_head, protected by
|
||||
* fbs_lock in the same structure.
|
||||
*/
|
||||
struct list_head filp_head;
|
||||
};
|
||||
|
||||
int drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb,
|
||||
const struct drm_framebuffer_funcs *funcs);
|
||||
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
|
||||
uint32_t id);
|
||||
void drm_framebuffer_remove(struct drm_framebuffer *fb);
|
||||
void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
|
||||
void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
|
||||
|
||||
/**
|
||||
* drm_framebuffer_reference - incr the fb refcnt
|
||||
* @fb: framebuffer
|
||||
*
|
||||
* This functions increments the fb's refcount.
|
||||
*/
|
||||
static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
|
||||
{
|
||||
drm_mode_object_reference(&fb->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_unreference - unref a framebuffer
|
||||
* @fb: framebuffer to unref
|
||||
*
|
||||
* This functions decrements the fb's refcount and frees it if it drops to zero.
|
||||
*/
|
||||
static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
|
||||
{
|
||||
drm_mode_object_unreference(&fb->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_framebuffer_read_refcount - read the framebuffer reference count.
|
||||
* @fb: framebuffer
|
||||
*
|
||||
* This functions returns the framebuffer's reference count.
|
||||
*/
|
||||
static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
|
||||
{
|
||||
return atomic_read(&fb->base.refcount.refcount);
|
||||
}
|
||||
#endif
|
|
@ -210,8 +210,8 @@ drm_gem_object_reference(struct drm_gem_object *obj)
|
|||
* drm_gem_object_unreference_unlocked().
|
||||
*
|
||||
* Drivers should never call this directly in their code. Instead they should
|
||||
* wrap it up into a driver_gem_object_unreference(struct driver_gem_object
|
||||
* *obj) wrapper function, and use that. Shared code should never call this, to
|
||||
* wrap it up into a ``driver_gem_object_unreference(struct driver_gem_object
|
||||
* *obj)`` wrapper function, and use that. Shared code should never call this, to
|
||||
* avoid breaking drivers by accident which still depend upon dev->struct_mutex
|
||||
* locking.
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#ifndef __DRM_MODES_H__
|
||||
#define __DRM_MODES_H__
|
||||
|
||||
#include <drm/drm_modeset.h>
|
||||
#include <drm/drm_connector.h>
|
||||
|
||||
/*
|
||||
* Note on terminology: here, for brevity and convenience, we refer to connector
|
||||
* control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS,
|
||||
|
@ -400,21 +403,6 @@ struct drm_display_mode {
|
|||
enum hdmi_picture_aspect picture_aspect_ratio;
|
||||
};
|
||||
|
||||
/* mode specified on the command line */
|
||||
struct drm_cmdline_mode {
|
||||
bool specified;
|
||||
bool refresh_specified;
|
||||
bool bpp_specified;
|
||||
int xres, yres;
|
||||
int bpp;
|
||||
int refresh;
|
||||
bool rb;
|
||||
bool interlace;
|
||||
bool cvt;
|
||||
bool margins;
|
||||
enum drm_connector_force force;
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_mode_is_stereo - check for stereo mode flags
|
||||
* @mode: drm_display_mode to check
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_MODESET_H__
|
||||
#define __DRM_MODESET_H__
|
||||
|
||||
#include <linux/kref.h>
|
||||
struct drm_object_properties;
|
||||
struct drm_property;
|
||||
|
||||
struct drm_mode_object {
|
||||
uint32_t id;
|
||||
uint32_t type;
|
||||
struct drm_object_properties *properties;
|
||||
struct kref refcount;
|
||||
void (*free_cb)(struct kref *kref);
|
||||
};
|
||||
|
||||
#define DRM_OBJECT_MAX_PROPERTY 24
|
||||
struct drm_object_properties {
|
||||
int count, atomic_count;
|
||||
/* NOTE: if we ever start dynamically destroying properties (ie.
|
||||
* not at drm_mode_config_cleanup() time), then we'd have to do
|
||||
* a better job of detaching property from mode objects to avoid
|
||||
* dangling property pointers:
|
||||
*/
|
||||
struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
|
||||
/* do not read/write values directly, but use drm_object_property_get_value()
|
||||
* and drm_object_property_set_value():
|
||||
*/
|
||||
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
|
||||
};
|
||||
|
||||
/* Avoid boilerplate. I'm tired of typing. */
|
||||
#define DRM_ENUM_NAME_FN(fnname, list) \
|
||||
const char *fnname(int val) \
|
||||
{ \
|
||||
int i; \
|
||||
for (i = 0; i < ARRAY_SIZE(list); i++) { \
|
||||
if (list[i].type == val) \
|
||||
return list[i].name; \
|
||||
} \
|
||||
return "(unknown)"; \
|
||||
}
|
||||
|
||||
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
|
||||
uint32_t id, uint32_t type);
|
||||
void drm_mode_object_reference(struct drm_mode_object *obj);
|
||||
void drm_mode_object_unreference(struct drm_mode_object *obj);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __DRM_KMS_HELPER_H__
|
||||
#define __DRM_KMS_HELPER_H__
|
||||
|
||||
#include <drm/drmP.h>
|
||||
|
||||
void drm_helper_move_panel_connectors_to_head(struct drm_device *);
|
||||
|
||||
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
|
||||
#endif
|
|
@ -855,7 +855,7 @@ struct drm_plane_helper_funcs {
|
|||
* everything else must complete successfully.
|
||||
*/
|
||||
int (*prepare_fb)(struct drm_plane *plane,
|
||||
const struct drm_plane_state *new_state);
|
||||
struct drm_plane_state *new_state);
|
||||
/**
|
||||
* @cleanup_fb:
|
||||
*
|
||||
|
@ -866,7 +866,7 @@ struct drm_plane_helper_funcs {
|
|||
* transitional plane helpers, but it is optional.
|
||||
*/
|
||||
void (*cleanup_fb)(struct drm_plane *plane,
|
||||
const struct drm_plane_state *old_state);
|
||||
struct drm_plane_state *old_state);
|
||||
|
||||
/**
|
||||
* @atomic_check:
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
|
||||
/*
|
||||
* Drivers that don't allow primary plane scaling may pass this macro in place
|
||||
|
@ -37,9 +38,6 @@
|
|||
*/
|
||||
#define DRM_PLANE_HELPER_NO_SCALING (1<<16)
|
||||
|
||||
int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
|
||||
int drm_plane_helper_check_state(struct drm_plane_state *state,
|
||||
const struct drm_rect *clip,
|
||||
int min_scale, int max_scale,
|
||||
|
|
|
@ -73,34 +73,6 @@ static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
|
|||
unsigned int decodes) { };
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vga_get - acquire & locks VGA resources
|
||||
*
|
||||
* @pdev: pci device of the VGA card or NULL for the system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
* @interruptible: blocking should be interruptible by signals ?
|
||||
*
|
||||
* This function acquires VGA resources for the given
|
||||
* card and mark those resources locked. If the resource 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 accesse are enabled on the card (including
|
||||
* VGA forwarding on parent P2P bridges if any).
|
||||
* This 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 differenciate VGA memory and IO
|
||||
* afaik). You can indicate whether this blocking should be interruptible
|
||||
* by a signal (for userland interface) or not.
|
||||
* Must not be called at interrupt time or in atomic context.
|
||||
* If the card already owns the resources, the function succeeds.
|
||||
* Nested calls are supported (a per-resource counter is maintained)
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_VGA_ARB)
|
||||
extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
|
||||
#else
|
||||
|
@ -108,11 +80,14 @@ static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interrupt
|
|||
#endif
|
||||
|
||||
/**
|
||||
* vga_get_interruptible
|
||||
* vga_get_interruptible
|
||||
* @pdev: pci device of the VGA card or NULL for the system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
*
|
||||
* Shortcut to vga_get
|
||||
* Shortcut to vga_get with interruptible set to true.
|
||||
*
|
||||
* On success, release the VGA resource again with vga_put().
|
||||
*/
|
||||
|
||||
static inline int vga_get_interruptible(struct pci_dev *pdev,
|
||||
unsigned int rsrc)
|
||||
{
|
||||
|
@ -120,47 +95,26 @@ static inline int vga_get_interruptible(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
/**
|
||||
* vga_get_uninterruptible
|
||||
* vga_get_uninterruptible - shortcut to vga_get()
|
||||
* @pdev: pci device of the VGA card or NULL for the system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
*
|
||||
* Shortcut to vga_get
|
||||
* Shortcut to vga_get with interruptible set to false.
|
||||
*
|
||||
* On success, release the VGA resource again with vga_put().
|
||||
*/
|
||||
|
||||
static inline int vga_get_uninterruptible(struct pci_dev *pdev,
|
||||
unsigned int rsrc)
|
||||
{
|
||||
return vga_get(pdev, rsrc, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* vga_tryget - try to acquire & lock legacy VGA resources
|
||||
*
|
||||
* @pdev: pci devivce of VGA card or NULL for system default
|
||||
* @rsrc: bit mask of resources to acquire and lock
|
||||
*
|
||||
* This function performs the same operation as vga_get(), but
|
||||
* will return an error (-EBUSY) instead of blocking if the resources
|
||||
* are already locked by another card. It can be called in any context
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_VGA_ARB)
|
||||
extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc);
|
||||
#else
|
||||
static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vga_put - release lock on legacy VGA resources
|
||||
*
|
||||
* @pdev: pci device of VGA card or NULL for system default
|
||||
* @rsrc: but mask of resource to release
|
||||
*
|
||||
* This function releases resources previously locked by vga_get()
|
||||
* or vga_tryget(). The resources aren't disabled right away, so
|
||||
* that a subsequence vga_get() on the same card will succeed
|
||||
* immediately. Resources have a counter, so locks are only
|
||||
* released if the counter reaches 0.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_VGA_ARB)
|
||||
extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
|
||||
#else
|
||||
|
@ -168,25 +122,6 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* vga_default_device
|
||||
*
|
||||
* This can be defined by the platform. The default implementation
|
||||
* is rather dumb and will probably only work properly on single
|
||||
* vga card setups and/or x86 platforms.
|
||||
*
|
||||
* If your VGA default device is not PCI, you'll have to return
|
||||
* NULL here. In this case, I assume it will not conflict with
|
||||
* any PCI card. If this is not true, I'll have to define two archs
|
||||
* hooks for enabling/disabling the VGA default device if that is
|
||||
* possible. This may be a problem with real _ISA_ VGA cards, in
|
||||
* addition to a PCI one. I don't know at this point how to deal
|
||||
* with that card. Can theirs IOs be disabled at all ? If not, then
|
||||
* I suppose it's a matter of having the proper arch hook telling
|
||||
* us about it, so we basically never allow anybody to succeed a
|
||||
* vga_get()...
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_VGA_ARB
|
||||
extern struct pci_dev *vga_default_device(void);
|
||||
extern void vga_set_default_device(struct pci_dev *pdev);
|
||||
|
@ -195,14 +130,11 @@ static inline struct pci_dev *vga_default_device(void) { return NULL; };
|
|||
static inline void vga_set_default_device(struct pci_dev *pdev) { };
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vga_conflicts
|
||||
*
|
||||
* Architectures should define this if they have several
|
||||
* independent PCI domains that can afford concurrent VGA
|
||||
* decoding
|
||||
/*
|
||||
* Architectures should define this if they have several
|
||||
* independent PCI domains that can afford concurrent VGA
|
||||
* decoding
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_HAS_VGA_CONFLICT
|
||||
static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
|
||||
{
|
||||
|
@ -210,34 +142,6 @@ static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vga_client_register
|
||||
*
|
||||
* @pdev: pci device of the VGA client
|
||||
* @cookie: client cookie to be used in callbacks
|
||||
* @irq_set_state: irq state change callback
|
||||
* @set_vga_decode: vga decode change callback
|
||||
*
|
||||
* return value: 0 on success, -1 on failure
|
||||
* Register a client with the VGA arbitration logic
|
||||
*
|
||||
* Clients have two callback mechanisms they can use.
|
||||
* irq enable/disable callback -
|
||||
* If a client can't disable its GPUs VGA resources, then we
|
||||
* need to be able to ask it to turn off its irqs when we
|
||||
* turn off its mem and io decoding.
|
||||
* set_vga_decode
|
||||
* If a client can disable its GPU VGA resource, it will
|
||||
* get a callback from this to set the encode/decode state
|
||||
*
|
||||
* Rationale: we cannot disable VGA decode resources unconditionally
|
||||
* some single GPU laptops seem to require ACPI or BIOS access to the
|
||||
* VGA registers to control things like backlights etc.
|
||||
* Hopefully newer multi-GPU laptops do something saner, and desktops
|
||||
* won't have any special ACPI for this.
|
||||
* They driver will get a callback when VGA arbitration is first used
|
||||
* by userspace since we some older X servers have issues.
|
||||
*/
|
||||
#if defined(CONFIG_VGA_ARB)
|
||||
int vga_client_register(struct pci_dev *pdev, void *cookie,
|
||||
void (*irq_set_state)(void *cookie, bool state),
|
||||
|
|
Loading…
Reference in New Issue