Commit 12e412d7 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-fixes-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

drm-misc-fixes before holidays:

- fixup for the lease fixup (Keith)
- fb leak in the ww mutex fallback code (Maarten)
- sun4i fixes (Maxime, Hans)

* tag 'drm-misc-fixes-2017-12-21' of git://anongit.freedesktop.org/drm/drm-misc:
  drm: move lease init after validation in drm_lease_create
  drm/plane: Make framebuffer refcounting the responsibility of setplane_internal callers
  drm/sun4i: hdmi: Move the mode_valid callback to the encoder
  drm/sun4i: Fix error path handling
  drm/sun4i: validate modes for HDMI
parents 5e9748cb d2a48e52
...@@ -220,17 +220,6 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr ...@@ -220,17 +220,6 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
mutex_lock(&dev->mode_config.idr_mutex); mutex_lock(&dev->mode_config.idr_mutex);
/* Insert the new lessee into the tree */
id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
if (id < 0) {
error = id;
goto out_lessee;
}
lessee->lessee_id = id;
lessee->lessor = drm_master_get(lessor);
list_add_tail(&lessee->lessee_list, &lessor->lessees);
idr_for_each_entry(leases, entry, object) { idr_for_each_entry(leases, entry, object) {
error = 0; error = 0;
if (!idr_find(&dev->mode_config.crtc_idr, object)) if (!idr_find(&dev->mode_config.crtc_idr, object))
...@@ -246,6 +235,17 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr ...@@ -246,6 +235,17 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr
} }
} }
/* Insert the new lessee into the tree */
id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
if (id < 0) {
error = id;
goto out_lessee;
}
lessee->lessee_id = id;
lessee->lessor = drm_master_get(lessor);
list_add_tail(&lessee->lessee_list, &lessor->lessees);
/* Move the leases over */ /* Move the leases over */
lessee->leases = *leases; lessee->leases = *leases;
DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor); DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
......
...@@ -558,11 +558,10 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format) ...@@ -558,11 +558,10 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
} }
/* /*
* setplane_internal - setplane handler for internal callers * __setplane_internal - setplane handler for internal callers
* *
* Note that we assume an extra reference has already been taken on fb. If the * This function will take a reference on the new fb for the plane
* update fails, this reference will be dropped before return; if it succeeds, * on success.
* the previous framebuffer (if any) will be unreferenced instead.
* *
* src_{x,y,w,h} are provided in 16.16 fixed point format * src_{x,y,w,h} are provided in 16.16 fixed point format
*/ */
...@@ -630,14 +629,12 @@ static int __setplane_internal(struct drm_plane *plane, ...@@ -630,14 +629,12 @@ static int __setplane_internal(struct drm_plane *plane,
if (!ret) { if (!ret) {
plane->crtc = crtc; plane->crtc = crtc;
plane->fb = fb; plane->fb = fb;
fb = NULL; drm_framebuffer_get(plane->fb);
} else { } else {
plane->old_fb = NULL; plane->old_fb = NULL;
} }
out: out:
if (fb)
drm_framebuffer_put(fb);
if (plane->old_fb) if (plane->old_fb)
drm_framebuffer_put(plane->old_fb); drm_framebuffer_put(plane->old_fb);
plane->old_fb = NULL; plane->old_fb = NULL;
...@@ -685,6 +682,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, ...@@ -685,6 +682,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_plane *plane; struct drm_plane *plane;
struct drm_crtc *crtc = NULL; struct drm_crtc *crtc = NULL;
struct drm_framebuffer *fb = NULL; struct drm_framebuffer *fb = NULL;
int ret;
if (!drm_core_check_feature(dev, DRIVER_MODESET)) if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL; return -EINVAL;
...@@ -717,15 +715,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data, ...@@ -717,15 +715,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
} }
} }
/* ret = setplane_internal(plane, crtc, fb,
* setplane_internal will take care of deref'ing either the old or new plane_req->crtc_x, plane_req->crtc_y,
* framebuffer depending on success. plane_req->crtc_w, plane_req->crtc_h,
*/ plane_req->src_x, plane_req->src_y,
return setplane_internal(plane, crtc, fb, plane_req->src_w, plane_req->src_h);
plane_req->crtc_x, plane_req->crtc_y,
plane_req->crtc_w, plane_req->crtc_h, if (fb)
plane_req->src_x, plane_req->src_y, drm_framebuffer_put(fb);
plane_req->src_w, plane_req->src_h);
return ret;
} }
static int drm_mode_cursor_universal(struct drm_crtc *crtc, static int drm_mode_cursor_universal(struct drm_crtc *crtc,
...@@ -788,13 +787,12 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc, ...@@ -788,13 +787,12 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
src_h = fb->height << 16; src_h = fb->height << 16;
} }
/*
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
ret = __setplane_internal(crtc->cursor, crtc, fb, ret = __setplane_internal(crtc->cursor, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h, crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h, ctx); 0, 0, src_w, src_h, ctx);
if (fb)
drm_framebuffer_put(fb);
/* Update successful; save new cursor position, if necessary */ /* Update successful; save new cursor position, if necessary */
if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
......
...@@ -175,11 +175,31 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -175,11 +175,31 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder,
writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG);
} }
static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder);
unsigned long rate = mode->clock * 1000;
unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */
long rounded_rate;
/* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */
if (rate > 165000000)
return MODE_CLOCK_HIGH;
rounded_rate = clk_round_rate(hdmi->tmds_clk, rate);
if (rounded_rate > 0 &&
max_t(unsigned long, rounded_rate, rate) -
min_t(unsigned long, rounded_rate, rate) < diff)
return MODE_OK;
return MODE_NOCLOCK;
}
static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = {
.atomic_check = sun4i_hdmi_atomic_check, .atomic_check = sun4i_hdmi_atomic_check,
.disable = sun4i_hdmi_disable, .disable = sun4i_hdmi_disable,
.enable = sun4i_hdmi_enable, .enable = sun4i_hdmi_enable,
.mode_set = sun4i_hdmi_mode_set, .mode_set = sun4i_hdmi_mode_set,
.mode_valid = sun4i_hdmi_mode_valid,
}; };
static const struct drm_encoder_funcs sun4i_hdmi_funcs = { static const struct drm_encoder_funcs sun4i_hdmi_funcs = {
......
...@@ -724,12 +724,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, ...@@ -724,12 +724,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
if (IS_ERR(tcon->crtc)) { if (IS_ERR(tcon->crtc)) {
dev_err(dev, "Couldn't create our CRTC\n"); dev_err(dev, "Couldn't create our CRTC\n");
ret = PTR_ERR(tcon->crtc); ret = PTR_ERR(tcon->crtc);
goto err_free_clocks; goto err_free_dotclock;
} }
ret = sun4i_rgb_init(drm, tcon); ret = sun4i_rgb_init(drm, tcon);
if (ret < 0) if (ret < 0)
goto err_free_clocks; goto err_free_dotclock;
if (tcon->quirks->needs_de_be_mux) { if (tcon->quirks->needs_de_be_mux) {
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment