diff options
author | Dave Airlie <airlied@redhat.com> | 2017-12-21 19:00:04 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-12-21 19:00:04 -0500 |
commit | 12e412d785c716fbdcc6021c599f61c48e2872ef (patch) | |
tree | 6f341b81df9123e5139c4f2941fad6d7a719516f | |
parent | 5e9748cb4b1c4f15e549e3fc970e9727f027de49 (diff) | |
parent | d2a48e52541cdf474ef35d51e8d73ded5be33122 (diff) |
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
-rw-r--r-- | drivers/gpu/drm/drm_lease.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_plane.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 |
4 files changed, 53 insertions, 35 deletions
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c index 59849f02e2ad..1402c0e71b03 100644 --- a/drivers/gpu/drm/drm_lease.c +++ b/drivers/gpu/drm/drm_lease.c | |||
@@ -220,17 +220,6 @@ static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr | |||
220 | 220 | ||
221 | mutex_lock(&dev->mode_config.idr_mutex); | 221 | mutex_lock(&dev->mode_config.idr_mutex); |
222 | 222 | ||
223 | /* Insert the new lessee into the tree */ | ||
224 | id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); | ||
225 | if (id < 0) { | ||
226 | error = id; | ||
227 | goto out_lessee; | ||
228 | } | ||
229 | |||
230 | lessee->lessee_id = id; | ||
231 | lessee->lessor = drm_master_get(lessor); | ||
232 | list_add_tail(&lessee->lessee_list, &lessor->lessees); | ||
233 | |||
234 | idr_for_each_entry(leases, entry, object) { | 223 | idr_for_each_entry(leases, entry, object) { |
235 | error = 0; | 224 | error = 0; |
236 | if (!idr_find(&dev->mode_config.crtc_idr, object)) | 225 | 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 | } | 235 | } |
247 | } | 236 | } |
248 | 237 | ||
238 | /* Insert the new lessee into the tree */ | ||
239 | id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); | ||
240 | if (id < 0) { | ||
241 | error = id; | ||
242 | goto out_lessee; | ||
243 | } | ||
244 | |||
245 | lessee->lessee_id = id; | ||
246 | lessee->lessor = drm_master_get(lessor); | ||
247 | list_add_tail(&lessee->lessee_list, &lessor->lessees); | ||
248 | |||
249 | /* Move the leases over */ | 249 | /* Move the leases over */ |
250 | lessee->leases = *leases; | 250 | lessee->leases = *leases; |
251 | DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor); | 251 | DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor); |
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 37a93cdffb4a..2c90519576a3 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c | |||
@@ -558,11 +558,10 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format) | |||
558 | } | 558 | } |
559 | 559 | ||
560 | /* | 560 | /* |
561 | * setplane_internal - setplane handler for internal callers | 561 | * __setplane_internal - setplane handler for internal callers |
562 | * | 562 | * |
563 | * Note that we assume an extra reference has already been taken on fb. If the | 563 | * This function will take a reference on the new fb for the plane |
564 | * update fails, this reference will be dropped before return; if it succeeds, | 564 | * on success. |
565 | * the previous framebuffer (if any) will be unreferenced instead. | ||
566 | * | 565 | * |
567 | * src_{x,y,w,h} are provided in 16.16 fixed point format | 566 | * src_{x,y,w,h} are provided in 16.16 fixed point format |
568 | */ | 567 | */ |
@@ -630,14 +629,12 @@ static int __setplane_internal(struct drm_plane *plane, | |||
630 | if (!ret) { | 629 | if (!ret) { |
631 | plane->crtc = crtc; | 630 | plane->crtc = crtc; |
632 | plane->fb = fb; | 631 | plane->fb = fb; |
633 | fb = NULL; | 632 | drm_framebuffer_get(plane->fb); |
634 | } else { | 633 | } else { |
635 | plane->old_fb = NULL; | 634 | plane->old_fb = NULL; |
636 | } | 635 | } |
637 | 636 | ||
638 | out: | 637 | out: |
639 | if (fb) | ||
640 | drm_framebuffer_put(fb); | ||
641 | if (plane->old_fb) | 638 | if (plane->old_fb) |
642 | drm_framebuffer_put(plane->old_fb); | 639 | drm_framebuffer_put(plane->old_fb); |
643 | plane->old_fb = NULL; | 640 | plane->old_fb = NULL; |
@@ -685,6 +682,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
685 | struct drm_plane *plane; | 682 | struct drm_plane *plane; |
686 | struct drm_crtc *crtc = NULL; | 683 | struct drm_crtc *crtc = NULL; |
687 | struct drm_framebuffer *fb = NULL; | 684 | struct drm_framebuffer *fb = NULL; |
685 | int ret; | ||
688 | 686 | ||
689 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 687 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
690 | return -EINVAL; | 688 | return -EINVAL; |
@@ -717,15 +715,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
717 | } | 715 | } |
718 | } | 716 | } |
719 | 717 | ||
720 | /* | 718 | ret = setplane_internal(plane, crtc, fb, |
721 | * setplane_internal will take care of deref'ing either the old or new | 719 | plane_req->crtc_x, plane_req->crtc_y, |
722 | * framebuffer depending on success. | 720 | plane_req->crtc_w, plane_req->crtc_h, |
723 | */ | 721 | plane_req->src_x, plane_req->src_y, |
724 | return setplane_internal(plane, crtc, fb, | 722 | plane_req->src_w, plane_req->src_h); |
725 | plane_req->crtc_x, plane_req->crtc_y, | 723 | |
726 | plane_req->crtc_w, plane_req->crtc_h, | 724 | if (fb) |
727 | plane_req->src_x, plane_req->src_y, | 725 | drm_framebuffer_put(fb); |
728 | plane_req->src_w, plane_req->src_h); | 726 | |
727 | return ret; | ||
729 | } | 728 | } |
730 | 729 | ||
731 | static int drm_mode_cursor_universal(struct drm_crtc *crtc, | 730 | 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 | src_h = fb->height << 16; | 787 | src_h = fb->height << 16; |
789 | } | 788 | } |
790 | 789 | ||
791 | /* | ||
792 | * setplane_internal will take care of deref'ing either the old or new | ||
793 | * framebuffer depending on success. | ||
794 | */ | ||
795 | ret = __setplane_internal(crtc->cursor, crtc, fb, | 790 | ret = __setplane_internal(crtc->cursor, crtc, fb, |
796 | crtc_x, crtc_y, crtc_w, crtc_h, | 791 | crtc_x, crtc_y, crtc_w, crtc_h, |
797 | 0, 0, src_w, src_h, ctx); | 792 | 0, 0, src_w, src_h, ctx); |
793 | |||
794 | if (fb) | ||
795 | drm_framebuffer_put(fb); | ||
798 | 796 | ||
799 | /* Update successful; save new cursor position, if necessary */ | 797 | /* Update successful; save new cursor position, if necessary */ |
800 | if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { | 798 | if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) { |
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index dda904ec0534..500b6fb3e028 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | |||
@@ -175,11 +175,31 @@ static void sun4i_hdmi_mode_set(struct drm_encoder *encoder, | |||
175 | writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); | 175 | writel(val, hdmi->base + SUN4I_HDMI_VID_TIMING_POL_REG); |
176 | } | 176 | } |
177 | 177 | ||
178 | static enum drm_mode_status sun4i_hdmi_mode_valid(struct drm_encoder *encoder, | ||
179 | const struct drm_display_mode *mode) | ||
180 | { | ||
181 | struct sun4i_hdmi *hdmi = drm_encoder_to_sun4i_hdmi(encoder); | ||
182 | unsigned long rate = mode->clock * 1000; | ||
183 | unsigned long diff = rate / 200; /* +-0.5% allowed by HDMI spec */ | ||
184 | long rounded_rate; | ||
185 | |||
186 | /* 165 MHz is the typical max pixelclock frequency for HDMI <= 1.2 */ | ||
187 | if (rate > 165000000) | ||
188 | return MODE_CLOCK_HIGH; | ||
189 | rounded_rate = clk_round_rate(hdmi->tmds_clk, rate); | ||
190 | if (rounded_rate > 0 && | ||
191 | max_t(unsigned long, rounded_rate, rate) - | ||
192 | min_t(unsigned long, rounded_rate, rate) < diff) | ||
193 | return MODE_OK; | ||
194 | return MODE_NOCLOCK; | ||
195 | } | ||
196 | |||
178 | static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { | 197 | static const struct drm_encoder_helper_funcs sun4i_hdmi_helper_funcs = { |
179 | .atomic_check = sun4i_hdmi_atomic_check, | 198 | .atomic_check = sun4i_hdmi_atomic_check, |
180 | .disable = sun4i_hdmi_disable, | 199 | .disable = sun4i_hdmi_disable, |
181 | .enable = sun4i_hdmi_enable, | 200 | .enable = sun4i_hdmi_enable, |
182 | .mode_set = sun4i_hdmi_mode_set, | 201 | .mode_set = sun4i_hdmi_mode_set, |
202 | .mode_valid = sun4i_hdmi_mode_valid, | ||
183 | }; | 203 | }; |
184 | 204 | ||
185 | static const struct drm_encoder_funcs sun4i_hdmi_funcs = { | 205 | static const struct drm_encoder_funcs sun4i_hdmi_funcs = { |
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index e122f5b2a395..f4284b51bdca 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c | |||
@@ -724,12 +724,12 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master, | |||
724 | if (IS_ERR(tcon->crtc)) { | 724 | if (IS_ERR(tcon->crtc)) { |
725 | dev_err(dev, "Couldn't create our CRTC\n"); | 725 | dev_err(dev, "Couldn't create our CRTC\n"); |
726 | ret = PTR_ERR(tcon->crtc); | 726 | ret = PTR_ERR(tcon->crtc); |
727 | goto err_free_clocks; | 727 | goto err_free_dotclock; |
728 | } | 728 | } |
729 | 729 | ||
730 | ret = sun4i_rgb_init(drm, tcon); | 730 | ret = sun4i_rgb_init(drm, tcon); |
731 | if (ret < 0) | 731 | if (ret < 0) |
732 | goto err_free_clocks; | 732 | goto err_free_dotclock; |
733 | 733 | ||
734 | if (tcon->quirks->needs_de_be_mux) { | 734 | if (tcon->quirks->needs_de_be_mux) { |
735 | /* | 735 | /* |