Merge remote-tracking branch 'airlied/drm-next' into HEAD
Backmerge drm-next so that I can keep merging patches. Specifically I want: - atomic stuff, yay! - eld parsing patch from Jani. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
This commit is contained in:
commit
eb84f976c8
|
@ -994,6 +994,10 @@ int max_width, max_height;</synopsis>
|
|||
<title>Display Modes Function Reference</title>
|
||||
!Iinclude/drm/drm_modes.h
|
||||
!Edrivers/gpu/drm/drm_modes.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Atomic Mode Setting Function Reference</title>
|
||||
!Edrivers/gpu/drm/drm_atomic.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Frame Buffer Creation</title>
|
||||
|
@ -1825,6 +1829,10 @@ void intel_crt_init(struct drm_device *dev)
|
|||
<sect2>
|
||||
<title>KMS API Functions</title>
|
||||
!Edrivers/gpu/drm/drm_crtc.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>KMS Data Structures</title>
|
||||
!Iinclude/drm/drm_crtc.h
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>KMS Locking</title>
|
||||
|
@ -2315,9 +2323,26 @@ void intel_crt_init(struct drm_device *dev)
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Atomic Modeset Helper Functions Reference</title>
|
||||
<sect3>
|
||||
<title>Overview</title>
|
||||
!Pdrivers/gpu/drm/drm_atomic_helper.c overview
|
||||
</sect3>
|
||||
<sect3>
|
||||
<title>Implementing Asynchronous Atomic Commit</title>
|
||||
!Pdrivers/gpu/drm/drm_atomic_helper.c implementing async commit
|
||||
</sect3>
|
||||
<sect3>
|
||||
<title>Atomic State Reset and Initialization</title>
|
||||
!Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization
|
||||
</sect3>
|
||||
!Edrivers/gpu/drm/drm_atomic_helper.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Modeset Helper Functions Reference</title>
|
||||
!Edrivers/gpu/drm/drm_crtc_helper.c
|
||||
!Pdrivers/gpu/drm/drm_crtc_helper.c overview
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Output Probing Helper Functions Reference</title>
|
||||
|
@ -2371,7 +2396,8 @@ void intel_crt_init(struct drm_device *dev)
|
|||
</sect2>
|
||||
<sect2>
|
||||
<title id="drm-kms-planehelpers">Plane Helper Reference</title>
|
||||
!Edrivers/gpu/drm/drm_plane_helper.c Plane Helpers
|
||||
!Edrivers/gpu/drm/drm_plane_helper.c
|
||||
!Pdrivers/gpu/drm/drm_plane_helper.c overview
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
|
@ -2508,7 +2534,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
</tr>
|
||||
<tr>
|
||||
<td rowspan="21" valign="top" >DRM</td>
|
||||
<td rowspan="2" valign="top" >Generic</td>
|
||||
<td rowspan="3" valign="top" >Generic</td>
|
||||
<td valign="top" >“EDID”</td>
|
||||
<td valign="top" >BLOB | IMMUTABLE</td>
|
||||
<td valign="top" >0</td>
|
||||
|
@ -2523,6 +2549,13 @@ void intel_crt_init(struct drm_device *dev)
|
|||
<td valign="top" >Contains DPMS operation mode value.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“PATH”</td>
|
||||
<td valign="top" >BLOB | IMMUTABLE</td>
|
||||
<td valign="top" >0</td>
|
||||
<td valign="top" >Connector</td>
|
||||
<td valign="top" >Contains topology path to a connector.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1" valign="top" >Plane</td>
|
||||
<td valign="top" >“type”</td>
|
||||
<td valign="top" >ENUM | IMMUTABLE</td>
|
||||
|
|
|
@ -14,7 +14,7 @@ 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_modeset_lock.o drm_atomic.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
||||
|
@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o
|
|||
drm-$(CONFIG_OF) += drm_of.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_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||
drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
************************************************************
|
||||
* For the very latest on DRI development, please see: *
|
||||
* http://dri.freedesktop.org/ *
|
||||
************************************************************
|
||||
|
||||
The Direct Rendering Manager (drm) is a device-independent kernel-level
|
||||
device driver that provides support for the XFree86 Direct Rendering
|
||||
Infrastructure (DRI).
|
||||
|
||||
The DRM supports the Direct Rendering Infrastructure (DRI) in four major
|
||||
ways:
|
||||
|
||||
1. The DRM provides synchronized access to the graphics hardware via
|
||||
the use of an optimized two-tiered lock.
|
||||
|
||||
2. The DRM enforces the DRI security policy for access to the graphics
|
||||
hardware by only allowing authenticated X11 clients access to
|
||||
restricted regions of memory.
|
||||
|
||||
3. The DRM provides a generic DMA engine, complete with multiple
|
||||
queues and the ability to detect the need for an OpenGL context
|
||||
switch.
|
||||
|
||||
4. The DRM is extensible via the use of small device-specific modules
|
||||
that rely extensively on the API exported by the DRM module.
|
||||
|
||||
|
||||
Documentation on the DRI is available from:
|
||||
http://dri.freedesktop.org/wiki/Documentation
|
||||
http://sourceforge.net/project/showfiles.php?group_id=387
|
||||
http://dri.sourceforge.net/doc/
|
||||
|
||||
For specific information about kernel-level support, see:
|
||||
|
||||
The Direct Rendering Manager, Kernel Support for the Direct Rendering
|
||||
Infrastructure
|
||||
http://dri.sourceforge.net/doc/drm_low_level.html
|
||||
|
||||
Hardware Locking for the Direct Rendering Infrastructure
|
||||
http://dri.sourceforge.net/doc/hardware_locking_low_level.html
|
||||
|
||||
A Security Analysis of the Direct Rendering Infrastructure
|
||||
http://dri.sourceforge.net/doc/security_low_level.html
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "armada_crtc.h"
|
||||
#include "armada_drm.h"
|
||||
#include "armada_fb.h"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "ast_drv.h"
|
||||
|
||||
#include "ast_tables.h"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include "bochs.h"
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
static int defx = 1024;
|
||||
static int defy = 768;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include <video/cirrus.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,628 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2014 Intel Corp.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice 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 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robdclark@gmail.com>
|
||||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
static void kfree_state(struct drm_atomic_state *state)
|
||||
{
|
||||
kfree(state->connectors);
|
||||
kfree(state->connector_states);
|
||||
kfree(state->crtcs);
|
||||
kfree(state->crtc_states);
|
||||
kfree(state->planes);
|
||||
kfree(state->plane_states);
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_state_alloc - allocate atomic state
|
||||
* @dev: DRM device
|
||||
*
|
||||
* This allocates an empty atomic state to track updates.
|
||||
*/
|
||||
struct drm_atomic_state *
|
||||
drm_atomic_state_alloc(struct drm_device *dev)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
state->crtcs = kcalloc(dev->mode_config.num_crtc,
|
||||
sizeof(*state->crtcs), GFP_KERNEL);
|
||||
if (!state->crtcs)
|
||||
goto fail;
|
||||
state->crtc_states = kcalloc(dev->mode_config.num_crtc,
|
||||
sizeof(*state->crtc_states), GFP_KERNEL);
|
||||
if (!state->crtc_states)
|
||||
goto fail;
|
||||
state->planes = kcalloc(dev->mode_config.num_total_plane,
|
||||
sizeof(*state->planes), GFP_KERNEL);
|
||||
if (!state->planes)
|
||||
goto fail;
|
||||
state->plane_states = kcalloc(dev->mode_config.num_total_plane,
|
||||
sizeof(*state->plane_states), GFP_KERNEL);
|
||||
if (!state->plane_states)
|
||||
goto fail;
|
||||
state->connectors = kcalloc(dev->mode_config.num_connector,
|
||||
sizeof(*state->connectors),
|
||||
GFP_KERNEL);
|
||||
if (!state->connectors)
|
||||
goto fail;
|
||||
state->connector_states = kcalloc(dev->mode_config.num_connector,
|
||||
sizeof(*state->connector_states),
|
||||
GFP_KERNEL);
|
||||
if (!state->connector_states)
|
||||
goto fail;
|
||||
|
||||
state->dev = dev;
|
||||
|
||||
DRM_DEBUG_KMS("Allocate atomic state %p\n", state);
|
||||
|
||||
return state;
|
||||
fail:
|
||||
kfree_state(state);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_alloc);
|
||||
|
||||
/**
|
||||
* drm_atomic_state_clear - clear state object
|
||||
* @state: atomic state
|
||||
*
|
||||
* When the w/w mutex algorithm detects a deadlock we need to back off and drop
|
||||
* all locks. So someone else could sneak in and change the current modeset
|
||||
* configuration. Which means that all the state assembled in @state is no
|
||||
* longer an atomic update to the current state, but to some arbitrary earlier
|
||||
* state. Which could break assumptions the driver's ->atomic_check likely
|
||||
* relies on.
|
||||
*
|
||||
* Hence we must clear all cached state and completely start over, using this
|
||||
* function.
|
||||
*/
|
||||
void drm_atomic_state_clear(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("Clearing atomic state %p\n", state);
|
||||
|
||||
for (i = 0; i < dev->mode_config.num_connector; i++) {
|
||||
struct drm_connector *connector = state->connectors[i];
|
||||
|
||||
if (!connector)
|
||||
continue;
|
||||
|
||||
connector->funcs->atomic_destroy_state(connector,
|
||||
state->connector_states[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->mode_config.num_crtc; i++) {
|
||||
struct drm_crtc *crtc = state->crtcs[i];
|
||||
|
||||
if (!crtc)
|
||||
continue;
|
||||
|
||||
crtc->funcs->atomic_destroy_state(crtc,
|
||||
state->crtc_states[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->mode_config.num_total_plane; i++) {
|
||||
struct drm_plane *plane = state->planes[i];
|
||||
|
||||
if (!plane)
|
||||
continue;
|
||||
|
||||
plane->funcs->atomic_destroy_state(plane,
|
||||
state->plane_states[i]);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_clear);
|
||||
|
||||
/**
|
||||
* drm_atomic_state_free - free all memory for an atomic state
|
||||
* @state: atomic state to deallocate
|
||||
*
|
||||
* This frees all memory associated with an atomic state, including all the
|
||||
* per-object state for planes, crtcs and connectors.
|
||||
*/
|
||||
void drm_atomic_state_free(struct drm_atomic_state *state)
|
||||
{
|
||||
drm_atomic_state_clear(state);
|
||||
|
||||
DRM_DEBUG_KMS("Freeing atomic state %p\n", state);
|
||||
|
||||
kfree_state(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_state_free);
|
||||
|
||||
/**
|
||||
* drm_atomic_get_crtc_state - get crtc state
|
||||
* @state: global atomic state object
|
||||
* @crtc: crtc to get state object for
|
||||
*
|
||||
* This function returns the crtc state for the given crtc, allocating it if
|
||||
* needed. It will also grab the relevant crtc lock to make sure that the state
|
||||
* is consistent.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Either the allocated state or the error code encoded into the pointer. When
|
||||
* the error is EDEADLK then the w/w mutex code has detected a deadlock and the
|
||||
* entire atomic sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
struct drm_crtc_state *
|
||||
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
int ret, index;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
index = drm_crtc_index(crtc);
|
||||
|
||||
if (state->crtc_states[index])
|
||||
return state->crtc_states[index];
|
||||
|
||||
ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
|
||||
if (!crtc_state)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
state->crtc_states[index] = crtc_state;
|
||||
state->crtcs[index] = crtc;
|
||||
crtc_state->state = state;
|
||||
|
||||
DRM_DEBUG_KMS("Added [CRTC:%d] %p state to %p\n",
|
||||
crtc->base.id, crtc_state, state);
|
||||
|
||||
return crtc_state;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_get_crtc_state);
|
||||
|
||||
/**
|
||||
* drm_atomic_get_plane_state - get plane state
|
||||
* @state: global atomic state object
|
||||
* @plane: plane to get state object for
|
||||
*
|
||||
* This function returns the plane state for the given plane, allocating it if
|
||||
* needed. It will also grab the relevant plane lock to make sure that the state
|
||||
* is consistent.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Either the allocated state or the error code encoded into the pointer. When
|
||||
* the error is EDEADLK then the w/w mutex code has detected a deadlock and the
|
||||
* entire atomic sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
struct drm_plane_state *
|
||||
drm_atomic_get_plane_state(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane)
|
||||
{
|
||||
int ret, index;
|
||||
struct drm_plane_state *plane_state;
|
||||
|
||||
index = drm_plane_index(plane);
|
||||
|
||||
if (state->plane_states[index])
|
||||
return state->plane_states[index];
|
||||
|
||||
/*
|
||||
* TODO: We currently don't have per-plane mutexes. So instead of trying
|
||||
* crazy tricks with deferring plane->crtc and hoping for the best just
|
||||
* grab all crtc locks. Once we have per-plane locks we must update this
|
||||
* to only take the plane mutex.
|
||||
*/
|
||||
ret = drm_modeset_lock_all_crtcs(state->dev, state->acquire_ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
plane_state = plane->funcs->atomic_duplicate_state(plane);
|
||||
if (!plane_state)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
state->plane_states[index] = plane_state;
|
||||
state->planes[index] = plane;
|
||||
plane_state->state = state;
|
||||
|
||||
DRM_DEBUG_KMS("Added [PLANE:%d] %p state to %p\n",
|
||||
plane->base.id, plane_state, state);
|
||||
|
||||
if (plane_state->crtc) {
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state,
|
||||
plane_state->crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return ERR_CAST(crtc_state);
|
||||
}
|
||||
|
||||
return plane_state;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_get_plane_state);
|
||||
|
||||
/**
|
||||
* drm_atomic_get_connector_state - get connector state
|
||||
* @state: global atomic state object
|
||||
* @connector: connector to get state object for
|
||||
*
|
||||
* This function returns the connector state for the given connector,
|
||||
* allocating it if needed. It will also grab the relevant connector lock to
|
||||
* make sure that the state is consistent.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Either the allocated state or the error code encoded into the pointer. When
|
||||
* the error is EDEADLK then the w/w mutex code has detected a deadlock and the
|
||||
* entire atomic sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
struct drm_connector_state *
|
||||
drm_atomic_get_connector_state(struct drm_atomic_state *state,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
int ret, index;
|
||||
struct drm_mode_config *config = &connector->dev->mode_config;
|
||||
struct drm_connector_state *connector_state;
|
||||
|
||||
index = drm_connector_index(connector);
|
||||
|
||||
if (state->connector_states[index])
|
||||
return state->connector_states[index];
|
||||
|
||||
ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
connector_state = connector->funcs->atomic_duplicate_state(connector);
|
||||
if (!connector_state)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
state->connector_states[index] = connector_state;
|
||||
state->connectors[index] = connector;
|
||||
connector_state->state = state;
|
||||
|
||||
DRM_DEBUG_KMS("Added [CONNECTOR:%d] %p state to %p\n",
|
||||
connector->base.id, connector_state, state);
|
||||
|
||||
if (connector_state->crtc) {
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state,
|
||||
connector_state->crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return ERR_CAST(crtc_state);
|
||||
}
|
||||
|
||||
return connector_state;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_get_connector_state);
|
||||
|
||||
/**
|
||||
* drm_atomic_set_crtc_for_plane - set crtc for plane
|
||||
* @plane_state: atomic state object for the plane
|
||||
* @crtc: crtc to use for the plane
|
||||
*
|
||||
* Changing the assigned crtc for a plane requires us to grab the lock and state
|
||||
* for the new crtc, as needed. This function takes care of all these details
|
||||
* besides updating the pointer in the state object itself.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
|
||||
* then the w/w mutex code has detected a deadlock and the entire atomic
|
||||
* sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
int
|
||||
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
if (crtc) {
|
||||
crtc_state = drm_atomic_get_crtc_state(plane_state->state,
|
||||
crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
}
|
||||
|
||||
plane_state->crtc = crtc;
|
||||
|
||||
if (crtc)
|
||||
DRM_DEBUG_KMS("Link plane state %p to [CRTC:%d]\n",
|
||||
plane_state, crtc->base.id);
|
||||
else
|
||||
DRM_DEBUG_KMS("Link plane state %p to [NOCRTC]\n", plane_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_set_crtc_for_plane);
|
||||
|
||||
/**
|
||||
* drm_atomic_set_fb_for_plane - set crtc for plane
|
||||
* @plane_state: atomic state object for the plane
|
||||
* @fb: fb to use for the plane
|
||||
*
|
||||
* Changing the assigned framebuffer for a plane requires us to grab a reference
|
||||
* to the new fb and drop the reference to the old fb, if there is one. This
|
||||
* function takes care of all these details besides updating the pointer in the
|
||||
* state object itself.
|
||||
*/
|
||||
void
|
||||
drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
if (plane_state->fb)
|
||||
drm_framebuffer_unreference(plane_state->fb);
|
||||
if (fb)
|
||||
drm_framebuffer_reference(fb);
|
||||
plane_state->fb = fb;
|
||||
|
||||
if (fb)
|
||||
DRM_DEBUG_KMS("Set [FB:%d] for plane state %p\n",
|
||||
fb->base.id, plane_state);
|
||||
else
|
||||
DRM_DEBUG_KMS("Set [NOFB] for plane state %p\n", plane_state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
|
||||
|
||||
/**
|
||||
* drm_atomic_set_crtc_for_connector - set crtc for connector
|
||||
* @conn_state: atomic state object for the connector
|
||||
* @crtc: crtc to use for the connector
|
||||
*
|
||||
* Changing the assigned crtc for a connector requires us to grab the lock and
|
||||
* state for the new crtc, as needed. This function takes care of all these
|
||||
* details besides updating the pointer in the state object itself.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
|
||||
* then the w/w mutex code has detected a deadlock and the entire atomic
|
||||
* sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
int
|
||||
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
if (crtc) {
|
||||
crtc_state = drm_atomic_get_crtc_state(conn_state->state, crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
}
|
||||
|
||||
conn_state->crtc = crtc;
|
||||
|
||||
if (crtc)
|
||||
DRM_DEBUG_KMS("Link connector state %p to [CRTC:%d]\n",
|
||||
conn_state, crtc->base.id);
|
||||
else
|
||||
DRM_DEBUG_KMS("Link connector state %p to [NOCRTC]\n",
|
||||
conn_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_set_crtc_for_connector);
|
||||
|
||||
/**
|
||||
* drm_atomic_add_affected_connectors - add connectors for crtc
|
||||
* @state: atomic state
|
||||
* @crtc: DRM crtc
|
||||
*
|
||||
* This function walks the current configuration and adds all connectors
|
||||
* currently using @crtc to the atomic configuration @state. Note that this
|
||||
* function must acquire the connection mutex. This can potentially cause
|
||||
* unneeded seralization if the update is just for the planes on one crtc. Hence
|
||||
* drivers and helpers should only call this when really needed (e.g. when a
|
||||
* full modeset needs to happen due to some change).
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
|
||||
* then the w/w mutex code has detected a deadlock and the entire atomic
|
||||
* sequence must be restarted. All other errors are fatal.
|
||||
*/
|
||||
int
|
||||
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_mode_config *config = &state->dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret;
|
||||
|
||||
ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_KMS("Adding all current connectors for [CRTC:%d] to %p\n",
|
||||
crtc->base.id, state);
|
||||
|
||||
/*
|
||||
* Changed connectors are already in @state, so only need to look at the
|
||||
* current configuration.
|
||||
*/
|
||||
list_for_each_entry(connector, &config->connector_list, head) {
|
||||
if (connector->state->crtc != crtc)
|
||||
continue;
|
||||
|
||||
conn_state = drm_atomic_get_connector_state(state, connector);
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_add_affected_connectors);
|
||||
|
||||
/**
|
||||
* drm_atomic_connectors_for_crtc - count number of connected outputs
|
||||
* @state: atomic state
|
||||
* @crtc: DRM crtc
|
||||
*
|
||||
* This function counts all connectors which will be connected to @crtc
|
||||
* according to @state. Useful to recompute the enable state for @crtc.
|
||||
*/
|
||||
int
|
||||
drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc)
|
||||
{
|
||||
int nconnectors = state->dev->mode_config.num_connector;
|
||||
int i, num_connected_connectors = 0;
|
||||
|
||||
for (i = 0; i < nconnectors; i++) {
|
||||
struct drm_connector_state *conn_state;
|
||||
|
||||
conn_state = state->connector_states[i];
|
||||
|
||||
if (conn_state && conn_state->crtc == crtc)
|
||||
num_connected_connectors++;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("State %p has %i connectors for [CRTC:%d]\n",
|
||||
state, num_connected_connectors, crtc->base.id);
|
||||
|
||||
return num_connected_connectors;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_connectors_for_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_legacy_backoff - locking backoff for legacy ioctls
|
||||
* @state: atomic state
|
||||
*
|
||||
* This function should be used by legacy entry points which don't understand
|
||||
* -EDEADLK semantics. For simplicity this one will grab all modeset locks after
|
||||
* the slowpath completed.
|
||||
*/
|
||||
void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
retry:
|
||||
drm_modeset_backoff(state->acquire_ctx);
|
||||
|
||||
ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
|
||||
state->acquire_ctx);
|
||||
if (ret)
|
||||
goto retry;
|
||||
ret = drm_modeset_lock_all_crtcs(state->dev,
|
||||
state->acquire_ctx);
|
||||
if (ret)
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_legacy_backoff);
|
||||
|
||||
/**
|
||||
* drm_atomic_check_only - check whether a given config would work
|
||||
* @state: atomic configuration to check
|
||||
*
|
||||
* Note that this function can return -EDEADLK if the driver needed to acquire
|
||||
* more locks but encountered a deadlock. The caller must then do the usual w/w
|
||||
* backoff dance and restart. All other errors are fatal.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int drm_atomic_check_only(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_mode_config *config = &state->dev->mode_config;
|
||||
|
||||
DRM_DEBUG_KMS("checking %p\n", state);
|
||||
|
||||
if (config->funcs->atomic_check)
|
||||
return config->funcs->atomic_check(state->dev, state);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_check_only);
|
||||
|
||||
/**
|
||||
* drm_atomic_commit - commit configuration atomically
|
||||
* @state: atomic configuration to check
|
||||
*
|
||||
* Note that this function can return -EDEADLK if the driver needed to acquire
|
||||
* more locks but encountered a deadlock. The caller must then do the usual w/w
|
||||
* backoff dance and restart. All other errors are fatal.
|
||||
*
|
||||
* Also note that on successful execution ownership of @state is transferred
|
||||
* from the caller of this function to the function itself. The caller must not
|
||||
* free or in any other way access @state. If the function fails then the caller
|
||||
* must clean up @state itself.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int drm_atomic_commit(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_mode_config *config = &state->dev->mode_config;
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_KMS("commiting %p\n", state);
|
||||
|
||||
return config->funcs->atomic_commit(state->dev, state, false);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_commit);
|
||||
|
||||
/**
|
||||
* drm_atomic_async_commit - atomic&async configuration commit
|
||||
* @state: atomic configuration to check
|
||||
*
|
||||
* Note that this function can return -EDEADLK if the driver needed to acquire
|
||||
* more locks but encountered a deadlock. The caller must then do the usual w/w
|
||||
* backoff dance and restart. All other errors are fatal.
|
||||
*
|
||||
* Also note that on successful execution ownership of @state is transferred
|
||||
* from the caller of this function to the function itself. The caller must not
|
||||
* free or in any other way access @state. If the function fails then the caller
|
||||
* must clean up @state itself.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
int drm_atomic_async_commit(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_mode_config *config = &state->dev->mode_config;
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_check_only(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_KMS("commiting %p asynchronously\n", state);
|
||||
|
||||
return config->funcs->atomic_commit(state->dev, state, true);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_async_commit);
|
File diff suppressed because it is too large
Load Diff
|
@ -766,7 +766,6 @@ static void drm_mode_remove(struct drm_connector *connector,
|
|||
/**
|
||||
* drm_connector_get_cmdline_mode - reads the user's cmdline mode
|
||||
* @connector: connector to quwery
|
||||
* @mode: returned mode
|
||||
*
|
||||
* The kernel supports per-connector configration of its consoles through
|
||||
* use of the video= parameter. This function parses that option and
|
||||
|
@ -2943,7 +2942,7 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);
|
|||
* @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 ioclt which only supported RGB formats.
|
||||
* original addfb ioctl which only supported RGB formats.
|
||||
*
|
||||
* Called by the user via ioctl.
|
||||
*
|
||||
|
@ -2955,11 +2954,9 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
{
|
||||
struct drm_mode_fb_cmd *or = data;
|
||||
struct drm_mode_fb_cmd2 r = {};
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_framebuffer *fb;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
/* Use new struct with format internally */
|
||||
/* convert to new format and call new ioctl */
|
||||
r.fb_id = or->fb_id;
|
||||
r.width = or->width;
|
||||
r.height = or->height;
|
||||
|
@ -2967,26 +2964,11 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
|
||||
r.handles[0] = or->handle;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
ret = drm_mode_addfb2(dev, &r, file_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((config->min_width > r.width) || (r.width > config->max_width))
|
||||
return -EINVAL;
|
||||
|
||||
if ((config->min_height > r.height) || (r.height > config->max_height))
|
||||
return -EINVAL;
|
||||
|
||||
fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_DEBUG_KMS("could not create framebuffer\n");
|
||||
return PTR_ERR(fb);
|
||||
}
|
||||
|
||||
mutex_lock(&file_priv->fbs_lock);
|
||||
or->fb_id = fb->base.id;
|
||||
list_add(&fb->filp_head, &file_priv->fbs);
|
||||
DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
|
||||
mutex_unlock(&file_priv->fbs_lock);
|
||||
or->fb_id = r.fb_id;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -3080,7 +3062,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
|||
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->height);
|
||||
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -3435,6 +3417,10 @@ void drm_fb_release(struct drm_file *priv)
|
|||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy.
|
||||
*
|
||||
* Note that the DRM core keeps a per-device list of properties and that, if
|
||||
* drm_mode_config_cleanup() is called, it will destroy all properties created
|
||||
* by the driver.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the newly created property on success, NULL on failure.
|
||||
*/
|
||||
|
@ -3611,7 +3597,7 @@ static struct drm_property *property_create_range(struct drm_device *dev,
|
|||
* object with drm_object_attach_property. The returned property object must be
|
||||
* freed with drm_property_destroy.
|
||||
*
|
||||
* Userspace is allowed to set any interger value in the (min, max) range
|
||||
* Userspace is allowed to set any integer value in the (min, max) range
|
||||
* inclusive.
|
||||
*
|
||||
* Returns:
|
||||
|
@ -4019,6 +4005,19 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_connector_set_path_property - set tile property on connector
|
||||
* @connector: connector to set property on.
|
||||
* @path: path to use for property.
|
||||
*
|
||||
* This creates a property to expose to userspace to specify a
|
||||
* connector path. This is mainly used for DisplayPort MST where
|
||||
* connectors have a topology and we want to allow userspace to give
|
||||
* them more meaningful names.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, errno on failure.
|
||||
*/
|
||||
int drm_mode_connector_set_path_property(struct drm_connector *connector,
|
||||
char *path)
|
||||
{
|
||||
|
|
|
@ -34,12 +34,35 @@
|
|||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* The CRTC modeset helper library provides a default set_config implementation
|
||||
* in drm_crtc_helper_set_config(). Plus a few other convenience functions using
|
||||
* the same callbacks which drivers can use to e.g. restore the modeset
|
||||
* configuration on resume with drm_helper_resume_force_mode().
|
||||
*
|
||||
* The driver callbacks are mostly compatible with the atomic modeset helpers,
|
||||
* except for the handling of the primary plane: Atomic helpers require that the
|
||||
* primary plane is implemented as a real standalone plane and not directly tied
|
||||
* to the CRTC state. For easier transition this library provides functions to
|
||||
* implement the old semantics required by the CRTC helpers using the new plane
|
||||
* and atomic helper callbacks.
|
||||
*
|
||||
* Drivers are strongly urged to convert to the atomic helpers (by way of first
|
||||
* converting to the plane helpers). New drivers must not use these functions
|
||||
* but need to implement the atomic interface instead, potentially using the
|
||||
* atomic helpers for that.
|
||||
*/
|
||||
MODULE_AUTHOR("David Airlie, Jesse Barnes");
|
||||
MODULE_DESCRIPTION("DRM KMS helper");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
@ -888,3 +911,112 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
|
|||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_resume_force_mode);
|
||||
|
||||
/**
|
||||
* drm_helper_crtc_mode_set - mode_set implementation for atomic plane helpers
|
||||
* @crtc: DRM CRTC
|
||||
* @mode: DRM display mode which userspace requested
|
||||
* @adjusted_mode: DRM display mode adjusted by ->mode_fixup callbacks
|
||||
* @x: x offset of the CRTC scanout area on the underlying framebuffer
|
||||
* @y: y offset of the CRTC scanout area on the underlying framebuffer
|
||||
* @old_fb: previous framebuffer
|
||||
*
|
||||
* This function implements a callback useable as the ->mode_set callback
|
||||
* required by the crtc helpers. Besides the atomic plane helper functions for
|
||||
* the primary plane the driver must also provide the ->mode_set_nofb callback
|
||||
* to set up the crtc.
|
||||
*
|
||||
* This is a transitional helper useful for converting drivers to the atomic
|
||||
* interfaces.
|
||||
*/
|
||||
int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
int ret;
|
||||
|
||||
if (crtc->funcs->atomic_duplicate_state)
|
||||
crtc_state = crtc->funcs->atomic_duplicate_state(crtc);
|
||||
else if (crtc->state)
|
||||
crtc_state = kmemdup(crtc->state, sizeof(*crtc_state),
|
||||
GFP_KERNEL);
|
||||
else
|
||||
crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
|
||||
if (!crtc_state)
|
||||
return -ENOMEM;
|
||||
|
||||
crtc_state->enable = true;
|
||||
crtc_state->planes_changed = true;
|
||||
crtc_state->mode_changed = true;
|
||||
drm_mode_copy(&crtc_state->mode, mode);
|
||||
drm_mode_copy(&crtc_state->adjusted_mode, adjusted_mode);
|
||||
|
||||
if (crtc_funcs->atomic_check) {
|
||||
ret = crtc_funcs->atomic_check(crtc, crtc_state);
|
||||
if (ret) {
|
||||
kfree(crtc_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
swap(crtc->state, crtc_state);
|
||||
|
||||
crtc_funcs->mode_set_nofb(crtc);
|
||||
|
||||
if (crtc_state) {
|
||||
if (crtc->funcs->atomic_destroy_state)
|
||||
crtc->funcs->atomic_destroy_state(crtc, crtc_state);
|
||||
else
|
||||
kfree(crtc_state);
|
||||
}
|
||||
|
||||
return drm_helper_crtc_mode_set_base(crtc, x, y, old_fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_crtc_mode_set);
|
||||
|
||||
/**
|
||||
* drm_helper_crtc_mode_set_base - mode_set_base implementation for atomic plane helpers
|
||||
* @crtc: DRM CRTC
|
||||
* @x: x offset of the CRTC scanout area on the underlying framebuffer
|
||||
* @y: y offset of the CRTC scanout area on the underlying framebuffer
|
||||
* @old_fb: previous framebuffer
|
||||
*
|
||||
* This function implements a callback useable as the ->mode_set_base used
|
||||
* required by the crtc helpers. The driver must provide the atomic plane helper
|
||||
* functions for the primary plane.
|
||||
*
|
||||
* This is a transitional helper useful for converting drivers to the atomic
|
||||
* interfaces.
|
||||
*/
|
||||
int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
|
||||
if (plane->funcs->atomic_duplicate_state)
|
||||
plane_state = plane->funcs->atomic_duplicate_state(plane);
|
||||
else if (plane->state)
|
||||
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
|
||||
else
|
||||
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
|
||||
if (!plane_state)
|
||||
return -ENOMEM;
|
||||
|
||||
plane_state->crtc = crtc;
|
||||
drm_atomic_set_fb_for_plane(plane_state, crtc->primary->fb);
|
||||
plane_state->crtc_x = 0;
|
||||
plane_state->crtc_y = 0;
|
||||
plane_state->crtc_h = crtc->mode.vdisplay;
|
||||
plane_state->crtc_w = crtc->mode.hdisplay;
|
||||
plane_state->src_x = x << 16;
|
||||
plane_state->src_y = y << 16;
|
||||
plane_state->src_h = crtc->mode.vdisplay << 16;
|
||||
plane_state->src_w = crtc->mode.hdisplay << 16;
|
||||
|
||||
return drm_plane_helper_commit(plane, plane_state, old_fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_crtc_mode_set_base);
|
||||
|
|
|
@ -39,198 +39,6 @@
|
|||
* blocks, ...
|
||||
*/
|
||||
|
||||
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
|
||||
static int
|
||||
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
ret = (*algo_data->aux_ch)(adapter, mode,
|
||||
write_byte, read_byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C over AUX CH
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send the address. If the I2C link is running, this 'restarts'
|
||||
* the connection with the new address, this is used for doing
|
||||
* a write followed by a read (as needed for DDC)
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_START;
|
||||
int ret;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
algo_data->address = address;
|
||||
algo_data->running = true;
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the I2C transaction. This closes out the link, sending
|
||||
* a bare address packet with the MOT bit turned off
|
||||
*/
|
||||
static void
|
||||
i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_STOP;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
if (algo_data->running) {
|
||||
(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
algo_data->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single byte to the current I2C address, the
|
||||
* the I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a single byte from the current I2C address, the
|
||||
* I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
int ret = 0;
|
||||
bool reading = false;
|
||||
int m;
|
||||
int b;
|
||||
|
||||
for (m = 0; m < num; m++) {
|
||||
u16 len = msgs[m].len;
|
||||
u8 *buf = msgs[m].buf;
|
||||
reading = (msgs[m].flags & I2C_M_RD) != 0;
|
||||
ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (reading) {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
ret = num;
|
||||
i2c_algo_dp_aux_stop(adapter, reading);
|
||||
DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
I2C_FUNC_10BIT_ADDR;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_dp_aux_algo = {
|
||||
.master_xfer = i2c_algo_dp_aux_xfer,
|
||||
.functionality = i2c_algo_dp_aux_functionality,
|
||||
};
|
||||
|
||||
static void
|
||||
i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
(void) i2c_algo_dp_aux_address(adapter, 0, false);
|
||||
(void) i2c_algo_dp_aux_stop(adapter, false);
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
adapter->algo = &i2c_dp_aux_algo;
|
||||
adapter->retries = 3;
|
||||
i2c_dp_aux_reset_bus(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i2c_dp_aux_add_bus() - register an i2c adapter using the aux ch helper
|
||||
* @adapter: i2c adapter to register
|
||||
*
|
||||
* This registers an i2c adapter that uses dp aux channel as it's underlaying
|
||||
* transport. The driver needs to fill out the &i2c_algo_dp_aux_data structure
|
||||
* and store it in the algo_data member of the @adapter argument. This will be
|
||||
* used by the i2c over dp aux algorithm to drive the hardware.
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, -ERRNO on failure.
|
||||
*
|
||||
* IMPORTANT:
|
||||
* This interface is deprecated, please switch to the new dp aux helpers and
|
||||
* drm_dp_aux_register().
|
||||
*/
|
||||
int
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = i2c_dp_aux_prepare_bus(adapter);
|
||||
if (error)
|
||||
return error;
|
||||
error = i2c_add_adapter(adapter);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_dp_aux_add_bus);
|
||||
|
||||
/* Helpers for DP link training */
|
||||
static u8 dp_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
|
||||
{
|
||||
|
@ -654,10 +462,12 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
|
||||
case DP_AUX_I2C_REPLY_NACK:
|
||||
DRM_DEBUG_KMS("I2C nack\n");
|
||||
aux->i2c_nack_count++;
|
||||
return -EREMOTEIO;
|
||||
|
||||
case DP_AUX_I2C_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("I2C defer\n");
|
||||
aux->i2c_defer_count++;
|
||||
usleep_range(400, 500);
|
||||
continue;
|
||||
|
||||
|
|
|
@ -1011,19 +1011,20 @@ static void drm_dp_check_port_guid(struct drm_dp_mst_branch *mstb,
|
|||
|
||||
static void build_mst_prop_path(struct drm_dp_mst_port *port,
|
||||
struct drm_dp_mst_branch *mstb,
|
||||
char *proppath)
|
||||
char *proppath,
|
||||
size_t proppath_size)
|
||||
{
|
||||
int i;
|
||||
char temp[8];
|
||||
snprintf(proppath, 255, "mst:%d", mstb->mgr->conn_base_id);
|
||||
snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
|
||||
for (i = 0; i < (mstb->lct - 1); i++) {
|
||||
int shift = (i % 2) ? 0 : 4;
|
||||
int port_num = mstb->rad[i / 2] >> shift;
|
||||
snprintf(temp, 8, "-%d", port_num);
|
||||
strncat(proppath, temp, 255);
|
||||
snprintf(temp, sizeof(temp), "-%d", port_num);
|
||||
strlcat(proppath, temp, proppath_size);
|
||||
}
|
||||
snprintf(temp, 8, "-%d", port->port_num);
|
||||
strncat(proppath, temp, 255);
|
||||
snprintf(temp, sizeof(temp), "-%d", port->port_num);
|
||||
strlcat(proppath, temp, proppath_size);
|
||||
}
|
||||
|
||||
static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
|
||||
|
@ -1094,7 +1095,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,
|
|||
|
||||
if (created && !port->input) {
|
||||
char proppath[255];
|
||||
build_mst_prop_path(port, mstb, proppath);
|
||||
build_mst_prop_path(port, mstb, proppath, sizeof(proppath));
|
||||
port->connector = (*mstb->mgr->cbs->add_connector)(mstb->mgr, port, proppath);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ static struct idr drm_minors_idr;
|
|||
struct class *drm_class;
|
||||
static struct dentry *drm_debugfs_root;
|
||||
|
||||
void drm_err(const char *func, const char *format, ...)
|
||||
void drm_err(const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
|
@ -66,7 +66,8 @@ void drm_err(const char *func, const char *format, ...)
|
|||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk(KERN_ERR "[" DRM_NAME ":%s] *ERROR* %pV", func, &vaf);
|
||||
printk(KERN_ERR "[" DRM_NAME ":%pf] *ERROR* %pV",
|
||||
__builtin_return_address(0), &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
|
|
@ -1570,7 +1570,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
|
|||
modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
if (modeset->num_connectors == 0) {
|
||||
BUG_ON(modeset->fb);
|
||||
BUG_ON(modeset->num_connectors);
|
||||
if (modeset->mode)
|
||||
drm_mode_destroy(dev, modeset->mode);
|
||||
modeset->mode = NULL;
|
||||
|
|
|
@ -515,10 +515,12 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
size_t total;
|
||||
ssize_t ret;
|
||||
|
||||
ret = wait_event_interruptible(file_priv->event_wait,
|
||||
!list_empty(&file_priv->event_list));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((filp->f_flags & O_NONBLOCK) == 0) {
|
||||
ret = wait_event_interruptible(file_priv->event_wait,
|
||||
!list_empty(&file_priv->event_list));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
while (drm_dequeue_event(file_priv, total, count, &e)) {
|
||||
|
@ -532,7 +534,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
e->destroy(e);
|
||||
}
|
||||
|
||||
return total;
|
||||
return total ?: -EAGAIN;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_read);
|
||||
|
||||
|
|
|
@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
|
|||
*
|
||||
* This functions restores the vblank interrupt state captured with
|
||||
* drm_vblank_off() again. Note that calls to drm_vblank_on() and
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionaly called
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionally called
|
||||
* in driver load code to reflect the current hardware state of the crtc.
|
||||
*
|
||||
* This is the legacy version of drm_crtc_vblank_on().
|
||||
|
@ -1237,7 +1237,7 @@ EXPORT_SYMBOL(drm_vblank_on);
|
|||
*
|
||||
* This functions restores the vblank interrupt state captured with
|
||||
* drm_vblank_off() again. Note that calls to drm_vblank_on() and
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionaly called
|
||||
* drm_vblank_off() can be unbalanced and so can also be unconditionally called
|
||||
* in driver load code to reflect the current hardware state of the crtc.
|
||||
*
|
||||
* This is the native kms version of drm_vblank_on().
|
||||
|
|
|
@ -914,7 +914,7 @@ EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
|
|||
*
|
||||
* This function is a helper which can be used to validate modes against size
|
||||
* limitations of the DRM device/connector. If a mode is too big its status
|
||||
* memeber is updated with the appropriate validation failure code. The list
|
||||
* member is updated with the appropriate validation failure code. The list
|
||||
* itself is not changed.
|
||||
*/
|
||||
void drm_mode_validate_size(struct drm_device *dev,
|
||||
|
|
|
@ -27,10 +27,38 @@
|
|||
#include <drm/drmP.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
|
||||
#define SUBPIXEL_MASK 0xffff
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* This helper library has two parts. The first part has support to implement
|
||||
* primary plane support on top of the normal CRTC configuration interface.
|
||||
* Since the legacy ->set_config interface ties the primary plane together with
|
||||
* the CRTC state this does not allow userspace to disable the primary plane
|
||||
* itself. To avoid too much duplicated code use
|
||||
* drm_plane_helper_check_update() which can be used to enforce the same
|
||||
* restrictions as primary planes had thus. The default primary plane only
|
||||
* expose XRBG8888 and ARGB8888 as valid pixel formats for the attached
|
||||
* framebuffer.
|
||||
*
|
||||
* Drivers are highly recommended to implement proper support for primary
|
||||
* planes, and newly merged drivers must not rely upon these transitional
|
||||
* helpers.
|
||||
*
|
||||
* The second part also implements transitional helpers which allow drivers to
|
||||
* gradually switch to the atomic helper infrastructure for plane updates. Once
|
||||
* that switch is complete drivers shouldn't use these any longer, instead using
|
||||
* the proper legacy implementations for update and disable plane hooks provided
|
||||
* by the atomic helpers.
|
||||
*
|
||||
* Again drivers are strongly urged to switch to the new interfaces.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -374,3 +402,171 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
|||
return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs);
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct drm_plane_helper_funcs *plane_funcs;
|
||||
struct drm_crtc *crtc[2];
|
||||
struct drm_crtc_helper_funcs *crtc_funcs[2];
|
||||
int i, ret = 0;
|
||||
|
||||
plane_funcs = plane->helper_private;
|
||||
|
||||
/* Since this is a transitional helper we can't assume that plane->state
|
||||
* is always valid. Hence we need to use plane->crtc instead of
|
||||
* plane->state->crtc as the old crtc. */
|
||||
crtc[0] = plane->crtc;
|
||||
crtc[1] = crtc[0] != plane_state->crtc ? plane_state->crtc : NULL;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
crtc_funcs[i] = crtc[i] ? crtc[i]->helper_private : NULL;
|
||||
|
||||
if (plane_funcs->atomic_check) {
|
||||
ret = plane_funcs->atomic_check(plane, plane_state);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (plane_funcs->prepare_fb && plane_state->fb) {
|
||||
ret = plane_funcs->prepare_fb(plane, plane_state->fb);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Point of no return, commit sw state. */
|
||||
swap(plane->state, plane_state);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (crtc_funcs[i] && crtc_funcs[i]->atomic_begin)
|
||||
crtc_funcs[i]->atomic_begin(crtc[i]);
|
||||
}
|
||||
|
||||
plane_funcs->atomic_update(plane);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (crtc_funcs[i] && crtc_funcs[i]->atomic_flush)
|
||||
crtc_funcs[i]->atomic_flush(crtc[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (!crtc[i])
|
||||
continue;
|
||||
|
||||
/* There's no other way to figure out whether the crtc is running. */
|
||||
ret = drm_crtc_vblank_get(crtc[i]);
|
||||
if (ret == 0) {
|
||||
drm_crtc_wait_one_vblank(crtc[i]);
|
||||
drm_crtc_vblank_put(crtc[i]);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (plane_funcs->cleanup_fb && old_fb)
|
||||
plane_funcs->cleanup_fb(plane, old_fb);
|
||||
out:
|
||||
if (plane_state) {
|
||||
if (plane->funcs->atomic_destroy_state)
|
||||
plane->funcs->atomic_destroy_state(plane, plane_state);
|
||||
else
|
||||
drm_atomic_helper_plane_destroy_state(plane, plane_state);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_helper_update() - Helper for primary plane update
|
||||
* @plane: plane object to update
|
||||
* @crtc: owning CRTC of owning plane
|
||||
* @fb: framebuffer to flip onto plane
|
||||
* @crtc_x: x offset of primary plane on crtc
|
||||
* @crtc_y: y offset of primary plane on crtc
|
||||
* @crtc_w: width of primary plane rectangle on crtc
|
||||
* @crtc_h: height of primary plane rectangle on crtc
|
||||
* @src_x: x offset of @fb for panning
|
||||
* @src_y: y offset of @fb for panning
|
||||
* @src_w: width of source rectangle in @fb
|
||||
* @src_h: height of source rectangle in @fb
|
||||
*
|
||||
* Provides a default plane update handler using the atomic plane update
|
||||
* functions. It is fully left to the driver to check plane constraints and
|
||||
* handle corner-cases like a fully occluded or otherwise invisible plane.
|
||||
*
|
||||
* This is useful for piecewise transitioning of a driver to the atomic helpers.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
{
|
||||
struct drm_plane_state *plane_state;
|
||||
|
||||
if (plane->funcs->atomic_duplicate_state)
|
||||
plane_state = plane->funcs->atomic_duplicate_state(plane);
|
||||
else if (plane->state)
|
||||
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
|
||||
else
|
||||
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
|
||||
if (!plane_state)
|
||||
return -ENOMEM;
|
||||
|
||||
plane_state->crtc = crtc;
|
||||
drm_atomic_set_fb_for_plane(plane_state, fb);
|
||||
plane_state->crtc_x = crtc_x;
|
||||
plane_state->crtc_y = crtc_y;
|
||||
plane_state->crtc_h = crtc_h;
|
||||
plane_state->crtc_w = crtc_w;
|
||||
plane_state->src_x = src_x;
|
||||
plane_state->src_y = src_y;
|
||||
plane_state->src_h = src_h;
|
||||
plane_state->src_w = src_w;
|
||||
|
||||
return drm_plane_helper_commit(plane, plane_state, plane->fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_helper_update);
|
||||
|
||||
/**
|
||||
* drm_plane_helper_disable() - Helper for primary plane disable
|
||||
* @plane: plane to disable
|
||||
*
|
||||
* Provides a default plane disable handler using the atomic plane update
|
||||
* functions. It is fully left to the driver to check plane constraints and
|
||||
* handle corner-cases like a fully occluded or otherwise invisible plane.
|
||||
*
|
||||
* This is useful for piecewise transitioning of a driver to the atomic helpers.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
int drm_plane_helper_disable(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane_state *plane_state;
|
||||
|
||||
/* crtc helpers love to call disable functions for already disabled hw
|
||||
* functions. So cope with that. */
|
||||
if (!plane->crtc)
|
||||
return 0;
|
||||
|
||||
if (plane->funcs->atomic_duplicate_state)
|
||||
plane_state = plane->funcs->atomic_duplicate_state(plane);
|
||||
else if (plane->state)
|
||||
plane_state = drm_atomic_helper_plane_duplicate_state(plane);
|
||||
else
|
||||
plane_state = kzalloc(sizeof(*plane_state), GFP_KERNEL);
|
||||
if (!plane_state)
|
||||
return -ENOMEM;
|
||||
|
||||
plane_state->crtc = NULL;
|
||||
drm_atomic_set_fb_for_plane(plane_state, NULL);
|
||||
|
||||
return drm_plane_helper_commit(plane, plane_state, plane->fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_helper_disable);
|
||||
|
|
|
@ -328,7 +328,7 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
|
|||
*/
|
||||
|
||||
/**
|
||||
* drm_gem_prime_export - helper library implemention of the export callback
|
||||
* drm_gem_prime_export - helper library implementation of the export callback
|
||||
* @dev: drm_device to export from
|
||||
* @obj: GEM object to export
|
||||
* @flags: flags like DRM_CLOEXEC
|
||||
|
@ -483,7 +483,7 @@ out_unlock:
|
|||
EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
|
||||
|
||||
/**
|
||||
* drm_gem_prime_import - helper library implemention of the import callback
|
||||
* drm_gem_prime_import - helper library implementation of the import callback
|
||||
* @dev: drm_device to import into
|
||||
* @dma_buf: dma-buf object to import
|
||||
*
|
||||
|
|
|
@ -118,7 +118,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||
mode->status = MODE_UNVERIFIED;
|
||||
|
||||
if (connector->force) {
|
||||
if (connector->force == DRM_FORCE_ON)
|
||||
if (connector->force == DRM_FORCE_ON ||
|
||||
connector->force == DRM_FORCE_ON_DIGITAL)
|
||||
connector->status = connector_status_connected;
|
||||
else
|
||||
connector->status = connector_status_disconnected;
|
||||
|
|
|
@ -37,6 +37,201 @@
|
|||
#include "gma_display.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
/**
|
||||
* struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
|
||||
* aux algorithm
|
||||
* @running: set by the algo indicating whether an i2c is ongoing or whether
|
||||
* the i2c bus is quiescent
|
||||
* @address: i2c target address for the currently ongoing transfer
|
||||
* @aux_ch: driver callback to transfer a single byte of the i2c payload
|
||||
*/
|
||||
struct i2c_algo_dp_aux_data {
|
||||
bool running;
|
||||
u16 address;
|
||||
int (*aux_ch) (struct i2c_adapter *adapter,
|
||||
int mode, uint8_t write_byte,
|
||||
uint8_t *read_byte);
|
||||
};
|
||||
|
||||
/* Run a single AUX_CH I2C transaction, writing/reading data as necessary */
|
||||
static int
|
||||
i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode,
|
||||
uint8_t write_byte, uint8_t *read_byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
ret = (*algo_data->aux_ch)(adapter, mode,
|
||||
write_byte, read_byte);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C over AUX CH
|
||||
*/
|
||||
|
||||
/*
|
||||
* Send the address. If the I2C link is running, this 'restarts'
|
||||
* the connection with the new address, this is used for doing
|
||||
* a write followed by a read (as needed for DDC)
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_START;
|
||||
int ret;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
algo_data->address = address;
|
||||
algo_data->running = true;
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the I2C transaction. This closes out the link, sending
|
||||
* a bare address packet with the MOT bit turned off
|
||||
*/
|
||||
static void
|
||||
i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int mode = MODE_I2C_STOP;
|
||||
|
||||
if (reading)
|
||||
mode |= MODE_I2C_READ;
|
||||
else
|
||||
mode |= MODE_I2C_WRITE;
|
||||
if (algo_data->running) {
|
||||
(void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL);
|
||||
algo_data->running = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single byte to the current I2C address, the
|
||||
* the I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a single byte from the current I2C address, the
|
||||
* I2C link must be running or this returns -EIO
|
||||
*/
|
||||
static int
|
||||
i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret)
|
||||
{
|
||||
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
|
||||
int ret;
|
||||
|
||||
if (!algo_data->running)
|
||||
return -EIO;
|
||||
|
||||
ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
int ret = 0;
|
||||
bool reading = false;
|
||||
int m;
|
||||
int b;
|
||||
|
||||
for (m = 0; m < num; m++) {
|
||||
u16 len = msgs[m].len;
|
||||
u8 *buf = msgs[m].buf;
|
||||
reading = (msgs[m].flags & I2C_M_RD) != 0;
|
||||
ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (reading) {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (b = 0; b < len; b++) {
|
||||
ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
if (ret >= 0)
|
||||
ret = num;
|
||||
i2c_algo_dp_aux_stop(adapter, reading);
|
||||
DRM_DEBUG_KMS("dp_aux_xfer return %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
I2C_FUNC_10BIT_ADDR;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm i2c_dp_aux_algo = {
|
||||
.master_xfer = i2c_algo_dp_aux_xfer,
|
||||
.functionality = i2c_algo_dp_aux_functionality,
|
||||
};
|
||||
|
||||
static void
|
||||
i2c_dp_aux_reset_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
(void) i2c_algo_dp_aux_address(adapter, 0, false);
|
||||
(void) i2c_algo_dp_aux_stop(adapter, false);
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
adapter->algo = &i2c_dp_aux_algo;
|
||||
adapter->retries = 3;
|
||||
i2c_dp_aux_reset_bus(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This is the old dp aux helper, gma500 is the last driver that needs to
|
||||
* be ported over to the new helper code in drm_dp_helper.c like i915 or radeon.
|
||||
*/
|
||||
static int __deprecated
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = i2c_dp_aux_prepare_bus(adapter);
|
||||
if (error)
|
||||
return error;
|
||||
error = i2c_add_adapter(adapter);
|
||||
return error;
|
||||
}
|
||||
|
||||
#define _wait_for(COND, MS, W) ({ \
|
||||
unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
|
||||
int ret__ = 0; \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "framebuffer.h"
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_drv.h"
|
||||
|
|
|
@ -1631,57 +1631,8 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
|
|||
return !list_empty(&connector->probed_modes);
|
||||
}
|
||||
|
||||
static void
|
||||
psb_intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (psb_intel_sdvo_connector->left)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->left);
|
||||
if (psb_intel_sdvo_connector->right)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->right);
|
||||
if (psb_intel_sdvo_connector->top)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->top);
|
||||
if (psb_intel_sdvo_connector->bottom)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->bottom);
|
||||
if (psb_intel_sdvo_connector->hpos)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->hpos);
|
||||
if (psb_intel_sdvo_connector->vpos)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->vpos);
|
||||
if (psb_intel_sdvo_connector->saturation)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->saturation);
|
||||
if (psb_intel_sdvo_connector->contrast)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->contrast);
|
||||
if (psb_intel_sdvo_connector->hue)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->hue);
|
||||
if (psb_intel_sdvo_connector->sharpness)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->sharpness);
|
||||
if (psb_intel_sdvo_connector->flicker_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter);
|
||||
if (psb_intel_sdvo_connector->flicker_filter_2d)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_2d);
|
||||
if (psb_intel_sdvo_connector->flicker_filter_adaptive)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->flicker_filter_adaptive);
|
||||
if (psb_intel_sdvo_connector->tv_luma_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->tv_luma_filter);
|
||||
if (psb_intel_sdvo_connector->tv_chroma_filter)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->tv_chroma_filter);
|
||||
if (psb_intel_sdvo_connector->dot_crawl)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->dot_crawl);
|
||||
if (psb_intel_sdvo_connector->brightness)
|
||||
drm_property_destroy(dev, psb_intel_sdvo_connector->brightness);
|
||||
}
|
||||
|
||||
static void psb_intel_sdvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_sdvo_connector *psb_intel_sdvo_connector = to_psb_intel_sdvo_connector(connector);
|
||||
|
||||
if (psb_intel_sdvo_connector->tv_format)
|
||||
drm_property_destroy(connector->dev,
|
||||
psb_intel_sdvo_connector->tv_format);
|
||||
|
||||
psb_intel_sdvo_destroy_enhance_property(connector);
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
* those commands required by the parser. This generally works because command
|
||||
* opcode ranges have standard command length encodings. So for commands that
|
||||
* the parser does not need to check, it can easily skip them. This is
|
||||
* implementated via a per-ring length decoding vfunc.
|
||||
* implemented via a per-ring length decoding vfunc.
|
||||
*
|
||||
* Unfortunately, there are a number of commands that do not follow the standard
|
||||
* length encoding for their opcode range, primarily amongst the MI_* commands.
|
||||
|
@ -843,7 +843,7 @@ finish:
|
|||
* @ring: the ring in question
|
||||
*
|
||||
* Only certain platforms require software batch buffer command parsing, and
|
||||
* only when enabled via module paramter.
|
||||
* only when enabled via module parameter.
|
||||
*
|
||||
* Return: true if the ring requires software command parsing
|
||||
*/
|
||||
|
|
|
@ -672,7 +672,7 @@ enum punit_power_well {
|
|||
* need to be accessed during AUX communication,
|
||||
*
|
||||
* Generally the common lane corresponds to the pipe and
|
||||
* the spline (PCS/TX) correponds to the port.
|
||||
* the spline (PCS/TX) corresponds to the port.
|
||||
*
|
||||
* For dual channel PHY (VLV/CHV):
|
||||
*
|
||||
|
|
|
@ -1681,7 +1681,7 @@ static int lrc_setup_hardware_status_page(struct intel_engine_cs *ring,
|
|||
* the creation is a deferred call: it's better to make sure first that we need to use
|
||||
* a given ring with the context.
|
||||
*
|
||||
* Return: non-zero on eror.
|
||||
* Return: non-zero on error.
|
||||
*/
|
||||
int intel_lr_context_deferred_create(struct intel_context *ctx,
|
||||
struct intel_engine_cs *ring)
|
||||
|
|
|
@ -1991,57 +1991,10 @@ static int intel_sdvo_get_modes(struct drm_connector *connector)
|
|||
return !list_empty(&connector->probed_modes);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_sdvo_destroy_enhance_property(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (intel_sdvo_connector->left)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->left);
|
||||
if (intel_sdvo_connector->right)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->right);
|
||||
if (intel_sdvo_connector->top)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->top);
|
||||
if (intel_sdvo_connector->bottom)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->bottom);
|
||||
if (intel_sdvo_connector->hpos)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->hpos);
|
||||
if (intel_sdvo_connector->vpos)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->vpos);
|
||||
if (intel_sdvo_connector->saturation)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->saturation);
|
||||
if (intel_sdvo_connector->contrast)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->contrast);
|
||||
if (intel_sdvo_connector->hue)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->hue);
|
||||
if (intel_sdvo_connector->sharpness)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->sharpness);
|
||||
if (intel_sdvo_connector->flicker_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter);
|
||||
if (intel_sdvo_connector->flicker_filter_2d)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_2d);
|
||||
if (intel_sdvo_connector->flicker_filter_adaptive)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->flicker_filter_adaptive);
|
||||
if (intel_sdvo_connector->tv_luma_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->tv_luma_filter);
|
||||
if (intel_sdvo_connector->tv_chroma_filter)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->tv_chroma_filter);
|
||||
if (intel_sdvo_connector->dot_crawl)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->dot_crawl);
|
||||
if (intel_sdvo_connector->brightness)
|
||||
drm_property_destroy(dev, intel_sdvo_connector->brightness);
|
||||
}
|
||||
|
||||
static void intel_sdvo_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||
|
||||
if (intel_sdvo_connector->tv_format)
|
||||
drm_property_destroy(connector->dev,
|
||||
intel_sdvo_connector->tv_format);
|
||||
|
||||
intel_sdvo_destroy_enhance_property(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(intel_sdvo_connector);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "mgag200_drv.h"
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "nouveau_drm.h"
|
||||
#include "nouveau_reg.h"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
|
||||
#include <nvif/class.h>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "omap_drv.h"
|
||||
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "drm_crtc.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "qxl_drv.h"
|
||||
#include "qxl_object.h"
|
||||
#include "drm_crtc_helper.h"
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
static bool qxl_head_enabled(struct qxl_head *head)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include <linux/gcd.h>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "rcar_du_crtc.h"
|
||||
#include "rcar_du_drv.h"
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include <video/sh_mobile_meram.h>
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "sti_compositor.h"
|
||||
#include "sti_drm_drv.h"
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "drm.h"
|
||||
#include "gem.h"
|
||||
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
struct tegra_dc_soc_info {
|
||||
bool supports_interlacing;
|
||||
bool supports_cursor;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#include "drm_flip_work.h"
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "tilcdc_drv.h"
|
||||
#include "tilcdc_regs.h"
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include "udl_drv.h"
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "vmwgfx_kms.h"
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
|
||||
#define vmw_crtc_to_ldu(x) \
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
**************************************************************************/
|
||||
|
||||
#include "vmwgfx_kms.h"
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
|
||||
#define vmw_crtc_to_sou(x) \
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "imx-drm.h"
|
||||
|
||||
|
|
|
@ -125,8 +125,8 @@ struct dma_buf_attachment;
|
|||
extern __printf(2, 3)
|
||||
void drm_ut_debug_printk(const char *function_name,
|
||||
const char *format, ...);
|
||||
extern __printf(2, 3)
|
||||
void drm_err(const char *func, const char *format, ...);
|
||||
extern __printf(1, 2)
|
||||
void drm_err(const char *format, ...);
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name DRM template customization defaults */
|
||||
|
@ -155,7 +155,7 @@ void drm_err(const char *func, const char *format, ...);
|
|||
* \param arg arguments
|
||||
*/
|
||||
#define DRM_ERROR(fmt, ...) \
|
||||
drm_err(__func__, fmt, ##__VA_ARGS__)
|
||||
drm_err(fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
||||
|
@ -170,7 +170,7 @@ void drm_err(const char *func, const char *format, ...);
|
|||
DEFAULT_RATELIMIT_BURST); \
|
||||
\
|
||||
if (__ratelimit(&_rs)) \
|
||||
drm_err(__func__, fmt, ##__VA_ARGS__); \
|
||||
drm_err(fmt, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define DRM_INFO(fmt, ...) \
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2014 Intel Corp.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice 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 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robdclark@gmail.com>
|
||||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#ifndef DRM_ATOMIC_H_
|
||||
#define DRM_ATOMIC_H_
|
||||
|
||||
struct drm_atomic_state * __must_check
|
||||
drm_atomic_state_alloc(struct drm_device *dev);
|
||||
void drm_atomic_state_clear(struct drm_atomic_state *state);
|
||||
void drm_atomic_state_free(struct drm_atomic_state *state);
|
||||
|
||||
struct drm_crtc_state * __must_check
|
||||
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc);
|
||||
struct drm_plane_state * __must_check
|
||||
drm_atomic_get_plane_state(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane);
|
||||
struct drm_connector_state * __must_check
|
||||
drm_atomic_get_connector_state(struct drm_atomic_state *state,
|
||||
struct drm_connector *connector);
|
||||
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_crtc *crtc);
|
||||
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *fb);
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
|
||||
struct drm_crtc *crtc);
|
||||
int __must_check
|
||||
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc);
|
||||
int
|
||||
drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc);
|
||||
|
||||
void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
|
||||
|
||||
int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
|
||||
int __must_check drm_atomic_commit(struct drm_atomic_state *state);
|
||||
int __must_check drm_atomic_async_commit(struct drm_atomic_state *state);
|
||||
|
||||
#endif /* DRM_ATOMIC_H_ */
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2014 Intel Corp.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice 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 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robdclark@gmail.com>
|
||||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#ifndef DRM_ATOMIC_HELPER_H_
|
||||
#define DRM_ATOMIC_HELPER_H_
|
||||
|
||||
int drm_atomic_helper_check(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
int drm_atomic_helper_commit(struct drm_device *dev,
|
||||
struct drm_atomic_state *state,
|
||||
bool async);
|
||||
|
||||
void drm_atomic_helper_commit_pre_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
void drm_atomic_helper_commit_post_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state);
|
||||
|
||||
int drm_atomic_helper_prepare_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state);
|
||||
|
||||
void drm_atomic_helper_swap_state(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
/* implementations for legacy interfaces */
|
||||
int drm_atomic_helper_update_plane(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int drm_atomic_helper_disable_plane(struct drm_plane *plane);
|
||||
int drm_atomic_helper_set_config(struct drm_mode_set *set);
|
||||
|
||||
int drm_atomic_helper_crtc_set_property(struct drm_crtc *crtc,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
int drm_atomic_helper_plane_set_property(struct drm_plane *plane,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
int drm_atomic_helper_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags);
|
||||
|
||||
/* default implementations for state handling */
|
||||
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
|
||||
struct drm_crtc_state *
|
||||
drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
|
||||
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
|
||||
void drm_atomic_helper_plane_reset(struct drm_plane *plane);
|
||||
struct drm_plane_state *
|
||||
drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
|
||||
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
|
||||
void drm_atomic_helper_connector_reset(struct drm_connector *connector);
|
||||
struct drm_connector_state *
|
||||
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
|
||||
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
|
||||
|
||||
#endif /* DRM_ATOMIC_HELPER_H_ */
|
|
@ -42,6 +42,7 @@ struct drm_object_properties;
|
|||
struct drm_file;
|
||||
struct drm_clip_rect;
|
||||
struct device_node;
|
||||
struct fence;
|
||||
|
||||
#define DRM_MODE_OBJECT_CRTC 0xcccccccc
|
||||
#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
|
||||
|
@ -142,8 +143,8 @@ struct drm_framebuffer_funcs {
|
|||
int (*create_handle)(struct drm_framebuffer *fb,
|
||||
struct drm_file *file_priv,
|
||||
unsigned int *handle);
|
||||
/**
|
||||
* Optinal callback for the dirty fb ioctl.
|
||||
/*
|
||||
* Optional callback for the dirty fb ioctl.
|
||||
*
|
||||
* Userspace can notify the driver via this callback
|
||||
* that a area of the framebuffer has changed and should
|
||||
|
@ -224,19 +225,57 @@ struct drm_encoder;
|
|||
struct drm_pending_vblank_event;
|
||||
struct drm_plane;
|
||||
struct drm_bridge;
|
||||
struct drm_atomic_state;
|
||||
|
||||
/**
|
||||
* drm_crtc_funcs - control CRTCs for a given device
|
||||
* struct drm_crtc_state - mutable CRTC state
|
||||
* @enable: whether the CRTC should be enabled, gates all other state
|
||||
* @mode_changed: for use by helpers and drivers when computing state updates
|
||||
* @last_vblank_count: for helpers and drivers to capture the vblank of the
|
||||
* update to ensure framebuffer cleanup isn't done too early
|
||||
* @planes_changed: for use by helpers and drivers when computing state updates
|
||||
* @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
|
||||
* @mode: current mode timings
|
||||
* @event: optional pointer to a DRM event to signal upon completion of the
|
||||
* state update
|
||||
* @state: backpointer to global drm_atomic_state
|
||||
*/
|
||||
struct drm_crtc_state {
|
||||
bool enable;
|
||||
|
||||
/* computed state bits used by helpers and drivers */
|
||||
bool planes_changed : 1;
|
||||
bool mode_changed : 1;
|
||||
|
||||
/* last_vblank_count: for vblank waits before cleanup */
|
||||
u32 last_vblank_count;
|
||||
|
||||
/* adjusted_mode: for use by helpers and drivers */
|
||||
struct drm_display_mode adjusted_mode;
|
||||
|
||||
struct drm_display_mode mode;
|
||||
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_crtc_funcs - control CRTCs for a given device
|
||||
* @save: save CRTC state
|
||||
* @restore: restore CRTC state
|
||||
* @reset: reset CRTC after state has been invalidated (e.g. resume)
|
||||
* @cursor_set: setup the cursor
|
||||
* @cursor_set2: setup the cursor with hotspot, superseeds @cursor_set if set
|
||||
* @cursor_move: move the cursor
|
||||
* @gamma_set: specify color ramp for CRTC
|
||||
* @destroy: deinit and free object
|
||||
* @set_property: called when a property is changed
|
||||
* @set_config: apply a new CRTC configuration
|
||||
* @page_flip: initiate a page flip
|
||||
* @atomic_duplicate_state: duplicate the atomic state for this CRTC
|
||||
* @atomic_destroy_state: destroy an atomic state for this CRTC
|
||||
* @atomic_set_property: set a property on an atomic state for this CRTC
|
||||
*
|
||||
* The drm_crtc_funcs structure is the central CRTC management structure
|
||||
* in the DRM. Each CRTC controls one or more connectors (note that the name
|
||||
|
@ -287,16 +326,28 @@ struct drm_crtc_funcs {
|
|||
|
||||
int (*set_property)(struct drm_crtc *crtc,
|
||||
struct drm_property *property, uint64_t val);
|
||||
|
||||
/* atomic update handling */
|
||||
struct drm_crtc_state *(*atomic_duplicate_state)(struct drm_crtc *crtc);
|
||||
void (*atomic_destroy_state)(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
int (*atomic_set_property)(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_crtc - central CRTC control structure
|
||||
* struct drm_crtc - central CRTC control structure
|
||||
* @dev: parent DRM device
|
||||
* @port: OF node used by drm_of_find_possible_crtcs()
|
||||
* @head: list management
|
||||
* @mutex: per-CRTC locking
|
||||
* @base: base KMS object for ID tracking etc.
|
||||
* @primary: primary plane for this CRTC
|
||||
* @cursor: cursor plane for this CRTC
|
||||
* @cursor_x: current x position of the cursor, used for universal cursor planes
|
||||
* @cursor_y: current y position of the cursor, used for universal cursor planes
|
||||
* @enabled: is this CRTC enabled?
|
||||
* @mode: current mode timings
|
||||
* @hwmode: mode timings as programmed to hw regs
|
||||
|
@ -309,10 +360,13 @@ struct drm_crtc_funcs {
|
|||
* @gamma_size: size of gamma ramp
|
||||
* @gamma_store: gamma ramp values
|
||||
* @framedur_ns: precise frame timing
|
||||
* @framedur_ns: precise line timing
|
||||
* @linedur_ns: precise line timing
|
||||
* @pixeldur_ns: precise pixel timing
|
||||
* @helper_private: mid-layer private data
|
||||
* @properties: property tracking for this CRTC
|
||||
* @state: current atomic state for this CRTC
|
||||
* @acquire_ctx: per-CRTC implicit acquire context used by atomic drivers for
|
||||
* legacy ioctls
|
||||
*
|
||||
* Each CRTC may have one or more connectors associated with it. This structure
|
||||
* allows the CRTC to be controlled.
|
||||
|
@ -322,7 +376,7 @@ struct drm_crtc {
|
|||
struct device_node *port;
|
||||
struct list_head head;
|
||||
|
||||
/**
|
||||
/*
|
||||
* crtc mutex
|
||||
*
|
||||
* This provides a read lock for the overall crtc state (mode, dpms
|
||||
|
@ -368,6 +422,8 @@ struct drm_crtc {
|
|||
|
||||
struct drm_object_properties properties;
|
||||
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
/*
|
||||
* For legacy crtc ioctls so that atomic drivers can get at the locking
|
||||
* acquire context.
|
||||
|
@ -375,9 +431,22 @@ struct drm_crtc {
|
|||
struct drm_modeset_acquire_ctx *acquire_ctx;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_connector_state - mutable connector state
|
||||
* @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_crtc *crtc;
|
||||
|
||||
struct drm_encoder *best_encoder;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_connector_funcs - control connectors on a given device
|
||||
* struct drm_connector_funcs - control connectors on a given device
|
||||
* @dpms: set power state (see drm_crtc_funcs above)
|
||||
* @save: save connector state
|
||||
* @restore: restore connector state
|
||||
|
@ -387,6 +456,9 @@ struct drm_crtc {
|
|||
* @set_property: property for this connector may need an update
|
||||
* @destroy: make object go away
|
||||
* @force: notify the driver that the connector is forced on
|
||||
* @atomic_duplicate_state: duplicate the atomic state for this connector
|
||||
* @atomic_destroy_state: destroy an atomic state for this connector
|
||||
* @atomic_set_property: set a property on an atomic state for this connector
|
||||
*
|
||||
* 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,
|
||||
|
@ -411,10 +483,19 @@ struct drm_connector_funcs {
|
|||
uint64_t val);
|
||||
void (*destroy)(struct drm_connector *connector);
|
||||
void (*force)(struct drm_connector *connector);
|
||||
|
||||
/* atomic update handling */
|
||||
struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
|
||||
void (*atomic_destroy_state)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
int (*atomic_set_property)(struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_encoder_funcs - encoder controls
|
||||
* struct drm_encoder_funcs - encoder controls
|
||||
* @reset: reset state (e.g. at init or resume time)
|
||||
* @destroy: cleanup and free associated data
|
||||
*
|
||||
|
@ -428,7 +509,7 @@ struct drm_encoder_funcs {
|
|||
#define DRM_CONNECTOR_MAX_ENCODER 3
|
||||
|
||||
/**
|
||||
* drm_encoder - central DRM encoder structure
|
||||
* struct drm_encoder - central DRM encoder structure
|
||||
* @dev: parent DRM device
|
||||
* @head: list management
|
||||
* @base: base KMS object
|
||||
|
@ -472,7 +553,7 @@ struct drm_encoder {
|
|||
#define MAX_ELD_BYTES 128
|
||||
|
||||
/**
|
||||
* drm_connector - central DRM connector control structure
|
||||
* struct drm_connector - central DRM connector control structure
|
||||
* @dev: parent DRM device
|
||||
* @kdev: kernel device for sysfs attributes
|
||||
* @attr: sysfs attributes
|
||||
|
@ -483,6 +564,7 @@ struct drm_encoder {
|
|||
* @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?
|
||||
* @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
|
||||
|
@ -490,10 +572,13 @@ struct drm_encoder {
|
|||
* @funcs: connector control functions
|
||||
* @edid_blob_ptr: DRM property containing EDID if present
|
||||
* @properties: property tracking for this connector
|
||||
* @path_blob_ptr: DRM blob property data for the DP MST path property
|
||||
* @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
|
||||
|
@ -503,6 +588,9 @@ struct drm_encoder {
|
|||
* @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
|
||||
* @debugfs_entry: debugfs directory for this connector
|
||||
* @state: current atomic state for this connector
|
||||
*
|
||||
* 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
|
||||
|
@ -563,14 +651,54 @@ struct drm_connector {
|
|||
unsigned bad_edid_counter;
|
||||
|
||||
struct dentry *debugfs_entry;
|
||||
|
||||
struct drm_connector_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_plane_funcs - driver plane control functions
|
||||
* struct drm_plane_state - mutable plane state
|
||||
* @crtc: currently bound CRTC, NULL if disabled
|
||||
* @fb: currently bound framebuffer
|
||||
* @fence: optional fence to wait for before scanning out @fb
|
||||
* @crtc_x: left position of visible portion of plane on crtc
|
||||
* @crtc_y: upper position of visible portion of plane on crtc
|
||||
* @crtc_w: width of visible portion of plane on crtc
|
||||
* @crtc_h: height of visible portion of plane on crtc
|
||||
* @src_x: left position of visible portion of plane within
|
||||
* plane (in 16.16)
|
||||
* @src_y: upper position of visible portion of plane within
|
||||
* plane (in 16.16)
|
||||
* @src_w: width of visible portion of plane (in 16.16)
|
||||
* @src_h: height of visible portion of plane (in 16.16)
|
||||
* @state: backpointer to global drm_atomic_state
|
||||
*/
|
||||
struct drm_plane_state {
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_framebuffer *fb;
|
||||
struct fence *fence;
|
||||
|
||||
/* Signed dest location allows it to be partially off screen */
|
||||
int32_t crtc_x, crtc_y;
|
||||
uint32_t crtc_w, crtc_h;
|
||||
|
||||
/* Source values are 16.16 fixed point */
|
||||
uint32_t src_x, src_y;
|
||||
uint32_t src_h, src_w;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct drm_plane_funcs - driver plane control functions
|
||||
* @update_plane: update the plane configuration
|
||||
* @disable_plane: shut down the plane
|
||||
* @destroy: clean up plane resources
|
||||
* @reset: reset plane after state has been invalidated (e.g. resume)
|
||||
* @set_property: called when a property is changed
|
||||
* @atomic_duplicate_state: duplicate the atomic state for this plane
|
||||
* @atomic_destroy_state: destroy an atomic state for this plane
|
||||
* @atomic_set_property: set a property on an atomic state for this plane
|
||||
*/
|
||||
struct drm_plane_funcs {
|
||||
int (*update_plane)(struct drm_plane *plane,
|
||||
|
@ -585,6 +713,15 @@ struct drm_plane_funcs {
|
|||
|
||||
int (*set_property)(struct drm_plane *plane,
|
||||
struct drm_property *property, uint64_t val);
|
||||
|
||||
/* atomic update handling */
|
||||
struct drm_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
|
||||
void (*atomic_destroy_state)(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
int (*atomic_set_property)(struct drm_plane *plane,
|
||||
struct drm_plane_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
};
|
||||
|
||||
enum drm_plane_type {
|
||||
|
@ -594,7 +731,7 @@ enum drm_plane_type {
|
|||
};
|
||||
|
||||
/**
|
||||
* drm_plane - central DRM plane control structure
|
||||
* struct drm_plane - central DRM plane control structure
|
||||
* @dev: DRM device this plane belongs to
|
||||
* @head: for list management
|
||||
* @base: base mode object
|
||||
|
@ -603,9 +740,12 @@ enum drm_plane_type {
|
|||
* @format_count: number of formats supported
|
||||
* @crtc: currently bound CRTC
|
||||
* @fb: currently bound fb
|
||||
* @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
|
||||
* drm_mode_set_config_internal() to implement correct refcounting.
|
||||
* @funcs: helper functions
|
||||
* @properties: property tracking for this plane
|
||||
* @type: type of plane (overlay, primary, cursor)
|
||||
* @state: current atomic state for this plane
|
||||
*/
|
||||
struct drm_plane {
|
||||
struct drm_device *dev;
|
||||
|
@ -620,8 +760,6 @@ struct drm_plane {
|
|||
struct drm_crtc *crtc;
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
/* Temporary tracking of the old fb while a modeset is ongoing. Used
|
||||
* by drm_mode_set_config_internal to implement correct refcounting. */
|
||||
struct drm_framebuffer *old_fb;
|
||||
|
||||
const struct drm_plane_funcs *funcs;
|
||||
|
@ -629,10 +767,14 @@ struct drm_plane {
|
|||
struct drm_object_properties properties;
|
||||
|
||||
enum drm_plane_type type;
|
||||
|
||||
void *helper_private;
|
||||
|
||||
struct drm_plane_state *state;
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_bridge_funcs - drm_bridge control functions
|
||||
* struct drm_bridge_funcs - drm_bridge control functions
|
||||
* @mode_fixup: Try to fixup (or reject entirely) proposed mode for this bridge
|
||||
* @disable: Called right before encoder prepare, disables the bridge
|
||||
* @post_disable: Called right after encoder prepare, for lockstepped disable
|
||||
|
@ -656,7 +798,7 @@ struct drm_bridge_funcs {
|
|||
};
|
||||
|
||||
/**
|
||||
* drm_bridge - central DRM bridge control structure
|
||||
* struct drm_bridge - central DRM bridge control structure
|
||||
* @dev: DRM device this bridge belongs to
|
||||
* @head: list management
|
||||
* @base: base mode object
|
||||
|
@ -674,8 +816,33 @@ struct drm_bridge {
|
|||
};
|
||||
|
||||
/**
|
||||
* drm_mode_set - new values for a CRTC config change
|
||||
* @head: list management
|
||||
* struct struct drm_atomic_state - the global state object for atomic updates
|
||||
* @dev: parent DRM device
|
||||
* @flags: state flags like async update
|
||||
* @planes: pointer to array of plane pointers
|
||||
* @plane_states: pointer to array of plane states pointers
|
||||
* @crtcs: pointer to array of CRTC pointers
|
||||
* @crtc_states: pointer to array of CRTC states pointers
|
||||
* @connectors: pointer to array of connector pointers
|
||||
* @connector_states: pointer to array of connector states pointers
|
||||
* @acquire_ctx: acquire context for this atomic modeset state update
|
||||
*/
|
||||
struct drm_atomic_state {
|
||||
struct drm_device *dev;
|
||||
uint32_t flags;
|
||||
struct drm_plane **planes;
|
||||
struct drm_plane_state **plane_states;
|
||||
struct drm_crtc **crtcs;
|
||||
struct drm_crtc_state **crtc_states;
|
||||
struct drm_connector **connectors;
|
||||
struct drm_connector_state **connector_states;
|
||||
|
||||
struct drm_modeset_acquire_ctx *acquire_ctx;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct drm_mode_set - new values for a CRTC config change
|
||||
* @fb: framebuffer to use for new config
|
||||
* @crtc: CRTC whose configuration we're about to change
|
||||
* @mode: mode timings to use
|
||||
|
@ -705,6 +872,9 @@ struct drm_mode_set {
|
|||
* struct drm_mode_config_funcs - basic driver provided mode setting functions
|
||||
* @fb_create: create a new framebuffer object
|
||||
* @output_poll_changed: function to handle output configuration changes
|
||||
* @atomic_check: check whether a give atomic state update is possible
|
||||
* @atomic_commit: commit an atomic state update previously verified with
|
||||
* atomic_check()
|
||||
*
|
||||
* Some global (i.e. not per-CRTC, connector, etc) mode setting functions that
|
||||
* involve drivers.
|
||||
|
@ -714,13 +884,20 @@ struct drm_mode_config_funcs {
|
|||
struct drm_file *file_priv,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
void (*output_poll_changed)(struct drm_device *dev);
|
||||
|
||||
int (*atomic_check)(struct drm_device *dev,
|
||||
struct drm_atomic_state *a);
|
||||
int (*atomic_commit)(struct drm_device *dev,
|
||||
struct drm_atomic_state *a,
|
||||
bool async);
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_mode_group - group of mode setting resources for potential sub-grouping
|
||||
* struct drm_mode_group - group of mode setting resources for potential sub-grouping
|
||||
* @num_crtcs: CRTC count
|
||||
* @num_encoders: encoder count
|
||||
* @num_connectors: connector count
|
||||
* @num_bridges: bridge count
|
||||
* @id_list: list of KMS object IDs in this group
|
||||
*
|
||||
* Currently this simply tracks the global mode setting state. But in the
|
||||
|
@ -740,10 +917,14 @@ struct drm_mode_group {
|
|||
};
|
||||
|
||||
/**
|
||||
* drm_mode_config - Mode configuration control structure
|
||||
* struct drm_mode_config - Mode configuration control structure
|
||||
* @mutex: mutex protecting KMS related lists and structures
|
||||
* @connection_mutex: ww mutex protecting connector state and routing
|
||||
* @acquire_ctx: global implicit acquire context used by atomic drivers for
|
||||
* legacy ioctls
|
||||
* @idr_mutex: mutex for KMS ID allocation and management
|
||||
* @crtc_idr: main KMS ID tracking object
|
||||
* @fb_lock: mutex to protect fb state and lists
|
||||
* @num_fb: number of fbs available
|
||||
* @fb_list: list of framebuffers available
|
||||
* @num_connector: number of connectors on this device
|
||||
|
@ -752,17 +933,28 @@ struct drm_mode_group {
|
|||
* @bridge_list: list of bridge objects
|
||||
* @num_encoder: number of encoders on this device
|
||||
* @encoder_list: list of encoder objects
|
||||
* @num_overlay_plane: number of overlay planes on this device
|
||||
* @num_total_plane: number of universal (i.e. with primary/curso) planes on this device
|
||||
* @plane_list: list of plane objects
|
||||
* @num_crtc: number of CRTCs on this device
|
||||
* @crtc_list: list of CRTC objects
|
||||
* @property_list: list of property objects
|
||||
* @min_width: minimum pixel width on this device
|
||||
* @min_height: minimum pixel height on this device
|
||||
* @max_width: maximum pixel width on this device
|
||||
* @max_height: maximum pixel height on this device
|
||||
* @funcs: core driver provided mode setting functions
|
||||
* @fb_base: base address of the framebuffer
|
||||
* @poll_enabled: track polling status for this device
|
||||
* @poll_enabled: track polling support for this device
|
||||
* @poll_running: track polling status for this device
|
||||
* @output_poll_work: delayed work for polling in process context
|
||||
* @property_blob_list: list of all the blob property objects
|
||||
* @*_property: core property tracking
|
||||
* @preferred_depth: preferred RBG pixel depth, used by fb helpers
|
||||
* @prefer_shadow: hint to userspace to prefer shadow-fb rendering
|
||||
* @async_page_flip: does this device support async flips on the primary plane?
|
||||
* @cursor_width: hint to userspace for max cursor width
|
||||
* @cursor_height: hint to userspace for max cursor height
|
||||
*
|
||||
* Core mode resource tracking structure. All CRTC, encoders, and connectors
|
||||
* enumerated by the driver are added here, as are global properties. Some
|
||||
|
@ -776,14 +968,7 @@ struct drm_mode_config {
|
|||
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
|
||||
/* this is limited to one for now */
|
||||
|
||||
|
||||
/**
|
||||
* fb_lock - mutex to protect fb state
|
||||
*
|
||||
* Besides the global fb list his also protects the fbs list in the
|
||||
* file_priv
|
||||
*/
|
||||
struct mutex fb_lock;
|
||||
struct mutex fb_lock; /* proctects global and per-file fb lists */
|
||||
int num_fb;
|
||||
struct list_head fb_list;
|
||||
|
||||
|
@ -880,9 +1065,6 @@ extern int drm_crtc_init_with_planes(struct drm_device *dev,
|
|||
struct drm_plane *primary,
|
||||
struct drm_plane *cursor,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
extern int drm_crtc_init(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
extern void drm_crtc_cleanup(struct drm_crtc *crtc);
|
||||
extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
|
||||
|
||||
|
|
|
@ -68,6 +68,7 @@ struct drm_crtc_helper_funcs {
|
|||
int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
void (*mode_set_nofb)(struct drm_crtc *crtc);
|
||||
|
||||
/* Move the crtc on the current fb to the given position *optional* */
|
||||
int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
|
||||
|
@ -81,6 +82,12 @@ struct drm_crtc_helper_funcs {
|
|||
|
||||
/* disable crtc when not in use - more explicit than dpms off */
|
||||
void (*disable)(struct drm_crtc *crtc);
|
||||
|
||||
/* atomic helpers */
|
||||
int (*atomic_check)(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
void (*atomic_begin)(struct drm_crtc *crtc);
|
||||
void (*atomic_flush)(struct drm_crtc *crtc);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -161,6 +168,12 @@ static inline void drm_connector_helper_add(struct drm_connector *connector,
|
|||
|
||||
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,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
|
||||
/* drm_probe_helper.c */
|
||||
extern int drm_helper_probe_single_connector_modes(struct drm_connector
|
||||
*connector, uint32_t maxX,
|
||||
|
|
|
@ -405,26 +405,6 @@
|
|||
#define MODE_I2C_READ 4
|
||||
#define MODE_I2C_STOP 8
|
||||
|
||||
/**
|
||||
* struct i2c_algo_dp_aux_data - driver interface structure for i2c over dp
|
||||
* aux algorithm
|
||||
* @running: set by the algo indicating whether an i2c is ongoing or whether
|
||||
* the i2c bus is quiescent
|
||||
* @address: i2c target address for the currently ongoing transfer
|
||||
* @aux_ch: driver callback to transfer a single byte of the i2c payload
|
||||
*/
|
||||
struct i2c_algo_dp_aux_data {
|
||||
bool running;
|
||||
u16 address;
|
||||
int (*aux_ch) (struct i2c_adapter *adapter,
|
||||
int mode, uint8_t write_byte,
|
||||
uint8_t *read_byte);
|
||||
};
|
||||
|
||||
int
|
||||
i2c_dp_aux_add_bus(struct i2c_adapter *adapter);
|
||||
|
||||
|
||||
#define DP_LINK_STATUS_SIZE 6
|
||||
bool drm_dp_channel_eq_ok(const u8 link_status[DP_LINK_STATUS_SIZE],
|
||||
int lane_count);
|
||||
|
@ -551,6 +531,7 @@ struct drm_dp_aux {
|
|||
struct mutex hw_mutex;
|
||||
ssize_t (*transfer)(struct drm_dp_aux *aux,
|
||||
struct drm_dp_aux_msg *msg);
|
||||
unsigned i2c_nack_count, i2c_defer_count;
|
||||
};
|
||||
|
||||
ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
struct drm_dp_mst_branch;
|
||||
|
||||
/**
|
||||
* struct drm_dp_vcpi - Virtual Channel Payload Identifer
|
||||
* struct drm_dp_vcpi - Virtual Channel Payload Identifier
|
||||
* @vcpi: Virtual channel ID.
|
||||
* @pbn: Payload Bandwidth Number for this channel
|
||||
* @aligned_pbn: PBN aligned with slot size
|
||||
|
|
|
@ -207,6 +207,61 @@ struct detailed_timing {
|
|||
#define DRM_EDID_HDMI_DC_30 (1 << 4)
|
||||
#define DRM_EDID_HDMI_DC_Y444 (1 << 3)
|
||||
|
||||
/* ELD Header Block */
|
||||
#define DRM_ELD_HEADER_BLOCK_SIZE 4
|
||||
|
||||
#define DRM_ELD_VER 0
|
||||
# define DRM_ELD_VER_SHIFT 3
|
||||
# define DRM_ELD_VER_MASK (0x1f << 3)
|
||||
|
||||
#define DRM_ELD_BASELINE_ELD_LEN 2 /* in dwords! */
|
||||
|
||||
/* ELD Baseline Block for ELD_Ver == 2 */
|
||||
#define DRM_ELD_CEA_EDID_VER_MNL 4
|
||||
# define DRM_ELD_CEA_EDID_VER_SHIFT 5
|
||||
# define DRM_ELD_CEA_EDID_VER_MASK (7 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_NONE (0 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861 (1 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861A (2 << 5)
|
||||
# define DRM_ELD_CEA_EDID_VER_CEA861BCD (3 << 5)
|
||||
# define DRM_ELD_MNL_SHIFT 0
|
||||
# define DRM_ELD_MNL_MASK (0x1f << 0)
|
||||
|
||||
#define DRM_ELD_SAD_COUNT_CONN_TYPE 5
|
||||
# define DRM_ELD_SAD_COUNT_SHIFT 4
|
||||
# define DRM_ELD_SAD_COUNT_MASK (0xf << 4)
|
||||
# define DRM_ELD_CONN_TYPE_SHIFT 2
|
||||
# define DRM_ELD_CONN_TYPE_MASK (3 << 2)
|
||||
# define DRM_ELD_CONN_TYPE_HDMI (0 << 2)
|
||||
# define DRM_ELD_CONN_TYPE_DP (1 << 2)
|
||||
# define DRM_ELD_SUPPORTS_AI (1 << 1)
|
||||
# define DRM_ELD_SUPPORTS_HDCP (1 << 0)
|
||||
|
||||
#define DRM_ELD_AUD_SYNCH_DELAY 6 /* in units of 2 ms */
|
||||
# define DRM_ELD_AUD_SYNCH_DELAY_MAX 0xfa /* 500 ms */
|
||||
|
||||
#define DRM_ELD_SPEAKER 7
|
||||
# define DRM_ELD_SPEAKER_RLRC (1 << 6)
|
||||
# define DRM_ELD_SPEAKER_FLRC (1 << 5)
|
||||
# define DRM_ELD_SPEAKER_RC (1 << 4)
|
||||
# define DRM_ELD_SPEAKER_RLR (1 << 3)
|
||||
# define DRM_ELD_SPEAKER_FC (1 << 2)
|
||||
# define DRM_ELD_SPEAKER_LFE (1 << 1)
|
||||
# define DRM_ELD_SPEAKER_FLR (1 << 0)
|
||||
|
||||
#define DRM_ELD_PORT_ID 8 /* offsets 8..15 inclusive */
|
||||
# define DRM_ELD_PORT_ID_LEN 8
|
||||
|
||||
#define DRM_ELD_MANUFACTURER_NAME0 16
|
||||
#define DRM_ELD_MANUFACTURER_NAME1 17
|
||||
|
||||
#define DRM_ELD_PRODUCT_CODE0 18
|
||||
#define DRM_ELD_PRODUCT_CODE1 19
|
||||
|
||||
#define DRM_ELD_MONITOR_NAME_STRING 20 /* offsets 20..(20+mnl-1) inclusive */
|
||||
|
||||
#define DRM_ELD_CEA_SAD(mnl, sad) (20 + (mnl) + 3 * (sad))
|
||||
|
||||
struct edid {
|
||||
u8 header[8];
|
||||
/* Vendor & product info */
|
||||
|
@ -279,4 +334,51 @@ int
|
|||
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
|
||||
const struct drm_display_mode *mode);
|
||||
|
||||
/**
|
||||
* drm_eld_mnl - Get ELD monitor name length in bytes.
|
||||
* @eld: pointer to an eld memory structure with mnl set
|
||||
*/
|
||||
static inline int drm_eld_mnl(const uint8_t *eld)
|
||||
{
|
||||
return (eld[DRM_ELD_CEA_EDID_VER_MNL] & DRM_ELD_MNL_MASK) >> DRM_ELD_MNL_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_sad_count - Get ELD SAD count.
|
||||
* @eld: pointer to an eld memory structure with sad_count set
|
||||
*/
|
||||
static inline int drm_eld_sad_count(const uint8_t *eld)
|
||||
{
|
||||
return (eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_SAD_COUNT_MASK) >>
|
||||
DRM_ELD_SAD_COUNT_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_calc_baseline_block_size - Calculate baseline block size in bytes
|
||||
* @eld: pointer to an eld memory structure with mnl and sad_count set
|
||||
*
|
||||
* This is a helper for determining the payload size of the baseline block, in
|
||||
* bytes, for e.g. setting the Baseline_ELD_Len field in the ELD header block.
|
||||
*/
|
||||
static inline int drm_eld_calc_baseline_block_size(const uint8_t *eld)
|
||||
{
|
||||
return DRM_ELD_MONITOR_NAME_STRING - DRM_ELD_HEADER_BLOCK_SIZE +
|
||||
drm_eld_mnl(eld) + drm_eld_sad_count(eld) * 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_eld_size - Get ELD size in bytes
|
||||
* @eld: pointer to a complete eld memory structure
|
||||
*
|
||||
* The returned value does not include the vendor block. It's vendor specific,
|
||||
* and comprises of the remaining bytes in the ELD memory buffer after
|
||||
* drm_eld_size() bytes of header and baseline block.
|
||||
*
|
||||
* The returned value is guaranteed to be a multiple of 4.
|
||||
*/
|
||||
static inline int drm_eld_size(const uint8_t *eld)
|
||||
{
|
||||
return DRM_ELD_HEADER_BLOCK_SIZE + eld[DRM_ELD_BASELINE_ELD_LEN] * 4;
|
||||
}
|
||||
|
||||
#endif /* __DRM_EDID_H__ */
|
||||
|
|
|
@ -33,6 +33,7 @@ struct drm_modeset_lock;
|
|||
* @ww_ctx: base acquire ctx
|
||||
* @contended: used internally for -EDEADLK handling
|
||||
* @locked: list of held locks
|
||||
* @trylock_only: trylock mode used in atomic contexts/panic notifiers
|
||||
*
|
||||
* Each thread competing for a set of locks must use one acquire
|
||||
* ctx. And if any lock fxn returns -EDEADLK, it must backoff and
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define DRM_PLANE_HELPER_H
|
||||
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
/*
|
||||
* Drivers that don't allow primary plane scaling may pass this macro in place
|
||||
|
@ -42,6 +43,32 @@
|
|||
* planes.
|
||||
*/
|
||||
|
||||
extern int drm_crtc_init(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
const struct drm_crtc_funcs *funcs);
|
||||
|
||||
/**
|
||||
* drm_plane_helper_funcs - helper operations for CRTCs
|
||||
*
|
||||
* The helper operations are called by the mid-layer CRTC helper.
|
||||
*/
|
||||
struct drm_plane_helper_funcs {
|
||||
int (*prepare_fb)(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb);
|
||||
void (*cleanup_fb)(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb);
|
||||
|
||||
int (*atomic_check)(struct drm_plane *plane,
|
||||
struct drm_plane_state *state);
|
||||
void (*atomic_update)(struct drm_plane *plane);
|
||||
};
|
||||
|
||||
static inline void drm_plane_helper_add(struct drm_plane *plane,
|
||||
const struct drm_plane_helper_funcs *funcs)
|
||||
{
|
||||
plane->helper_private = (void *)funcs;
|
||||
}
|
||||
|
||||
extern int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
|
@ -68,4 +95,16 @@ extern struct drm_plane *drm_primary_helper_create_plane(struct drm_device *dev,
|
|||
int num_formats);
|
||||
|
||||
|
||||
int drm_plane_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int drm_plane_helper_disable(struct drm_plane *plane);
|
||||
|
||||
/* For use by drm_crtc_helper.c */
|
||||
int drm_plane_helper_commit(struct drm_plane *plane,
|
||||
struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *old_fb);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue