Skip to content

Commit

Permalink
Merge tag 'topic/drm-fixes-2015-11-19' of git://anongit.freedesktop.o…
Browse files Browse the repository at this point in the history
…rg/drm-intel into drm-fixes

Here are some drm core fixes for v4.4 that I've picked up. Atomic fixes
from Maarten, and atomic helper fixes from Ville and Daniel.

Admittedly the topmost commit didn't sit in our tree for very long, but
does come with reviews and testing from trustworthy people.

* tag 'topic/drm-fixes-2015-11-19' of git://anongit.freedesktop.org/drm-intel:
  drm/atomic-helper: Check encoder/crtc constraints
  drm: Fix primary plane size for stereo doubled modes for legacy setcrtc
  drm/core: Fix old_fb handling in pan_display_atomic.
  drm/core: Fix old_fb handling in restore_fbdev_mode_atomic.
  drm/atomic: add a drm_atomic_clean_old_fb helper.
  drm/core: Fix old_fb handling in drm_mode_atomic_ioctl.
  drm/core: Set legacy_cursor_update in drm_atomic_helper_disable_plane.
  • Loading branch information
airlied committed Nov 19, 2015
2 parents f6619ef + 5481c8f commit db39563
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 65 deletions.
61 changes: 42 additions & 19 deletions drivers/gpu/drm/drm_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state,
return ret;
}

/**
* drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
*
* @dev: drm device to check.
* @plane_mask: plane mask for planes that were updated.
* @ret: return value, can be -EDEADLK for a retry.
*
* Before doing an update plane->old_fb is set to plane->fb,
* but before dropping the locks old_fb needs to be set to NULL
* and plane->fb updated. This is a common operation for each
* atomic update, so this call is split off as a helper.
*/
void drm_atomic_clean_old_fb(struct drm_device *dev,
unsigned plane_mask,
int ret)
{
struct drm_plane *plane;

/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
* locks (ie. while it is still safe to deref plane->state). We
* need to do this here because the driver entry points cannot
* distinguish between legacy and atomic ioctls.
*/
drm_for_each_plane_mask(plane, dev, plane_mask) {
if (ret == 0) {
struct drm_framebuffer *new_fb = plane->state->fb;
if (new_fb)
drm_framebuffer_reference(new_fb);
plane->fb = new_fb;
plane->crtc = plane->state->crtc;

if (plane->old_fb)
drm_framebuffer_unreference(plane->old_fb);
}
plane->old_fb = NULL;
}
}
EXPORT_SYMBOL(drm_atomic_clean_old_fb);

int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
Expand All @@ -1446,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_crtc_state *crtc_state;
unsigned plane_mask = 0;
unsigned plane_mask;
int ret = 0;
unsigned int i, j;

Expand Down Expand Up @@ -1486,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);

retry:
plane_mask = 0;
copied_objs = 0;
copied_props = 0;

Expand Down Expand Up @@ -1576,24 +1616,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
}

out:
/* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
* locks (ie. while it is still safe to deref plane->state). We
* need to do this here because the driver entry points cannot
* distinguish between legacy and atomic ioctls.
*/
drm_for_each_plane_mask(plane, dev, plane_mask) {
if (ret == 0) {
struct drm_framebuffer *new_fb = plane->state->fb;
if (new_fb)
drm_framebuffer_reference(new_fb);
plane->fb = new_fb;
plane->crtc = plane->state->crtc;

if (plane->old_fb)
drm_framebuffer_unreference(plane->old_fb);
}
plane->old_fb = NULL;
}
drm_atomic_clean_old_fb(dev, plane_mask, ret);

