Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev into drm-next
rcar-du fixes * 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev: drm: rcar-du: Use the drm atomic state duplication helpers for planes drm: rcar-du: Clean up planes in the error paths of .atomic_commit() drm: rcar-du: Convert rcar_du_encoders_init_one() return value to 0/<0 drm: rcar-du: Clarify error message when encoder initialization fails drm: rcar-du: Fix crash with groups that have less than 9 planes drm: rcar-du: Disable all planes when stopping the CRTC drm: rcar-du: Print the error value when DRM/KMS init fails
This commit is contained in:
commit
a21be4ece9
|
@ -214,7 +214,7 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u32 dspr = 0;
|
u32 dspr = 0;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
|
for (i = 0; i < rcrtc->group->num_planes; ++i) {
|
||||||
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
|
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
|
||||||
unsigned int j;
|
unsigned int j;
|
||||||
|
|
||||||
|
@ -398,6 +398,19 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
|
||||||
if (!rcrtc->started)
|
if (!rcrtc->started)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Disable all planes and wait for the change to take effect. This is
|
||||||
|
* required as the DSnPR registers are updated on vblank, and no vblank
|
||||||
|
* will occur once the CRTC is stopped. Disabling planes when starting
|
||||||
|
* the CRTC thus wouldn't be enough as it would start scanning out
|
||||||
|
* immediately from old frame buffers until the next vblank.
|
||||||
|
*
|
||||||
|
* This increases the CRTC stop delay, especially when multiple CRTCs
|
||||||
|
* are stopped in one operation as we now wait for one vblank per CRTC.
|
||||||
|
* Whether this can be improved needs to be researched.
|
||||||
|
*/
|
||||||
|
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
|
||||||
|
drm_crtc_wait_one_vblank(crtc);
|
||||||
|
|
||||||
/* Disable vertical blanking interrupt reporting. We first need to wait
|
/* Disable vertical blanking interrupt reporting. We first need to wait
|
||||||
* for page flip completion before stopping the CRTC as userspace
|
* for page flip completion before stopping the CRTC as userspace
|
||||||
* expects page flips to eventually complete.
|
* expects page flips to eventually complete.
|
||||||
|
@ -432,7 +445,7 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
|
||||||
rcar_du_crtc_start(rcrtc);
|
rcar_du_crtc_start(rcrtc);
|
||||||
|
|
||||||
/* Commit the planes state. */
|
/* Commit the planes state. */
|
||||||
for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes); ++i) {
|
for (i = 0; i < rcrtc->group->num_planes; ++i) {
|
||||||
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
|
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
|
||||||
|
|
||||||
if (plane->plane.state->crtc != &rcrtc->crtc)
|
if (plane->plane.state->crtc != &rcrtc->crtc)
|
||||||
|
|
|
@ -190,7 +190,7 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
|
||||||
/* DRM/KMS objects */
|
/* DRM/KMS objects */
|
||||||
ret = rcar_du_modeset_init(rcdu);
|
ret = rcar_du_modeset_init(rcdu);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "failed to initialize DRM/KMS\n");
|
dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct rcar_du_device;
|
||||||
* @used_crtcs: number of CRTCs currently in use
|
* @used_crtcs: number of CRTCs currently in use
|
||||||
* @lock: protects the dptsr_planes field and the DPTSR register
|
* @lock: protects the dptsr_planes field and the DPTSR register
|
||||||
* @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
|
* @dptsr_planes: bitmask of planes driven by dot-clock and timing generator 1
|
||||||
|
* @num_planes: number of planes in the group
|
||||||
* @planes: planes handled by the group
|
* @planes: planes handled by the group
|
||||||
*/
|
*/
|
||||||
struct rcar_du_group {
|
struct rcar_du_group {
|
||||||
|
@ -44,6 +45,7 @@ struct rcar_du_group {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
unsigned int dptsr_planes;
|
unsigned int dptsr_planes;
|
||||||
|
|
||||||
|
unsigned int num_planes;
|
||||||
struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
|
struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,7 @@ static int rcar_du_atomic_check(struct drm_device *dev,
|
||||||
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
|
dev_dbg(rcdu->dev, "%s: finding free planes for group %u\n",
|
||||||
__func__, index);
|
__func__, index);
|
||||||
|
|
||||||
for (i = 0; i < RCAR_DU_NUM_KMS_PLANES; ++i) {
|
for (i = 0; i < group->num_planes; ++i) {
|
||||||
struct rcar_du_plane *plane = &group->planes[i];
|
struct rcar_du_plane *plane = &group->planes[i];
|
||||||
struct rcar_du_plane_state *plane_state;
|
struct rcar_du_plane_state *plane_state;
|
||||||
struct drm_plane_state *s;
|
struct drm_plane_state *s;
|
||||||
|
@ -495,8 +495,10 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
|
||||||
|
|
||||||
/* Allocate the commit object. */
|
/* Allocate the commit object. */
|
||||||
commit = kzalloc(sizeof(*commit), GFP_KERNEL);
|
commit = kzalloc(sizeof(*commit), GFP_KERNEL);
|
||||||
if (commit == NULL)
|
if (commit == NULL) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
INIT_WORK(&commit->work, rcar_du_atomic_work);
|
INIT_WORK(&commit->work, rcar_du_atomic_work);
|
||||||
commit->dev = dev;
|
commit->dev = dev;
|
||||||
|
@ -519,7 +521,7 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(commit);
|
kfree(commit);
|
||||||
return ret;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap the state, this is the point of no return. */
|
/* Swap the state, this is the point of no return. */
|
||||||
|
@ -531,6 +533,10 @@ static int rcar_du_atomic_commit(struct drm_device *dev,
|
||||||
rcar_du_atomic_complete(commit);
|
rcar_du_atomic_complete(commit);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
drm_atomic_helper_cleanup_planes(dev, state);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
@ -573,7 +579,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n",
|
dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n",
|
||||||
ep->local_node->full_name);
|
ep->local_node->full_name);
|
||||||
return 0;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0);
|
entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0);
|
||||||
|
@ -596,7 +602,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
|
||||||
encoder->full_name);
|
encoder->full_name);
|
||||||
of_node_put(entity_ep_node);
|
of_node_put(entity_ep_node);
|
||||||
of_node_put(encoder);
|
of_node_put(encoder);
|
||||||
return 0;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -625,7 +631,7 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
|
||||||
encoder->full_name);
|
encoder->full_name);
|
||||||
of_node_put(encoder);
|
of_node_put(encoder);
|
||||||
of_node_put(connector);
|
of_node_put(connector);
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
@ -639,7 +645,12 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
|
||||||
of_node_put(encoder);
|
of_node_put(encoder);
|
||||||
of_node_put(connector);
|
of_node_put(connector);
|
||||||
|
|
||||||
return ret < 0 ? ret : 1;
|
if (ret && ret != -EPROBE_DEFER)
|
||||||
|
dev_warn(rcdu->dev,
|
||||||
|
"failed to initialize encoder %s (%d), skipping\n",
|
||||||
|
encoder->full_name, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
|
static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
|
||||||
|
@ -688,12 +699,10 @@ static int rcar_du_encoders_init(struct rcar_du_device *rcdu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(rcdu->dev,
|
|
||||||
"encoder initialization failed, skipping\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_encoders += ret;
|
num_encoders++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return num_encoders;
|
return num_encoders;
|
||||||
|
|
|
@ -302,13 +302,15 @@ rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
|
||||||
struct rcar_du_plane_state *state;
|
struct rcar_du_plane_state *state;
|
||||||
struct rcar_du_plane_state *copy;
|
struct rcar_du_plane_state *copy;
|
||||||
|
|
||||||
|
if (WARN_ON(!plane->state))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
state = to_rcar_plane_state(plane->state);
|
state = to_rcar_plane_state(plane->state);
|
||||||
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
|
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
|
||||||
if (copy == NULL)
|
if (copy == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (copy->state.fb)
|
__drm_atomic_helper_plane_duplicate_state(plane, ©->state);
|
||||||
drm_framebuffer_reference(copy->state.fb);
|
|
||||||
|
|
||||||
return ©->state;
|
return ©->state;
|
||||||
}
|
}
|
||||||
|
@ -316,9 +318,7 @@ rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
|
||||||
static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
|
static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
|
||||||
struct drm_plane_state *state)
|
struct drm_plane_state *state)
|
||||||
{
|
{
|
||||||
if (state->fb)
|
__drm_atomic_helper_plane_destroy_state(plane, state);
|
||||||
drm_framebuffer_unreference(state->fb);
|
|
||||||
|
|
||||||
kfree(to_rcar_plane_state(state));
|
kfree(to_rcar_plane_state(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,7 +390,6 @@ static const uint32_t formats[] = {
|
||||||
int rcar_du_planes_init(struct rcar_du_group *rgrp)
|
int rcar_du_planes_init(struct rcar_du_group *rgrp)
|
||||||
{
|
{
|
||||||
struct rcar_du_device *rcdu = rgrp->dev;
|
struct rcar_du_device *rcdu = rgrp->dev;
|
||||||
unsigned int num_planes;
|
|
||||||
unsigned int crtcs;
|
unsigned int crtcs;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -398,11 +397,11 @@ int rcar_du_planes_init(struct rcar_du_group *rgrp)
|
||||||
/* Create one primary plane per CRTC in this group and seven overlay
|
/* Create one primary plane per CRTC in this group and seven overlay
|
||||||
* planes.
|
* planes.
|
||||||
*/
|
*/
|
||||||
num_planes = rgrp->num_crtcs + 7;
|
rgrp->num_planes = rgrp->num_crtcs + 7;
|
||||||
|
|
||||||
crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
|
crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
|
||||||
|
|
||||||
for (i = 0; i < num_planes; ++i) {
|
for (i = 0; i < rgrp->num_planes; ++i) {
|
||||||
enum drm_plane_type type = i < rgrp->num_crtcs
|
enum drm_plane_type type = i < rgrp->num_crtcs
|
||||||
? DRM_PLANE_TYPE_PRIMARY
|
? DRM_PLANE_TYPE_PRIMARY
|
||||||
: DRM_PLANE_TYPE_OVERLAY;
|
: DRM_PLANE_TYPE_OVERLAY;
|
||||||
|
|
Loading…
Reference in a new issue