aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Roper <matthew.d.roper@intel.com>2014-12-23 13:41:52 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-01-12 17:59:31 -0500
commitea2c67bb4affa84080c616920f3899f123786e56 (patch)
tree595c4e7deafc2093bf60790530e85ec998c8128b
parent4a3b8769f8b847d1dc3c0c14a0b0e1878be2d01c (diff)
drm/i915: Move to atomic plane helpers (v9)
Switch plane handling to use the atomic plane helpers. This means that rather than provide our own implementations of .update_plane() and .disable_plane(), we expose the lower-level check/prepare/commit/cleanup entrypoints and let the DRM core implement update/disable for us using those entrypoints. The other main change that falls out of this patch is that our drm_plane's will now always have a valid plane->state that contains the relevant plane state (initial state is allocated at plane creation). The base drm_plane_state pointed to holds the requested source/dest coordinates, and the subclassed intel_plane_state holds the adjusted values that our driver actually uses. v2: - Renamed file from intel_atomic.c to intel_atomic_plane.c (Daniel) - Fix a copy/paste comment mistake (Bob) v3: - Use prepare/cleanup functions that we've already factored out - Use newly refactored pre_commit/commit/post_commit to avoid sleeping during vblank evasion v4: - Rebase to latest di-nightly requires adding an 'old_state' parameter to atomic_update; v5: - Must have botched a rebase somewhere and lost some work. Restore state 'dirty' flag to let begin/end code know which planes to run the pre_commit/post_commit hooks for. This would have actually shown up as broken in the next commit rather than this one. v6: - Squash kerneldoc patch into this one. - Previous patches have now already taken care of most of the infrastructure that used to be in this patch. All we're adding here now is some thin wrappers. v7: - Check return of intel_plane_duplicate_state() for allocation failures. v8: - Drop unused drm_plane_state -> intel_plane_state cast. (Ander) - Squash in actual transition to plane helpers. Significant refactoring earlier in the patchset has made the combined prep+transition much easier to swallow than it was in earlier iterations. (Ander) v9: - s/track_fbs/disabled_planes/ in the atomic crtc flags. The only fb's we need to update frontbuffer tracking for are those on a plane about to be disabled (since the atomic helpers never call prepare_fb() when disabling a plane), so the new name more accurately describes what we're actually tracking. Testcase: igt/kms_plane Testcase: igt/kms_universal_plane Testcase: igt/kms_cursor_crc Signed-off-by: Matt Roper <matthew.d.roper@intel.com> Reviewed-by: Ander Conselvan de Oliveira <conselvan2@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--Documentation/DocBook/drm.tmpl5
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/intel_atomic_plane.c151
-rw-r--r--drivers/gpu/drm/i915/intel_display.c251
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h10
-rw-r--r--drivers/gpu/drm/i915/intel_sprite.c50
6 files changed, 303 insertions, 165 deletions
diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl
index 0d1e70c37a33..10cffd95fd7e 100644
--- a/Documentation/DocBook/drm.tmpl
+++ b/Documentation/DocBook/drm.tmpl
@@ -3932,6 +3932,11 @@ int num_ioctls;</synopsis>
3932 </para> 3932 </para>
3933 </sect2> 3933 </sect2>
3934 <sect2> 3934 <sect2>
3935 <title>Atomic Plane Helpers</title>
3936!Pdrivers/gpu/drm/i915/intel_atomic_plane.c atomic plane helpers
3937!Idrivers/gpu/drm/i915/intel_atomic_plane.c
3938 </sect2>
3939 <sect2>
3935 <title>Output Probing</title> 3940 <title>Output Probing</title>
3936 <para> 3941 <para>
3937 This section covers output probing and related infrastructure like the 3942 This section covers output probing and related infrastructure like the
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 1849ffae61ae..16e3dc350274 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -66,6 +66,7 @@ i915-y += dvo_ch7017.o \
66 dvo_ns2501.o \ 66 dvo_ns2501.o \
67 dvo_sil164.o \ 67 dvo_sil164.o \
68 dvo_tfp410.o \ 68 dvo_tfp410.o \
69 intel_atomic_plane.o \
69 intel_crt.o \ 70 intel_crt.o \
70 intel_ddi.o \ 71 intel_ddi.o \
71 intel_dp.o \ 72 intel_dp.o \
diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
new file mode 100644
index 000000000000..e7425d6ca36f
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright © 2014 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/**
25 * DOC: atomic plane helper support
26 *
27 * The functions here are used by the atomic plane helper functions to
28 * implement legacy plane updates (i.e., drm_plane->update_plane() and
29 * drm_plane->disable_plane()). This allows plane updates to use the
30 * atomic state infrastructure and perform plane updates as separate
31 * prepare/check/commit/cleanup steps.
32 */
33
34#include <drm/drmP.h>
35#include <drm/drm_atomic_helper.h>
36#include <drm/drm_plane_helper.h>
37#include "intel_drv.h"
38
39/**
40 * intel_plane_duplicate_state - duplicate plane state
41 * @plane: drm plane
42 *
43 * Allocates and returns a copy of the plane state (both common and
44 * Intel-specific) for the specified plane.
45 *
46 * Returns: The newly allocated plane state, or NULL or failure.
47 */
48struct drm_plane_state *
49intel_plane_duplicate_state(struct drm_plane *plane)
50{
51 struct intel_plane_state *state;
52
53 if (plane->state)
54 state = kmemdup(plane->state, sizeof(*state), GFP_KERNEL);
55 else
56 state = kzalloc(sizeof(*state), GFP_KERNEL);
57
58 if (!state)
59 return NULL;
60
61 if (state->base.fb)
62 drm_framebuffer_reference(state->base.fb);
63
64 return &state->base;
65}
66
67/**
68 * intel_plane_destroy_state - destroy plane state
69 * @plane: drm plane
70 *
71 * Destroys the plane state (both common and Intel-specific) for the
72 * specified plane.
73 */
74void
75intel_plane_destroy_state(struct drm_plane *plane,
76 struct drm_plane_state *state)
77{
78 drm_atomic_helper_plane_destroy_state(plane, state);
79}
80
81static int intel_plane_atomic_check(struct drm_plane *plane,
82 struct drm_plane_state *state)
83{
84 struct drm_crtc *crtc = state->crtc;
85 struct intel_crtc *intel_crtc;
86 struct intel_plane *intel_plane = to_intel_plane(plane);
87 struct intel_plane_state *intel_state = to_intel_plane_state(state);
88
89 crtc = crtc ? crtc : plane->crtc;
90 intel_crtc = to_intel_crtc(crtc);
91
92 /*
93 * The original src/dest coordinates are stored in state->base, but
94 * we want to keep another copy internal to our driver that we can
95 * clip/modify ourselves.
96 */
97 intel_state->src.x1 = state->src_x;
98 intel_state->src.y1 = state->src_y;
99 intel_state->src.x2 = state->src_x + state->src_w;
100 intel_state->src.y2 = state->src_y + state->src_h;
101 intel_state->dst.x1 = state->crtc_x;
102 intel_state->dst.y1 = state->crtc_y;
103 intel_state->dst.x2 = state->crtc_x + state->crtc_w;
104 intel_state->dst.y2 = state->crtc_y + state->crtc_h;
105
106 /* Clip all planes to CRTC size, or 0x0 if CRTC is disabled */
107 intel_state->clip.x1 = 0;
108 intel_state->clip.y1 = 0;
109 intel_state->clip.x2 =
110 intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
111 intel_state->clip.y2 =
112 intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
113
114 /*
115 * Disabling a plane is always okay; we just need to update
116 * fb tracking in a special way since cleanup_fb() won't
117 * get called by the plane helpers.
118 */
119 if (state->fb == NULL && plane->state->fb != NULL) {
120 /*
121 * 'prepare' is never called when plane is being disabled, so
122 * we need to handle frontbuffer tracking as a special case
123 */
124 intel_crtc->atomic.disabled_planes |=
125 (1 << drm_plane_index(plane));
126 }
127
128 return intel_plane->check_plane(plane, intel_state);
129}
130
131static void intel_plane_atomic_update(struct drm_plane *plane,
132 struct drm_plane_state *old_state)
133{
134 struct intel_plane *intel_plane = to_intel_plane(plane);
135 struct intel_plane_state *intel_state =
136 to_intel_plane_state(plane->state);
137
138 /* Don't disable an already disabled plane */
139 if (!plane->state->fb && !old_state->fb)
140 return;
141
142 intel_plane->commit_plane(plane, intel_state);
143}
144
145const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
146 .prepare_fb = intel_prepare_plane_fb,
147 .cleanup_fb = intel_cleanup_plane_fb,
148 .atomic_check = intel_plane_atomic_check,
149 .atomic_update = intel_plane_atomic_update,
150};
151
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d304cb87493d..73f9a755cc91 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -98,6 +98,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc,
98 const struct intel_crtc_config *pipe_config); 98 const struct intel_crtc_config *pipe_config);
99static void chv_prepare_pll(struct intel_crtc *crtc, 99static void chv_prepare_pll(struct intel_crtc *crtc,
100 const struct intel_crtc_config *pipe_config); 100 const struct intel_crtc_config *pipe_config);
101static void intel_begin_crtc_commit(struct drm_crtc *crtc);
102static void intel_finish_crtc_commit(struct drm_crtc *crtc);
101 103
102static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe) 104static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
103{ 105{
@@ -9794,6 +9796,8 @@ out_hang:
9794static struct drm_crtc_helper_funcs intel_helper_funcs = { 9796static struct drm_crtc_helper_funcs intel_helper_funcs = {
9795 .mode_set_base_atomic = intel_pipe_set_base_atomic, 9797 .mode_set_base_atomic = intel_pipe_set_base_atomic,
9796 .load_lut = intel_crtc_load_lut, 9798 .load_lut = intel_crtc_load_lut,
9799 .atomic_begin = intel_begin_crtc_commit,
9800 .atomic_flush = intel_finish_crtc_commit,
9797}; 9801};
9798 9802
9799/** 9803/**
@@ -11674,7 +11678,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
11674 unsigned frontbuffer_bits = 0; 11678 unsigned frontbuffer_bits = 0;
11675 int ret = 0; 11679 int ret = 0;
11676 11680
11677 if (WARN_ON(fb == plane->fb || !obj)) 11681 if (!obj)
11678 return 0; 11682 return 0;
11679 11683
11680 switch (plane->type) { 11684 switch (plane->type) {
@@ -11741,7 +11745,7 @@ intel_check_primary_plane(struct drm_plane *plane,
11741 struct drm_device *dev = plane->dev; 11745 struct drm_device *dev = plane->dev;
11742 struct drm_i915_private *dev_priv = dev->dev_private; 11746 struct drm_i915_private *dev_priv = dev->dev_private;
11743 struct drm_crtc *crtc = state->base.crtc; 11747 struct drm_crtc *crtc = state->base.crtc;
11744 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 11748 struct intel_crtc *intel_crtc;
11745 struct intel_plane *intel_plane = to_intel_plane(plane); 11749 struct intel_plane *intel_plane = to_intel_plane(plane);
11746 struct drm_framebuffer *fb = state->base.fb; 11750 struct drm_framebuffer *fb = state->base.fb;
11747 struct drm_rect *dest = &state->dst; 11751 struct drm_rect *dest = &state->dst;
@@ -11749,6 +11753,9 @@ intel_check_primary_plane(struct drm_plane *plane,
11749 const struct drm_rect *clip = &state->clip; 11753 const struct drm_rect *clip = &state->clip;
11750 int ret; 11754 int ret;
11751 11755
11756 crtc = crtc ? crtc : plane->crtc;
11757 intel_crtc = to_intel_crtc(crtc);
11758
11752 ret = drm_plane_helper_check_update(plane, crtc, fb, 11759 ret = drm_plane_helper_check_update(plane, crtc, fb,
11753 src, dest, clip, 11760 src, dest, clip,
11754 DRM_PLANE_HELPER_NO_SCALING, 11761 DRM_PLANE_HELPER_NO_SCALING,
@@ -11804,23 +11811,26 @@ intel_commit_primary_plane(struct drm_plane *plane,
11804 struct drm_framebuffer *fb = state->base.fb; 11811 struct drm_framebuffer *fb = state->base.fb;
11805 struct drm_device *dev = plane->dev; 11812 struct drm_device *dev = plane->dev;
11806 struct drm_i915_private *dev_priv = dev->dev_private; 11813 struct drm_i915_private *dev_priv = dev->dev_private;
11807 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 11814 struct intel_crtc *intel_crtc;
11808 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 11815 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
11809 struct intel_plane *intel_plane = to_intel_plane(plane); 11816 struct intel_plane *intel_plane = to_intel_plane(plane);
11810 struct drm_rect *src = &state->src; 11817 struct drm_rect *src = &state->src;
11811 11818
11819 crtc = crtc ? crtc : plane->crtc;
11820 intel_crtc = to_intel_crtc(crtc);
11821
11812 plane->fb = fb; 11822 plane->fb = fb;
11813 crtc->x = src->x1 >> 16; 11823 crtc->x = src->x1 >> 16;
11814 crtc->y = src->y1 >> 16; 11824 crtc->y = src->y1 >> 16;
11815 11825
11816 intel_plane->crtc_x = state->orig_dst.x1; 11826 intel_plane->crtc_x = state->base.crtc_x;
11817 intel_plane->crtc_y = state->orig_dst.y1; 11827 intel_plane->crtc_y = state->base.crtc_y;
11818 intel_plane->crtc_w = drm_rect_width(&state->orig_dst); 11828 intel_plane->crtc_w = state->base.crtc_w;
11819 intel_plane->crtc_h = drm_rect_height(&state->orig_dst); 11829 intel_plane->crtc_h = state->base.crtc_h;
11820 intel_plane->src_x = state->orig_src.x1; 11830 intel_plane->src_x = state->base.src_x;
11821 intel_plane->src_y = state->orig_src.y1; 11831 intel_plane->src_y = state->base.src_y;
11822 intel_plane->src_w = drm_rect_width(&state->orig_src); 11832 intel_plane->src_w = state->base.src_w;
11823 intel_plane->src_h = drm_rect_height(&state->orig_src); 11833 intel_plane->src_h = state->base.src_h;
11824 intel_plane->obj = obj; 11834 intel_plane->obj = obj;
11825 11835
11826 if (intel_crtc->active) { 11836 if (intel_crtc->active) {
@@ -11850,6 +11860,33 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc)
11850 struct drm_device *dev = crtc->dev; 11860 struct drm_device *dev = crtc->dev;
11851 struct drm_i915_private *dev_priv = dev->dev_private; 11861 struct drm_i915_private *dev_priv = dev->dev_private;
11852 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 11862 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
11863 struct intel_plane *intel_plane;
11864 struct drm_plane *p;
11865 unsigned fb_bits = 0;
11866
11867 /* Track fb's for any planes being disabled */
11868 list_for_each_entry(p, &dev->mode_config.plane_list, head) {
11869 intel_plane = to_intel_plane(p);
11870
11871 if (intel_crtc->atomic.disabled_planes &
11872 (1 << drm_plane_index(p))) {
11873 switch (p->type) {
11874 case DRM_PLANE_TYPE_PRIMARY:
11875 fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe);
11876 break;
11877 case DRM_PLANE_TYPE_CURSOR:
11878 fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe);
11879 break;
11880 case DRM_PLANE_TYPE_OVERLAY:
11881 fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe);
11882 break;
11883 }
11884
11885 mutex_lock(&dev->struct_mutex);
11886 i915_gem_track_fb(intel_fb_obj(p->fb), NULL, fb_bits);
11887 mutex_unlock(&dev->struct_mutex);
11888 }
11889 }
11853 11890
11854 if (intel_crtc->atomic.wait_for_flips) 11891 if (intel_crtc->atomic.wait_for_flips)
11855 intel_crtc_wait_for_pending_flips(crtc); 11892 intel_crtc_wait_for_pending_flips(crtc);
@@ -11907,111 +11944,6 @@ static void intel_finish_crtc_commit(struct drm_crtc *crtc)
11907 memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic)); 11944 memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic));
11908} 11945}
11909 11946
11910int
11911intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
11912 struct drm_framebuffer *fb, int crtc_x, int crtc_y,
11913 unsigned int crtc_w, unsigned int crtc_h,
11914 uint32_t src_x, uint32_t src_y,
11915 uint32_t src_w, uint32_t src_h)
11916{
11917 struct drm_device *dev = plane->dev;
11918 struct drm_framebuffer *old_fb = plane->fb;
11919 struct intel_plane_state state = {{ 0 }};
11920 struct intel_plane *intel_plane = to_intel_plane(plane);
11921 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
11922 int ret;
11923
11924 state.base.crtc = crtc ? crtc : plane->crtc;
11925 state.base.fb = fb;
11926
11927 /* sample coordinates in 16.16 fixed point */
11928 state.src.x1 = src_x;
11929 state.src.x2 = src_x + src_w;
11930 state.src.y1 = src_y;
11931 state.src.y2 = src_y + src_h;
11932
11933 /* integer pixels */
11934 state.dst.x1 = crtc_x;
11935 state.dst.x2 = crtc_x + crtc_w;
11936 state.dst.y1 = crtc_y;
11937 state.dst.y2 = crtc_y + crtc_h;
11938
11939 state.clip.x1 = 0;
11940 state.clip.y1 = 0;
11941 state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
11942 state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
11943
11944 state.orig_src = state.src;
11945 state.orig_dst = state.dst;
11946
11947 ret = intel_plane->check_plane(plane, &state);
11948 if (ret)
11949 return ret;
11950
11951 if (fb != old_fb && fb) {
11952 ret = intel_prepare_plane_fb(plane, fb);
11953 if (ret)
11954 return ret;
11955 }
11956
11957 if (!state.base.fb) {
11958 unsigned fb_bits = 0;
11959
11960 switch (plane->type) {
11961 case DRM_PLANE_TYPE_PRIMARY:
11962 fb_bits = INTEL_FRONTBUFFER_PRIMARY(intel_plane->pipe);
11963 break;
11964 case DRM_PLANE_TYPE_CURSOR:
11965 fb_bits = INTEL_FRONTBUFFER_CURSOR(intel_plane->pipe);
11966 break;
11967 case DRM_PLANE_TYPE_OVERLAY:
11968 fb_bits = INTEL_FRONTBUFFER_SPRITE(intel_plane->pipe);
11969 break;
11970 }
11971
11972 /*
11973 * 'prepare' is never called when plane is being disabled, so
11974 * we need to handle frontbuffer tracking here
11975 */
11976 mutex_lock(&dev->struct_mutex);
11977 i915_gem_track_fb(intel_fb_obj(plane->fb), NULL, fb_bits);
11978 mutex_unlock(&dev->struct_mutex);
11979 }
11980
11981 intel_begin_crtc_commit(crtc);
11982 intel_plane->commit_plane(plane, &state);
11983 intel_finish_crtc_commit(crtc);
11984
11985 if (fb != old_fb && old_fb) {
11986 if (intel_crtc->active)
11987 intel_wait_for_vblank(dev, intel_crtc->pipe);
11988 intel_cleanup_plane_fb(plane, old_fb);
11989 }
11990
11991 plane->fb = fb;
11992
11993 return 0;
11994}
11995
11996/**
11997 * intel_disable_plane - disable a plane
11998 * @plane: plane to disable
11999 *
12000 * General disable handler for all plane types.
12001 */
12002int
12003intel_disable_plane(struct drm_plane *plane)
12004{
12005 if (!plane->fb)
12006 return 0;
12007
12008 if (WARN_ON(!plane->crtc))
12009 return -EINVAL;
12010
12011 return plane->funcs->update_plane(plane, plane->crtc, NULL,
12012 0, 0, 0, 0, 0, 0, 0, 0);
12013}
12014
12015/** 11947/**
12016 * intel_plane_destroy - destroy a plane 11948 * intel_plane_destroy - destroy a plane
12017 * @plane: plane to destroy 11949 * @plane: plane to destroy
@@ -12022,15 +11954,19 @@ intel_disable_plane(struct drm_plane *plane)
12022void intel_plane_destroy(struct drm_plane *plane) 11954void intel_plane_destroy(struct drm_plane *plane)
12023{ 11955{
12024 struct intel_plane *intel_plane = to_intel_plane(plane); 11956 struct intel_plane *intel_plane = to_intel_plane(plane);
11957 intel_plane_destroy_state(plane, plane->state);
12025 drm_plane_cleanup(plane); 11958 drm_plane_cleanup(plane);
12026 kfree(intel_plane); 11959 kfree(intel_plane);
12027} 11960}
12028 11961
12029static const struct drm_plane_funcs intel_primary_plane_funcs = { 11962static const struct drm_plane_funcs intel_primary_plane_funcs = {
12030 .update_plane = intel_update_plane, 11963 .update_plane = drm_plane_helper_update,
12031 .disable_plane = intel_disable_plane, 11964 .disable_plane = drm_plane_helper_disable,
12032 .destroy = intel_plane_destroy, 11965 .destroy = intel_plane_destroy,
12033 .set_property = intel_plane_set_property 11966 .set_property = intel_plane_set_property,
11967 .atomic_duplicate_state = intel_plane_duplicate_state,
11968 .atomic_destroy_state = intel_plane_destroy_state,
11969
12034}; 11970};
12035 11971
12036static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, 11972static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
@@ -12044,6 +11980,12 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
12044 if (primary == NULL) 11980 if (primary == NULL)
12045 return NULL; 11981 return NULL;
12046 11982
11983 primary->base.state = intel_plane_duplicate_state(&primary->base);
11984 if (primary->base.state == NULL) {
11985 kfree(primary);
11986 return NULL;
11987 }
11988
12047 primary->can_scale = false; 11989 primary->can_scale = false;
12048 primary->max_downscale = 1; 11990 primary->max_downscale = 1;
12049 primary->pipe = pipe; 11991 primary->pipe = pipe;
@@ -12079,6 +12021,8 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
12079 primary->rotation); 12021 primary->rotation);
12080 } 12022 }
12081 12023
12024 drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
12025
12082 return &primary->base; 12026 return &primary->base;
12083} 12027}
12084 12028
@@ -12087,17 +12031,19 @@ intel_check_cursor_plane(struct drm_plane *plane,
12087 struct intel_plane_state *state) 12031 struct intel_plane_state *state)
12088{ 12032{
12089 struct drm_crtc *crtc = state->base.crtc; 12033 struct drm_crtc *crtc = state->base.crtc;
12090 struct drm_device *dev = crtc->dev; 12034 struct drm_device *dev = plane->dev;
12091 struct drm_framebuffer *fb = state->base.fb; 12035 struct drm_framebuffer *fb = state->base.fb;
12092 struct drm_rect *dest = &state->dst; 12036 struct drm_rect *dest = &state->dst;
12093 struct drm_rect *src = &state->src; 12037 struct drm_rect *src = &state->src;
12094 const struct drm_rect *clip = &state->clip; 12038 const struct drm_rect *clip = &state->clip;
12095 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 12039 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
12096 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 12040 struct intel_crtc *intel_crtc;
12097 int crtc_w, crtc_h;
12098 unsigned stride; 12041 unsigned stride;
12099 int ret; 12042 int ret;
12100 12043
12044 crtc = crtc ? crtc : plane->crtc;
12045 intel_crtc = to_intel_crtc(crtc);
12046
12101 ret = drm_plane_helper_check_update(plane, crtc, fb, 12047 ret = drm_plane_helper_check_update(plane, crtc, fb,
12102 src, dest, clip, 12048 src, dest, clip,
12103 DRM_PLANE_HELPER_NO_SCALING, 12049 DRM_PLANE_HELPER_NO_SCALING,
@@ -12112,15 +12058,14 @@ intel_check_cursor_plane(struct drm_plane *plane,
12112 goto finish; 12058 goto finish;
12113 12059
12114 /* Check for which cursor types we support */ 12060 /* Check for which cursor types we support */
12115 crtc_w = drm_rect_width(&state->orig_dst); 12061 if (!cursor_size_ok(dev, state->base.crtc_w, state->base.crtc_h)) {
12116 crtc_h = drm_rect_height(&state->orig_dst); 12062 DRM_DEBUG("Cursor dimension %dx%d not supported\n",
12117 if (!cursor_size_ok(dev, crtc_w, crtc_h)) { 12063 state->base.crtc_w, state->base.crtc_h);
12118 DRM_DEBUG("Cursor dimension not supported\n");
12119 return -EINVAL; 12064 return -EINVAL;
12120 } 12065 }
12121 12066
12122 stride = roundup_pow_of_two(crtc_w) * 4; 12067 stride = roundup_pow_of_two(state->base.crtc_w) * 4;
12123 if (obj->base.size < stride * crtc_h) { 12068 if (obj->base.size < stride * state->base.crtc_h) {
12124 DRM_DEBUG_KMS("buffer is too small\n"); 12069 DRM_DEBUG_KMS("buffer is too small\n");
12125 return -ENOMEM; 12070 return -ENOMEM;
12126 } 12071 }
@@ -12138,8 +12083,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
12138 12083
12139finish: 12084finish:
12140 if (intel_crtc->active) { 12085 if (intel_crtc->active) {
12141 if (intel_crtc->cursor_width != 12086 if (intel_crtc->cursor_width != state->base.crtc_w)
12142 drm_rect_width(&state->orig_dst))
12143 intel_crtc->atomic.update_wm = true; 12087 intel_crtc->atomic.update_wm = true;
12144 12088
12145 intel_crtc->atomic.fb_bits |= 12089 intel_crtc->atomic.fb_bits |=
@@ -12154,24 +12098,27 @@ intel_commit_cursor_plane(struct drm_plane *plane,
12154 struct intel_plane_state *state) 12098 struct intel_plane_state *state)
12155{ 12099{
12156 struct drm_crtc *crtc = state->base.crtc; 12100 struct drm_crtc *crtc = state->base.crtc;
12157 struct drm_device *dev = crtc->dev; 12101 struct drm_device *dev = plane->dev;
12158 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 12102 struct intel_crtc *intel_crtc;
12159 struct intel_plane *intel_plane = to_intel_plane(plane); 12103 struct intel_plane *intel_plane = to_intel_plane(plane);
12160 struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb); 12104 struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
12161 uint32_t addr; 12105 uint32_t addr;
12162 12106
12107 crtc = crtc ? crtc : plane->crtc;
12108 intel_crtc = to_intel_crtc(crtc);
12109
12163 plane->fb = state->base.fb; 12110 plane->fb = state->base.fb;
12164 crtc->cursor_x = state->orig_dst.x1; 12111 crtc->cursor_x = state->base.crtc_x;
12165 crtc->cursor_y = state->orig_dst.y1; 12112 crtc->cursor_y = state->base.crtc_y;
12166 12113
12167 intel_plane->crtc_x = state->orig_dst.x1; 12114 intel_plane->crtc_x = state->base.crtc_x;
12168 intel_plane->crtc_y = state->orig_dst.y1; 12115 intel_plane->crtc_y = state->base.crtc_y;
12169 intel_plane->crtc_w = drm_rect_width(&state->orig_dst); 12116 intel_plane->crtc_w = state->base.crtc_w;
12170 intel_plane->crtc_h = drm_rect_height(&state->orig_dst); 12117 intel_plane->crtc_h = state->base.crtc_h;
12171 intel_plane->src_x = state->orig_src.x1; 12118 intel_plane->src_x = state->base.src_x;
12172 intel_plane->src_y = state->orig_src.y1; 12119 intel_plane->src_y = state->base.src_y;
12173 intel_plane->src_w = drm_rect_width(&state->orig_src); 12120 intel_plane->src_w = state->base.src_w;
12174 intel_plane->src_h = drm_rect_height(&state->orig_src); 12121 intel_plane->src_h = state->base.src_h;
12175 intel_plane->obj = obj; 12122 intel_plane->obj = obj;
12176 12123
12177 if (intel_crtc->cursor_bo == obj) 12124 if (intel_crtc->cursor_bo == obj)
@@ -12187,18 +12134,20 @@ intel_commit_cursor_plane(struct drm_plane *plane,
12187 intel_crtc->cursor_addr = addr; 12134 intel_crtc->cursor_addr = addr;
12188 intel_crtc->cursor_bo = obj; 12135 intel_crtc->cursor_bo = obj;
12189update: 12136update:
12190 intel_crtc->cursor_width = drm_rect_width(&state->orig_dst); 12137 intel_crtc->cursor_width = state->base.crtc_w;
12191 intel_crtc->cursor_height = drm_rect_height(&state->orig_dst); 12138 intel_crtc->cursor_height = state->base.crtc_h;
12192 12139
12193 if (intel_crtc->active) 12140 if (intel_crtc->active)
12194 intel_crtc_update_cursor(crtc, state->visible); 12141 intel_crtc_update_cursor(crtc, state->visible);
12195} 12142}
12196 12143
12197static const struct drm_plane_funcs intel_cursor_plane_funcs = { 12144static const struct drm_plane_funcs intel_cursor_plane_funcs = {
12198 .update_plane = intel_update_plane, 12145 .update_plane = drm_plane_helper_update,
12199 .disable_plane = intel_disable_plane, 12146 .disable_plane = drm_plane_helper_disable,
12200 .destroy = intel_plane_destroy, 12147 .destroy = intel_plane_destroy,
12201 .set_property = intel_plane_set_property, 12148 .set_property = intel_plane_set_property,
12149 .atomic_duplicate_state = intel_plane_duplicate_state,
12150 .atomic_destroy_state = intel_plane_destroy_state,
12202}; 12151};
12203 12152
12204static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, 12153static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
@@ -12210,6 +12159,12 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
12210 if (cursor == NULL) 12159 if (cursor == NULL)
12211 return NULL; 12160 return NULL;
12212 12161
12162 cursor->base.state = intel_plane_duplicate_state(&cursor->base);
12163 if (cursor->base.state == NULL) {
12164 kfree(cursor);
12165 return NULL;
12166 }
12167
12213 cursor->can_scale = false; 12168 cursor->can_scale = false;
12214 cursor->max_downscale = 1; 12169 cursor->max_downscale = 1;
12215 cursor->pipe = pipe; 12170 cursor->pipe = pipe;
@@ -12236,6 +12191,8 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
12236 cursor->rotation); 12191 cursor->rotation);
12237 } 12192 }
12238 12193
12194 drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
12195
12239 return &cursor->base; 12196 return &cursor->base;
12240} 12197}
12241 12198
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 8022ea570a21..be85ae98811e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -248,8 +248,6 @@ struct intel_plane_state {
248 struct drm_rect src; 248 struct drm_rect src;
249 struct drm_rect dst; 249 struct drm_rect dst;
250 struct drm_rect clip; 250 struct drm_rect clip;
251 struct drm_rect orig_src;
252 struct drm_rect orig_dst;
253 bool visible; 251 bool visible;
254 252
255 /* 253 /*
@@ -437,6 +435,7 @@ struct intel_crtc_atomic_commit {
437 bool disable_fbc; 435 bool disable_fbc;
438 bool pre_disable_primary; 436 bool pre_disable_primary;
439 bool update_wm; 437 bool update_wm;
438 unsigned disabled_planes;
440 439
441 /* Sleepable operations to perform after commit */ 440 /* Sleepable operations to perform after commit */
442 unsigned fb_bits; 441 unsigned fb_bits;
@@ -575,6 +574,7 @@ struct cxsr_latency {
575#define to_intel_encoder(x) container_of(x, struct intel_encoder, base) 574#define to_intel_encoder(x) container_of(x, struct intel_encoder, base)
576#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) 575#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base)
577#define to_intel_plane(x) container_of(x, struct intel_plane, base) 576#define to_intel_plane(x) container_of(x, struct intel_plane, base)
577#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, base)
578#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL) 578#define intel_fb_obj(x) (x ? to_intel_framebuffer(x)->obj : NULL)
579 579
580struct intel_hdmi { 580struct intel_hdmi {
@@ -1255,4 +1255,10 @@ void intel_pre_disable_primary(struct drm_crtc *crtc);
1255/* intel_tv.c */ 1255/* intel_tv.c */
1256void intel_tv_init(struct drm_device *dev); 1256void intel_tv_init(struct drm_device *dev);
1257 1257
1258/* intel_atomic.c */
1259struct drm_plane_state *intel_plane_duplicate_state(struct drm_plane *plane);
1260void intel_plane_destroy_state(struct drm_plane *plane,
1261 struct drm_plane_state *state);
1262extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
1263
1258#endif /* __INTEL_DRV_H__ */ 1264#endif /* __INTEL_DRV_H__ */
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index bb67ae70dafd..c7e70511d25e 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -33,6 +33,7 @@
33#include <drm/drm_crtc.h> 33#include <drm/drm_crtc.h>
34#include <drm/drm_fourcc.h> 34#include <drm/drm_fourcc.h>
35#include <drm/drm_rect.h> 35#include <drm/drm_rect.h>
36#include <drm/drm_plane_helper.h>
36#include "intel_drv.h" 37#include "intel_drv.h"
37#include <drm/i915_drm.h> 38#include <drm/i915_drm.h>
38#include "i915_drv.h" 39#include "i915_drv.h"
@@ -1081,12 +1082,13 @@ intel_check_sprite_plane(struct drm_plane *plane,
1081 uint32_t src_x, src_y, src_w, src_h; 1082 uint32_t src_x, src_y, src_w, src_h;
1082 struct drm_rect *src = &state->src; 1083 struct drm_rect *src = &state->src;
1083 struct drm_rect *dst = &state->dst; 1084 struct drm_rect *dst = &state->dst;
1084 struct drm_rect *orig_src = &state->orig_src;
1085 const struct drm_rect *clip = &state->clip; 1085 const struct drm_rect *clip = &state->clip;
1086 int hscale, vscale; 1086 int hscale, vscale;
1087 int max_scale, min_scale; 1087 int max_scale, min_scale;
1088 int pixel_size; 1088 int pixel_size;
1089 1089
1090 intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
1091
1090 if (!fb) { 1092 if (!fb) {
1091 state->visible = false; 1093 state->visible = false;
1092 goto finish; 1094 goto finish;
@@ -1167,10 +1169,10 @@ intel_check_sprite_plane(struct drm_plane *plane,
1167 intel_plane->rotation); 1169 intel_plane->rotation);
1168 1170
1169 /* sanity check to make sure the src viewport wasn't enlarged */ 1171 /* sanity check to make sure the src viewport wasn't enlarged */
1170 WARN_ON(src->x1 < (int) orig_src->x1 || 1172 WARN_ON(src->x1 < (int) state->base.src_x ||
1171 src->y1 < (int) orig_src->y1 || 1173 src->y1 < (int) state->base.src_y ||
1172 src->x2 > (int) orig_src->x2 || 1174 src->x2 > (int) state->base.src_x + state->base.src_w ||
1173 src->y2 > (int) orig_src->y2); 1175 src->y2 > (int) state->base.src_y + state->base.src_h);
1174 1176
1175 /* 1177 /*
1176 * Hardware doesn't handle subpixel coordinates. 1178 * Hardware doesn't handle subpixel coordinates.
@@ -1267,7 +1269,7 @@ intel_commit_sprite_plane(struct drm_plane *plane,
1267 struct intel_plane_state *state) 1269 struct intel_plane_state *state)
1268{ 1270{
1269 struct drm_crtc *crtc = state->base.crtc; 1271 struct drm_crtc *crtc = state->base.crtc;
1270 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 1272 struct intel_crtc *intel_crtc;
1271 struct intel_plane *intel_plane = to_intel_plane(plane); 1273 struct intel_plane *intel_plane = to_intel_plane(plane);
1272 struct drm_framebuffer *fb = state->base.fb; 1274 struct drm_framebuffer *fb = state->base.fb;
1273 struct drm_i915_gem_object *obj = intel_fb_obj(fb); 1275 struct drm_i915_gem_object *obj = intel_fb_obj(fb);
@@ -1275,14 +1277,19 @@ intel_commit_sprite_plane(struct drm_plane *plane,
1275 unsigned int crtc_w, crtc_h; 1277 unsigned int crtc_w, crtc_h;
1276 uint32_t src_x, src_y, src_w, src_h; 1278 uint32_t src_x, src_y, src_w, src_h;
1277 1279
1278 intel_plane->crtc_x = state->orig_dst.x1; 1280 intel_plane->crtc_x = state->base.crtc_x;
1279 intel_plane->crtc_y = state->orig_dst.y1; 1281 intel_plane->crtc_y = state->base.crtc_y;
1280 intel_plane->crtc_w = drm_rect_width(&state->orig_dst); 1282 intel_plane->crtc_w = state->base.crtc_w;
1281 intel_plane->crtc_h = drm_rect_height(&state->orig_dst); 1283 intel_plane->crtc_h = state->base.crtc_h;
1282 intel_plane->src_x = state->orig_src.x1; 1284 intel_plane->src_x = state->base.src_x;
1283 intel_plane->src_y = state->orig_src.y1; 1285 intel_plane->src_y = state->base.src_y;
1284 intel_plane->src_w = drm_rect_width(&state->orig_src); 1286 intel_plane->src_w = state->base.src_w;
1285 intel_plane->src_h = drm_rect_height(&state->orig_src); 1287 intel_plane->src_h = state->base.src_h;
1288
1289 crtc = crtc ? crtc : plane->crtc;
1290 intel_crtc = to_intel_crtc(crtc);
1291
1292 plane->fb = state->base.fb;
1286 intel_plane->obj = obj; 1293 intel_plane->obj = obj;
1287 1294
1288 if (intel_crtc->active) { 1295 if (intel_crtc->active) {
@@ -1406,10 +1413,12 @@ int intel_plane_restore(struct drm_plane *plane)
1406} 1413}
1407 1414
1408static const struct drm_plane_funcs intel_sprite_plane_funcs = { 1415static const struct drm_plane_funcs intel_sprite_plane_funcs = {
1409 .update_plane = intel_update_plane, 1416 .update_plane = drm_plane_helper_update,
1410 .disable_plane = intel_disable_plane, 1417 .disable_plane = drm_plane_helper_disable,
1411 .destroy = intel_plane_destroy, 1418 .destroy = intel_plane_destroy,
1412 .set_property = intel_plane_set_property, 1419 .set_property = intel_plane_set_property,
1420 .atomic_duplicate_state = intel_plane_duplicate_state,
1421 .atomic_destroy_state = intel_plane_destroy_state,
1413}; 1422};
1414 1423
1415static uint32_t ilk_plane_formats[] = { 1424static uint32_t ilk_plane_formats[] = {
@@ -1471,6 +1480,13 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1471 if (!intel_plane) 1480 if (!intel_plane)
1472 return -ENOMEM; 1481 return -ENOMEM;
1473 1482
1483 intel_plane->base.state =
1484 intel_plane_duplicate_state(&intel_plane->base);
1485 if (intel_plane->base.state == NULL) {
1486 kfree(intel_plane);
1487 return -ENOMEM;
1488 }
1489
1474 switch (INTEL_INFO(dev)->gen) { 1490 switch (INTEL_INFO(dev)->gen) {
1475 case 5: 1491 case 5:
1476 case 6: 1492 case 6:
@@ -1564,6 +1580,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
1564 dev->mode_config.rotation_property, 1580 dev->mode_config.rotation_property,
1565 intel_plane->rotation); 1581 intel_plane->rotation);
1566 1582
1583 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1584
1567 out: 1585 out:
1568 return ret; 1586 return ret;
1569} 1587}