drm: rcar-du: Move plane allocator to rcar_du_plane.c
The plane allocator is specific to DU planes and won't be used for VSP-based planes, move it with the rest of the DU planes code where it belongs. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
This commit is contained in:
parent
2af0394409
commit
ab334e137c
|
@ -192,290 +192,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
|
|||
* Atomic Check and Update
|
||||
*/
|
||||
|
||||
/*
|
||||
* Atomic hardware plane allocator
|
||||
*
|
||||
* The hardware plane allocator is solely based on the atomic plane states
|
||||
* without keeping any external state to avoid races between .atomic_check()
|
||||
* and .atomic_commit().
|
||||
*
|
||||
* The core idea is to avoid using a free planes bitmask that would need to be
|
||||
* shared between check and commit handlers with a collective knowledge based on
|
||||
* the allocated hardware plane(s) for each KMS plane. The allocator then loops
|
||||
* over all plane states to compute the free planes bitmask, allocates hardware
|
||||
* planes based on that bitmask, and stores the result back in the plane states.
|
||||
*
|
||||
* For this to work we need to access the current state of planes not touched by
|
||||
* the atomic update. To ensure that it won't be modified, we need to lock all
|
||||
* planes using drm_atomic_get_plane_state(). This effectively serializes atomic
|
||||
* updates from .atomic_check() up to completion (when swapping the states if
|
||||
* the check step has succeeded) or rollback (when freeing the states if the
|
||||
* check step has failed).
|
||||
*
|
||||
* Allocation is performed in the .atomic_check() handler and applied
|
||||
* automatically when the core swaps the old and new states.
|
||||
*/
|
||||
|
||||
static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
|
||||
struct rcar_du_plane_state *new_state)
|
||||
{
|
||||
struct rcar_du_plane_state *cur_state;
|
||||
|
||||
cur_state = to_rcar_plane_state(plane->plane.state);
|
||||
|
||||
/* Lowering the number of planes doesn't strictly require reallocation
|
||||
* as the extra hardware plane will be freed when committing, but doing
|
||||
* so could lead to more fragmentation.
|
||||
*/
|
||||
if (!cur_state->format ||
|
||||
cur_state->format->planes != new_state->format->planes)
|
||||
return true;
|
||||
|
||||
/* Reallocate hardware planes if the source has changed. */
|
||||
if (cur_state->source != new_state->source)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
if (state->hwindex == -1)
|
||||
return 0;
|
||||
|
||||
mask = 1 << state->hwindex;
|
||||
if (state->format->planes == 2)
|
||||
mask |= 1 << ((state->hwindex + 1) % 8);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
|
||||
* VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
|
||||
* DU0/1 plane 1.
|
||||
*
|
||||
* Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
|
||||
* and allocate planes in reverse index order otherwise to ensure maximum
|
||||
* availability of planes 0 and 1.
|
||||
*
|
||||
* The caller is responsible for ensuring that the requested source is
|
||||
* compatible with the DU revision.
|
||||
*/
|
||||
static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
|
||||
struct rcar_du_plane_state *state,
|
||||
unsigned int free)
|
||||
{
|
||||
unsigned int num_planes = state->format->planes;
|
||||
int fixed = -1;
|
||||
int i;
|
||||
|
||||
if (state->source == RCAR_DU_PLANE_VSPD0) {
|
||||
/* VSPD0 feeds plane 0 on DU0/1. */
|
||||
if (plane->group->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
fixed = 0;
|
||||
} else if (state->source == RCAR_DU_PLANE_VSPD1) {
|
||||
/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
|
||||
fixed = plane->group->index == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (fixed >= 0)
|
||||
return free & (1 << fixed) ? fixed : -EBUSY;
|
||||
|
||||
for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
|
||||
if (!(free & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
|
||||
break;
|
||||
}
|
||||
|
||||
return i < 0 ? -EBUSY : i;
|
||||
}
|
||||
|
||||
static int rcar_du_atomic_check(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rcar_du_device *rcdu = dev->dev_private;
|
||||
unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
|
||||
unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
|
||||
bool needs_realloc = false;
|
||||
unsigned int groups = 0;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
ret = drm_atomic_helper_check(dev, state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Check if hardware planes need to be reallocated. */
|
||||
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct rcar_du_plane *plane;
|
||||
unsigned int index;
|
||||
|
||||
if (!state->planes[i])
|
||||
continue;
|
||||
|
||||
plane = to_rcar_plane(state->planes[i]);
|
||||
plane_state = to_rcar_plane_state(state->plane_states[i]);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
|
||||
plane->group->index, plane - plane->group->planes);
|
||||
|
||||
/* If the plane is being disabled we don't need to go through
|
||||
* the full reallocation procedure. Just mark the hardware
|
||||
* plane(s) as freed.
|
||||
*/
|
||||
if (!plane_state->format) {
|
||||
dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
|
||||
__func__);
|
||||
index = plane - plane->group->planes;
|
||||
group_freed_planes[plane->group->index] |= 1 << index;
|
||||
plane_state->hwindex = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the plane needs to be reallocated mark it as such, and
|
||||
* mark the hardware plane(s) as free.
|
||||
*/
|
||||
if (rcar_du_plane_needs_realloc(plane, plane_state)) {
|
||||
dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
|
||||
__func__);
|
||||
groups |= 1 << plane->group->index;
|
||||
needs_realloc = true;
|
||||
|
||||
index = plane - plane->group->planes;
|
||||
group_freed_planes[plane->group->index] |= 1 << index;
|
||||
plane_state->hwindex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needs_realloc)
|
||||
return 0;
|
||||
|
||||
/* Grab all plane states for the groups that need reallocation to ensure
|
||||
* locking and avoid racy updates. This serializes the update operation,
|
||||
* but there's not much we can do about it as that's the hardware
|
||||
* design.
|
||||
*
|
||||
* Compute the used planes mask for each group at the same time to avoid
|
||||
* looping over the planes separately later.
|
||||
*/
|
||||
while (groups) {
|
||||
unsigned int index = ffs(groups) - 1;
|
||||
struct rcar_du_group *group = &rcdu->groups[index];
|
||||
unsigned int used_planes = 0;
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
|
||||
__func__, index);
|
||||
|
||||
for (i = 0; i < group->num_planes; ++i) {
|
||||
struct rcar_du_plane *plane = &group->planes[i];
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct drm_plane_state *s;
|
||||
|
||||
s = drm_atomic_get_plane_state(state, &plane->plane);
|
||||
if (IS_ERR(s))
|
||||
return PTR_ERR(s);
|
||||
|
||||
/* If the plane has been freed in the above loop its
|
||||
* hardware planes must not be added to the used planes
|
||||
* bitmask. However, the current state doesn't reflect
|
||||
* the free state yet, as we've modified the new state
|
||||
* above. Use the local freed planes list to check for
|
||||
* that condition instead.
|
||||
*/
|
||||
if (group_freed_planes[index] & (1 << i)) {
|
||||
dev_dbg(rcdu->dev,
|
||||
"%s: plane (%u,%u) has been freed, skipping\n",
|
||||
__func__, plane->group->index,
|
||||
plane - plane->group->planes);
|
||||
continue;
|
||||
}
|
||||
|
||||
plane_state = to_rcar_plane_state(plane->plane.state);
|
||||
used_planes |= rcar_du_plane_hwmask(plane_state);
|
||||
|
||||
dev_dbg(rcdu->dev,
|
||||
"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
|
||||
__func__, plane->group->index,
|
||||
plane - plane->group->planes,
|
||||
plane_state->format ?
|
||||
plane_state->format->planes : 0,
|
||||
plane_state->hwindex);
|
||||
}
|
||||
|
||||
group_free_planes[index] = 0xff & ~used_planes;
|
||||
groups &= ~(1 << index);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
|
||||
__func__, index, group_free_planes[index]);
|
||||
}
|
||||
|
||||
/* Reallocate hardware planes for each plane that needs it. */
|
||||
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct rcar_du_plane *plane;
|
||||
unsigned int crtc_planes;
|
||||
unsigned int free;
|
||||
int idx;
|
||||
|
||||
if (!state->planes[i])
|
||||
continue;
|
||||
|
||||
plane = to_rcar_plane(state->planes[i]);
|
||||
plane_state = to_rcar_plane_state(state->plane_states[i]);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
|
||||
plane->group->index, plane - plane->group->planes);
|
||||
|
||||
/* Skip planes that are being disabled or don't need to be
|
||||
* reallocated.
|
||||
*/
|
||||
if (!plane_state->format ||
|
||||
!rcar_du_plane_needs_realloc(plane, plane_state))
|
||||
continue;
|
||||
|
||||
/* Try to allocate the plane from the free planes currently
|
||||
* associated with the target CRTC to avoid restarting the CRTC
|
||||
* group and thus minimize flicker. If it fails fall back to
|
||||
* allocating from all free planes.
|
||||
*/
|
||||
crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
|
||||
? plane->group->dptsr_planes
|
||||
: ~plane->group->dptsr_planes;
|
||||
free = group_free_planes[plane->group->index];
|
||||
|
||||
idx = rcar_du_plane_hwalloc(plane, plane_state,
|
||||
free & crtc_planes);
|
||||
if (idx < 0)
|
||||
idx = rcar_du_plane_hwalloc(plane, plane_state,
|
||||
free);
|
||||
if (idx < 0) {
|
||||
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
|
||||
__func__);
|
||||
return idx;
|
||||
}
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
|
||||
__func__, plane_state->format->planes, idx);
|
||||
|
||||
plane_state->hwindex = idx;
|
||||
|
||||
group_free_planes[plane->group->index] &=
|
||||
~rcar_du_plane_hwmask(plane_state);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
|
||||
__func__, plane->group->index,
|
||||
group_free_planes[plane->group->index]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rcar_du_atomic_check_planes(dev, state);
|
||||
}
|
||||
|
||||
struct rcar_du_commit {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
@ -25,6 +26,291 @@
|
|||
#include "rcar_du_plane.h"
|
||||
#include "rcar_du_regs.h"
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Atomic hardware plane allocator
|
||||
*
|
||||
* The hardware plane allocator is solely based on the atomic plane states
|
||||
* without keeping any external state to avoid races between .atomic_check()
|
||||
* and .atomic_commit().
|
||||
*
|
||||
* The core idea is to avoid using a free planes bitmask that would need to be
|
||||
* shared between check and commit handlers with a collective knowledge based on
|
||||
* the allocated hardware plane(s) for each KMS plane. The allocator then loops
|
||||
* over all plane states to compute the free planes bitmask, allocates hardware
|
||||
* planes based on that bitmask, and stores the result back in the plane states.
|
||||
*
|
||||
* For this to work we need to access the current state of planes not touched by
|
||||
* the atomic update. To ensure that it won't be modified, we need to lock all
|
||||
* planes using drm_atomic_get_plane_state(). This effectively serializes atomic
|
||||
* updates from .atomic_check() up to completion (when swapping the states if
|
||||
* the check step has succeeded) or rollback (when freeing the states if the
|
||||
* check step has failed).
|
||||
*
|
||||
* Allocation is performed in the .atomic_check() handler and applied
|
||||
* automatically when the core swaps the old and new states.
|
||||
*/
|
||||
|
||||
static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
|
||||
struct rcar_du_plane_state *new_state)
|
||||
{
|
||||
struct rcar_du_plane_state *cur_state;
|
||||
|
||||
cur_state = to_rcar_plane_state(plane->plane.state);
|
||||
|
||||
/* Lowering the number of planes doesn't strictly require reallocation
|
||||
* as the extra hardware plane will be freed when committing, but doing
|
||||
* so could lead to more fragmentation.
|
||||
*/
|
||||
if (!cur_state->format ||
|
||||
cur_state->format->planes != new_state->format->planes)
|
||||
return true;
|
||||
|
||||
/* Reallocate hardware planes if the source has changed. */
|
||||
if (cur_state->source != new_state->source)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
if (state->hwindex == -1)
|
||||
return 0;
|
||||
|
||||
mask = 1 << state->hwindex;
|
||||
if (state->format->planes == 2)
|
||||
mask |= 1 << ((state->hwindex + 1) % 8);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
|
||||
* VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
|
||||
* DU0/1 plane 1.
|
||||
*
|
||||
* Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
|
||||
* and allocate planes in reverse index order otherwise to ensure maximum
|
||||
* availability of planes 0 and 1.
|
||||
*
|
||||
* The caller is responsible for ensuring that the requested source is
|
||||
* compatible with the DU revision.
|
||||
*/
|
||||
static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
|
||||
struct rcar_du_plane_state *state,
|
||||
unsigned int free)
|
||||
{
|
||||
unsigned int num_planes = state->format->planes;
|
||||
int fixed = -1;
|
||||
int i;
|
||||
|
||||
if (state->source == RCAR_DU_PLANE_VSPD0) {
|
||||
/* VSPD0 feeds plane 0 on DU0/1. */
|
||||
if (plane->group->index != 0)
|
||||
return -EINVAL;
|
||||
|
||||
fixed = 0;
|
||||
} else if (state->source == RCAR_DU_PLANE_VSPD1) {
|
||||
/* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
|
||||
fixed = plane->group->index == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
if (fixed >= 0)
|
||||
return free & (1 << fixed) ? fixed : -EBUSY;
|
||||
|
||||
for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
|
||||
if (!(free & (1 << i)))
|
||||
continue;
|
||||
|
||||
if (num_planes == 1 || free & (1 << ((i + 1) % 8)))
|
||||
break;
|
||||
}
|
||||
|
||||
return i < 0 ? -EBUSY : i;
|
||||
}
|
||||
|
||||
int rcar_du_atomic_check_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rcar_du_device *rcdu = dev->dev_private;
|
||||
unsigned int group_freed_planes[RCAR_DU_MAX_GROUPS] = { 0, };
|
||||
unsigned int group_free_planes[RCAR_DU_MAX_GROUPS] = { 0, };
|
||||
bool needs_realloc = false;
|
||||
unsigned int groups = 0;
|
||||
unsigned int i;
|
||||
|
||||
/* Check if hardware planes need to be reallocated. */
|
||||
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct rcar_du_plane *plane;
|
||||
unsigned int index;
|
||||
|
||||
if (!state->planes[i])
|
||||
continue;
|
||||
|
||||
plane = to_rcar_plane(state->planes[i]);
|
||||
plane_state = to_rcar_plane_state(state->plane_states[i]);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: checking plane (%u,%u)\n", __func__,
|
||||
plane->group->index, plane - plane->group->planes);
|
||||
|
||||
/* If the plane is being disabled we don't need to go through
|
||||
* the full reallocation procedure. Just mark the hardware
|
||||
* plane(s) as freed.
|
||||
*/
|
||||
if (!plane_state->format) {
|
||||
dev_dbg(rcdu->dev, "%s: plane is being disabled\n",
|
||||
__func__);
|
||||
index = plane - plane->group->planes;
|
||||
group_freed_planes[plane->group->index] |= 1 << index;
|
||||
plane_state->hwindex = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the plane needs to be reallocated mark it as such, and
|
||||
* mark the hardware plane(s) as free.
|
||||
*/
|
||||
if (rcar_du_plane_needs_realloc(plane, plane_state)) {
|
||||
dev_dbg(rcdu->dev, "%s: plane needs reallocation\n",
|
||||
__func__);
|
||||
groups |= 1 << plane->group->index;
|
||||
needs_realloc = true;
|
||||
|
||||
index = plane - plane->group->planes;
|
||||
group_freed_planes[plane->group->index] |= 1 << index;
|
||||
plane_state->hwindex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!needs_realloc)
|
||||
return 0;
|
||||
|
||||
/* Grab all plane states for the groups that need reallocation to ensure
|
||||
* locking and avoid racy updates. This serializes the update operation,
|
||||
* but there's not much we can do about it as that's the hardware
|
||||
* design.
|
||||
*
|
||||
* Compute the used planes mask for each group at the same time to avoid
|
||||
* looping over the planes separately later.
|
||||
*/
|
||||
while (groups) {
|
||||
unsigned int index = ffs(groups) - 1;
|
||||
struct rcar_du_group *group = &rcdu->groups[index];
|
||||
unsigned int used_planes = 0;
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
|
||||
__func__, index);
|
||||
|
||||
for (i = 0; i < group->num_planes; ++i) {
|
||||
struct rcar_du_plane *plane = &group->planes[i];
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct drm_plane_state *s;
|
||||
|
||||
s = drm_atomic_get_plane_state(state, &plane->plane);
|
||||
if (IS_ERR(s))
|
||||
return PTR_ERR(s);
|
||||
|
||||
/* If the plane has been freed in the above loop its
|
||||
* hardware planes must not be added to the used planes
|
||||
* bitmask. However, the current state doesn't reflect
|
||||
* the free state yet, as we've modified the new state
|
||||
* above. Use the local freed planes list to check for
|
||||
* that condition instead.
|
||||
*/
|
||||
if (group_freed_planes[index] & (1 << i)) {
|
||||
dev_dbg(rcdu->dev,
|
||||
"%s: plane (%u,%u) has been freed, skipping\n",
|
||||
__func__, plane->group->index,
|
||||
plane - plane->group->planes);
|
||||
continue;
|
||||
}
|
||||
|
||||
plane_state = to_rcar_plane_state(plane->plane.state);
|
||||
used_planes |= rcar_du_plane_hwmask(plane_state);
|
||||
|
||||
dev_dbg(rcdu->dev,
|
||||
"%s: plane (%u,%u) uses %u hwplanes (index %d)\n",
|
||||
__func__, plane->group->index,
|
||||
plane - plane->group->planes,
|
||||
plane_state->format ?
|
||||
plane_state->format->planes : 0,
|
||||
plane_state->hwindex);
|
||||
}
|
||||
|
||||
group_free_planes[index] = 0xff & ~used_planes;
|
||||
groups &= ~(1 << index);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
|
||||
__func__, index, group_free_planes[index]);
|
||||
}
|
||||
|
||||
/* Reallocate hardware planes for each plane that needs it. */
|
||||
for (i = 0; i < dev->mode_config.num_total_plane; ++i) {
|
||||
struct rcar_du_plane_state *plane_state;
|
||||
struct rcar_du_plane *plane;
|
||||
unsigned int crtc_planes;
|
||||
unsigned int free;
|
||||
int idx;
|
||||
|
||||
if (!state->planes[i])
|
||||
continue;
|
||||
|
||||
plane = to_rcar_plane(state->planes[i]);
|
||||
plane_state = to_rcar_plane_state(state->plane_states[i]);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: allocating plane (%u,%u)\n", __func__,
|
||||
plane->group->index, plane - plane->group->planes);
|
||||
|
||||
/* Skip planes that are being disabled or don't need to be
|
||||
* reallocated.
|
||||
*/
|
||||
if (!plane_state->format ||
|
||||
!rcar_du_plane_needs_realloc(plane, plane_state))
|
||||
continue;
|
||||
|
||||
/* Try to allocate the plane from the free planes currently
|
||||
* associated with the target CRTC to avoid restarting the CRTC
|
||||
* group and thus minimize flicker. If it fails fall back to
|
||||
* allocating from all free planes.
|
||||
*/
|
||||
crtc_planes = to_rcar_crtc(plane_state->state.crtc)->index % 2
|
||||
? plane->group->dptsr_planes
|
||||
: ~plane->group->dptsr_planes;
|
||||
free = group_free_planes[plane->group->index];
|
||||
|
||||
idx = rcar_du_plane_hwalloc(plane, plane_state,
|
||||
free & crtc_planes);
|
||||
if (idx < 0)
|
||||
idx = rcar_du_plane_hwalloc(plane, plane_state,
|
||||
free);
|
||||
if (idx < 0) {
|
||||
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
|
||||
__func__);
|
||||
return idx;
|
||||
}
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: allocated %u hwplanes (index %u)\n",
|
||||
__func__, plane_state->format->planes, idx);
|
||||
|
||||
plane_state->hwindex = idx;
|
||||
|
||||
group_free_planes[plane->group->index] &=
|
||||
~rcar_du_plane_hwmask(plane_state);
|
||||
|
||||
dev_dbg(rcdu->dev, "%s: group %u free planes mask 0x%02x\n",
|
||||
__func__, plane->group->index,
|
||||
group_free_planes[plane->group->index]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Plane Setup
|
||||
*/
|
||||
|
||||
#define RCAR_DU_COLORKEY_NONE (0 << 24)
|
||||
#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
|
||||
#define RCAR_DU_COLORKEY_MASK (1 << 24)
|
||||
|
|
|
@ -71,6 +71,9 @@ to_rcar_plane_state(struct drm_plane_state *state)
|
|||
return container_of(state, struct rcar_du_plane_state, state);
|
||||
}
|
||||
|
||||
int rcar_du_atomic_check_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
int rcar_du_planes_init(struct rcar_du_group *rgrp);
|
||||
|
||||
void rcar_du_plane_setup(struct rcar_du_plane *plane);
|
||||
|
|
Loading…
Reference in New Issue