if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
/*
Expand Down
29 changes: 20 additions & 9 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,14 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
return -EINVAL;
}

if (!drm_encoder_crtc_ok(new_encoder, connector_state->crtc)) {
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] incompatible with [CRTC:%d]\n",
new_encoder->base.id,
new_encoder->name,
connector_state->crtc->base.id);
return -EINVAL;
}

if (new_encoder == connector_state->best_encoder) {
DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] keeps [ENCODER:%d:%s], now on [CRTC:%d]\n",
connector->base.id,
Expand Down Expand Up @@ -1553,6 +1561,9 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
goto fail;
}

if (plane_state->crtc && (plane == plane->crtc->cursor))
plane_state->state->legacy_cursor_update = true;

ret = __drm_atomic_helper_disable_plane(plane, plane_state);
if (ret != 0)
goto fail;
Expand Down Expand Up @@ -1605,9 +1616,6 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
plane_state->src_h = 0;
plane_state->src_w = 0;

if (plane->crtc && (plane == plane->crtc->cursor))
plane_state->state->legacy_cursor_update = true;

return 0;
}

Expand Down Expand Up @@ -1741,6 +1749,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
struct drm_crtc_state *crtc_state;
struct drm_plane_state *primary_state;
struct drm_crtc *crtc = set->crtc;
int hdisplay, vdisplay;
int ret;

crtc_state = drm_atomic_get_crtc_state(state, crtc);
Expand Down Expand Up @@ -1783,19 +1792,21 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
if (ret != 0)
return ret;

drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);

drm_atomic_set_fb_for_plane(primary_state, set->fb);
primary_state->crtc_x = 0;
primary_state->crtc_y = 0;
primary_state->crtc_h = set->mode->vdisplay;
primary_state->crtc_w = set->mode->hdisplay;
primary_state->crtc_h = vdisplay;
primary_state->crtc_w = hdisplay;
primary_state->src_x = set->x << 16;
primary_state->src_y = set->y << 16;
if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
primary_state->src_h = set->mode->hdisplay << 16;
primary_state->src_w = set->mode->vdisplay << 16;
primary_state->src_h = hdisplay << 16;
primary_state->src_w = vdisplay << 16;
} else {
primary_state->src_h = set->mode->vdisplay << 16;
primary_state->src_w = set->mode->hdisplay << 16;
primary_state->src_h = vdisplay << 16;
primary_state->src_w = hdisplay << 16;
}

commit:
Expand Down
51 changes: 14 additions & 37 deletions drivers/gpu/drm/drm_fb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,18 +342,18 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
struct drm_plane *plane;
struct drm_atomic_state *state;
int i, ret;
unsigned plane_mask;

state = drm_atomic_state_alloc(dev);
if (!state)
return -ENOMEM;

state->acquire_ctx = dev->mode_config.acquire_ctx;
retry:
plane_mask = 0;
drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;

plane->old_fb = plane->fb;

plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
Expand All @@ -362,6 +362,9 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)

plane_state->rotation = BIT(DRM_ROTATE_0);

plane->old_fb = plane->fb;
plane_mask |= 1 << drm_plane_index(plane);

/* disable non-primary: */
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
continue;
Expand All @@ -382,19 +385,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
ret = drm_atomic_commit(state);

fail:
drm_for_each_plane(plane, dev) {
if (ret == 0) {
struct drm_framebuffer *new_fb = plane->state->fb;
if (new_fb)
drm_framebuffer_reference(new_fb);
plane->fb = new_fb;
plane->crtc = plane->state->crtc;

if (plane->old_fb)
drm_framebuffer_unreference(plane->old_fb);
}
plane->old_fb = NULL;
}
drm_atomic_clean_old_fb(dev, plane_mask, ret);

if (ret == -EDEADLK)
goto backoff;
Expand Down Expand Up @@ -1236,27 +1227,32 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
struct drm_fb_helper *fb_helper = info->par;
struct drm_device *dev = fb_helper->dev;
struct drm_atomic_state *state;
struct drm_plane *plane;
int i, ret;
unsigned plane_mask;

state = drm_atomic_state_alloc(dev);
if (!state)
return -ENOMEM;

state->acquire_ctx = dev->mode_config.acquire_ctx;
retry:
plane_mask = 0;
for(i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set;

mode_set = &fb_helper->crtc_info[i].mode_set;

mode_set->crtc->primary->old_fb = mode_set->crtc->primary->fb;

mode_set->x = var->xoffset;
mode_set->y = var->yoffset;

ret = __drm_atomic_helper_set_config(mode_set, state);
if (ret != 0)
goto fail;

plane = mode_set->crtc->primary;
plane_mask |= drm_plane_index(plane);
plane->old_fb = plane->fb;
}

ret = drm_atomic_commit(state);
Expand All @@ -1268,26 +1264,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,


fail:
for(i = 0; i < fb_helper->crtc_count; i++) {
struct drm_mode_set *mode_set;
struct drm_plane *plane;

mode_set = &fb_helper->crtc_info[i].mode_set;
plane = mode_set->crtc->primary;

if (ret == 0) {
struct drm_framebuffer *new_fb = plane->state->fb;

if (new_fb)
drm_framebuffer_reference(new_fb);
plane->fb = new_fb;
plane->crtc = plane->state->crtc;

if (plane->old_fb)
drm_framebuffer_unreference(plane->old_fb);
}
plane->old_fb = NULL;
}
drm_atomic_clean_old_fb(dev, plane_mask, ret);

if (ret == -EDEADLK)
goto backoff;
Expand Down
3 changes: 3 additions & 0 deletions include/drm/drm_atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ drm_atomic_connectors_for_crtc(struct drm_atomic_state *state,

void drm_atomic_legacy_backoff(struct drm_atomic_state *state);

void
drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);

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);
Expand Down

0 comments on commit db39563

Please sign in to comment.