| @@ -1,1126 +1,1126 @@ | | | @@ -1,1126 +1,1126 @@ |
1 | /* $NetBSD: intel_sprite.c,v 1.10 2020/02/14 04:36:12 riastradh Exp $ */ | | 1 | /* $NetBSD: intel_sprite.c,v 1.11 2020/10/31 04:05:42 maya Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright © 2011 Intel Corporation | | 4 | * Copyright © 2011 Intel Corporation |
5 | * | | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), | | 7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation | | 8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | | 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the | | 10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: | | 11 | * Software is furnished to do so, subject to the following conditions: |
12 | * | | 12 | * |
13 | * The above copyright notice and this permission notice (including the next | | 13 | * The above copyright notice and this permission notice (including the next |
14 | * paragraph) shall be included in all copies or substantial portions of the | | 14 | * paragraph) shall be included in all copies or substantial portions of the |
15 | * Software. | | 15 | * Software. |
16 | * | | 16 | * |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | | 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | | 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | | 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | | 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | | 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | | 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | * SOFTWARE. | | 23 | * SOFTWARE. |
24 | * | | 24 | * |
25 | * Authors: | | 25 | * Authors: |
26 | * Jesse Barnes <jbarnes@virtuousgeek.org> | | 26 | * Jesse Barnes <jbarnes@virtuousgeek.org> |
27 | * | | 27 | * |
28 | * New plane/sprite handling. | | 28 | * New plane/sprite handling. |
29 | * | | 29 | * |
30 | * The older chips had a separate interface for programming plane related | | 30 | * The older chips had a separate interface for programming plane related |
31 | * registers; newer ones are much simpler and we can use the new DRM plane | | 31 | * registers; newer ones are much simpler and we can use the new DRM plane |
32 | * support. | | 32 | * support. |
33 | */ | | 33 | */ |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: intel_sprite.c,v 1.10 2020/02/14 04:36:12 riastradh Exp $"); | | 35 | __KERNEL_RCSID(0, "$NetBSD: intel_sprite.c,v 1.11 2020/10/31 04:05:42 maya Exp $"); |
36 | | | 36 | |
37 | #include <drm/drmP.h> | | 37 | #include <drm/drmP.h> |
38 | #include <drm/drm_crtc.h> | | 38 | #include <drm/drm_crtc.h> |
39 | #include <drm/drm_fourcc.h> | | 39 | #include <drm/drm_fourcc.h> |
40 | #include <drm/drm_rect.h> | | 40 | #include <drm/drm_rect.h> |
41 | #include <drm/drm_atomic.h> | | 41 | #include <drm/drm_atomic.h> |
42 | #include <drm/drm_plane_helper.h> | | 42 | #include <drm/drm_plane_helper.h> |
43 | #include "intel_drv.h" | | 43 | #include "intel_drv.h" |
44 | #include <drm/i915_drm.h> | | 44 | #include <drm/i915_drm.h> |
45 | #include "i915_drv.h" | | 45 | #include "i915_drv.h" |
46 | #include "i915_trace.h" | | 46 | #include "i915_trace.h" |
47 | | | 47 | |
48 | static bool | | 48 | static bool |
49 | format_is_yuv(uint32_t format) | | 49 | format_is_yuv(uint32_t format) |
50 | { | | 50 | { |
51 | switch (format) { | | 51 | switch (format) { |
52 | case DRM_FORMAT_YUYV: | | 52 | case DRM_FORMAT_YUYV: |
53 | case DRM_FORMAT_UYVY: | | 53 | case DRM_FORMAT_UYVY: |
54 | case DRM_FORMAT_VYUY: | | 54 | case DRM_FORMAT_VYUY: |
55 | case DRM_FORMAT_YVYU: | | 55 | case DRM_FORMAT_YVYU: |
56 | return true; | | 56 | return true; |
57 | default: | | 57 | default: |
58 | return false; | | 58 | return false; |
59 | } | | 59 | } |
60 | } | | 60 | } |
61 | | | 61 | |
62 | static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, | | 62 | static int usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, |
63 | int usecs) | | 63 | int usecs) |
64 | { | | 64 | { |
65 | /* paranoia */ | | 65 | /* paranoia */ |
66 | if (!adjusted_mode->crtc_htotal) | | 66 | if (!adjusted_mode->crtc_htotal) |
67 | return 1; | | 67 | return 1; |
68 | | | 68 | |
69 | return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, | | 69 | return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock, |
70 | 1000 * adjusted_mode->crtc_htotal); | | 70 | 1000 * adjusted_mode->crtc_htotal); |
71 | } | | 71 | } |
72 | | | 72 | |
73 | /** | | 73 | /** |
74 | * intel_pipe_update_start() - start update of a set of display registers | | 74 | * intel_pipe_update_start() - start update of a set of display registers |
75 | * @crtc: the crtc of which the registers are going to be updated | | 75 | * @crtc: the crtc of which the registers are going to be updated |
76 | * @start_vbl_count: vblank counter return pointer used for error checking | | 76 | * @start_vbl_count: vblank counter return pointer used for error checking |
77 | * | | 77 | * |
78 | * Mark the start of an update to pipe registers that should be updated | | 78 | * Mark the start of an update to pipe registers that should be updated |
79 | * atomically regarding vblank. If the next vblank will happens within | | 79 | * atomically regarding vblank. If the next vblank will happens within |
80 | * the next 100 us, this function waits until the vblank passes. | | 80 | * the next 100 us, this function waits until the vblank passes. |
81 | * | | 81 | * |
82 | * After a successful call to this function, interrupts will be disabled | | 82 | * After a successful call to this function, interrupts will be disabled |
83 | * until a subsequent call to intel_pipe_update_end(). That is done to | | 83 | * until a subsequent call to intel_pipe_update_end(). That is done to |
84 | * avoid random delays. The value written to @start_vbl_count should be | | 84 | * avoid random delays. The value written to @start_vbl_count should be |
85 | * supplied to intel_pipe_update_end() for error checking. | | 85 | * supplied to intel_pipe_update_end() for error checking. |
86 | */ | | 86 | */ |
87 | void intel_pipe_update_start(struct intel_crtc *crtc) | | 87 | void intel_pipe_update_start(struct intel_crtc *crtc) |
88 | { | | 88 | { |
89 | struct drm_device *dev = crtc->base.dev; | | 89 | struct drm_device *dev = crtc->base.dev; |
90 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; | | 90 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
91 | enum pipe pipe = crtc->pipe; | | 91 | enum pipe pipe = crtc->pipe; |
92 | long timeout = msecs_to_jiffies_timeout(1); | | 92 | long timeout = msecs_to_jiffies_timeout(1); |
93 | int scanline, min, max, vblank_start; | | 93 | int scanline, min, max, vblank_start; |
94 | #ifdef __NetBSD__ | | 94 | #ifdef __NetBSD__ |
95 | drm_waitqueue_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); | | 95 | drm_waitqueue_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); |
96 | int ret; | | 96 | int ret; |
97 | #else | | 97 | #else |
98 | wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); | | 98 | wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); |
99 | DEFINE_WAIT(wait); | | 99 | DEFINE_WAIT(wait); |
100 | #endif | | 100 | #endif |
101 | | | 101 | |
102 | vblank_start = adjusted_mode->crtc_vblank_start; | | 102 | vblank_start = adjusted_mode->crtc_vblank_start; |
103 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) | | 103 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) |
104 | vblank_start = DIV_ROUND_UP(vblank_start, 2); | | 104 | vblank_start = DIV_ROUND_UP(vblank_start, 2); |
105 | | | 105 | |
106 | /* FIXME needs to be calibrated sensibly */ | | 106 | /* FIXME needs to be calibrated sensibly */ |
107 | min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); | | 107 | min = vblank_start - usecs_to_scanlines(adjusted_mode, 100); |
108 | max = vblank_start - 1; | | 108 | max = vblank_start - 1; |
109 | | | 109 | |
110 | #ifdef __NetBSD__ | | 110 | #ifdef __NetBSD__ |
111 | spin_lock(&dev->vbl_lock); | | 111 | spin_lock(&dev->vbl_lock); |
112 | #else | | 112 | #else |
113 | local_irq_disable(); | | 113 | local_irq_disable(); |
114 | #endif | | 114 | #endif |
115 | | | 115 | |
116 | if (min <= 0 || max <= 0) | | 116 | if (min <= 0 || max <= 0) |
117 | return; | | 117 | return; |
118 | | | 118 | |
119 | if (WARN_ON(drm_crtc_vblank_get_locked(&crtc->base))) | | 119 | if (WARN_ON(drm_crtc_vblank_get_locked(&crtc->base))) |
120 | return; | | 120 | return; |
121 | | | 121 | |
122 | crtc->debug.min_vbl = min; | | 122 | crtc->debug.min_vbl = min; |
123 | crtc->debug.max_vbl = max; | | 123 | crtc->debug.max_vbl = max; |
124 | trace_i915_pipe_update_start(crtc); | | 124 | trace_i915_pipe_update_start(crtc); |
125 | | | 125 | |
126 | #ifdef __NetBSD__ | | 126 | #ifdef __NetBSD__ |
127 | DRM_SPIN_TIMED_WAIT_UNTIL(ret, wq, &dev->vbl_lock, timeout, | | 127 | DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, wq, &dev->vbl_lock, timeout, |
128 | (scanline = intel_get_crtc_scanline(crtc), | | 128 | (scanline = intel_get_crtc_scanline(crtc), |
129 | scanline < min || scanline > max)); | | 129 | scanline < min || scanline > max)); |
130 | if (ret <= 0) | | 130 | if (ret <= 0) |
131 | DRM_ERROR("Potential atomic update failure on pipe %c: %d\n", | | 131 | DRM_ERROR("Potential atomic update failure on pipe %c: %d\n", |
132 | pipe_name(crtc->pipe), ret ? ret : -EWOULDBLOCK); | | 132 | pipe_name(crtc->pipe), ret ? ret : -EWOULDBLOCK); |
133 | drm_crtc_vblank_put_locked(&crtc->base); | | 133 | drm_crtc_vblank_put_locked(&crtc->base); |
134 | #else | | 134 | #else |
135 | for (;;) { | | 135 | for (;;) { |
136 | /* | | 136 | /* |
137 | * prepare_to_wait() has a memory barrier, which guarantees | | 137 | * prepare_to_wait() has a memory barrier, which guarantees |
138 | * other CPUs can see the task state update by the time we | | 138 | * other CPUs can see the task state update by the time we |
139 | * read the scanline. | | 139 | * read the scanline. |
140 | */ | | 140 | */ |
141 | prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); | | 141 | prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); |
142 | | | 142 | |
143 | scanline = intel_get_crtc_scanline(crtc); | | 143 | scanline = intel_get_crtc_scanline(crtc); |
144 | if (scanline < min || scanline > max) | | 144 | if (scanline < min || scanline > max) |
145 | break; | | 145 | break; |
146 | | | 146 | |
147 | if (timeout <= 0) { | | 147 | if (timeout <= 0) { |
148 | DRM_ERROR("Potential atomic update failure on pipe %c\n", | | 148 | DRM_ERROR("Potential atomic update failure on pipe %c\n", |
149 | pipe_name(crtc->pipe)); | | 149 | pipe_name(crtc->pipe)); |
150 | break; | | 150 | break; |
151 | } | | 151 | } |
152 | | | 152 | |
153 | local_irq_enable(); | | 153 | local_irq_enable(); |
154 | | | 154 | |
155 | timeout = schedule_timeout(timeout); | | 155 | timeout = schedule_timeout(timeout); |
156 | | | 156 | |
157 | local_irq_disable(); | | 157 | local_irq_disable(); |
158 | } | | 158 | } |
159 | | | 159 | |
160 | finish_wait(wq, &wait); | | 160 | finish_wait(wq, &wait); |
161 | | | 161 | |
162 | drm_crtc_vblank_put(&crtc->base); | | 162 | drm_crtc_vblank_put(&crtc->base); |
163 | #endif | | 163 | #endif |
164 | | | 164 | |
165 | crtc->debug.scanline_start = scanline; | | 165 | crtc->debug.scanline_start = scanline; |
166 | crtc->debug.start_vbl_time = ktime_get(); | | 166 | crtc->debug.start_vbl_time = ktime_get(); |
167 | crtc->debug.start_vbl_count = | | 167 | crtc->debug.start_vbl_count = |
168 | dev->driver->get_vblank_counter(dev, pipe); | | 168 | dev->driver->get_vblank_counter(dev, pipe); |
169 | | | 169 | |
170 | trace_i915_pipe_update_vblank_evaded(crtc); | | 170 | trace_i915_pipe_update_vblank_evaded(crtc); |
171 | } | | 171 | } |
172 | | | 172 | |
173 | /** | | 173 | /** |
174 | * intel_pipe_update_end() - end update of a set of display registers | | 174 | * intel_pipe_update_end() - end update of a set of display registers |
175 | * @crtc: the crtc of which the registers were updated | | 175 | * @crtc: the crtc of which the registers were updated |
176 | * @start_vbl_count: start vblank counter (used for error checking) | | 176 | * @start_vbl_count: start vblank counter (used for error checking) |
177 | * | | 177 | * |
178 | * Mark the end of an update started with intel_pipe_update_start(). This | | 178 | * Mark the end of an update started with intel_pipe_update_start(). This |
179 | * re-enables interrupts and verifies the update was actually completed | | 179 | * re-enables interrupts and verifies the update was actually completed |
180 | * before a vblank using the value of @start_vbl_count. | | 180 | * before a vblank using the value of @start_vbl_count. |
181 | */ | | 181 | */ |
182 | void intel_pipe_update_end(struct intel_crtc *crtc) | | 182 | void intel_pipe_update_end(struct intel_crtc *crtc) |
183 | { | | 183 | { |
184 | struct drm_device *dev = crtc->base.dev; | | 184 | struct drm_device *dev = crtc->base.dev; |
185 | enum pipe pipe = crtc->pipe; | | 185 | enum pipe pipe = crtc->pipe; |
186 | int scanline_end = intel_get_crtc_scanline(crtc); | | 186 | int scanline_end = intel_get_crtc_scanline(crtc); |
187 | u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); | | 187 | u32 end_vbl_count = dev->driver->get_vblank_counter(dev, pipe); |
188 | ktime_t end_vbl_time = ktime_get(); | | 188 | ktime_t end_vbl_time = ktime_get(); |
189 | | | 189 | |
190 | trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); | | 190 | trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end); |
191 | | | 191 | |
192 | #ifdef __NetBSD__ | | 192 | #ifdef __NetBSD__ |
193 | spin_unlock(&dev->vbl_lock); | | 193 | spin_unlock(&dev->vbl_lock); |
194 | #else | | 194 | #else |
195 | local_irq_enable(); | | 195 | local_irq_enable(); |
196 | #endif | | 196 | #endif |
197 | | | 197 | |
198 | if (crtc->debug.start_vbl_count && | | 198 | if (crtc->debug.start_vbl_count && |
199 | crtc->debug.start_vbl_count != end_vbl_count) { | | 199 | crtc->debug.start_vbl_count != end_vbl_count) { |
200 | DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %"PRIdMAX" us, min %d, max %d, scanline start %d, end %d\n", | | 200 | DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %"PRIdMAX" us, min %d, max %d, scanline start %d, end %d\n", |
201 | pipe_name(pipe), crtc->debug.start_vbl_count, | | 201 | pipe_name(pipe), crtc->debug.start_vbl_count, |
202 | end_vbl_count, | | 202 | end_vbl_count, |
203 | ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), | | 203 | ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time), |
204 | crtc->debug.min_vbl, crtc->debug.max_vbl, | | 204 | crtc->debug.min_vbl, crtc->debug.max_vbl, |
205 | crtc->debug.scanline_start, scanline_end); | | 205 | crtc->debug.scanline_start, scanline_end); |
206 | } | | 206 | } |
207 | } | | 207 | } |
208 | | | 208 | |
209 | static void | | 209 | static void |
210 | skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, | | 210 | skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc, |
211 | struct drm_framebuffer *fb, | | 211 | struct drm_framebuffer *fb, |
212 | int crtc_x, int crtc_y, | | 212 | int crtc_x, int crtc_y, |
213 | unsigned int crtc_w, unsigned int crtc_h, | | 213 | unsigned int crtc_w, unsigned int crtc_h, |
214 | uint32_t x, uint32_t y, | | 214 | uint32_t x, uint32_t y, |
215 | uint32_t src_w, uint32_t src_h) | | 215 | uint32_t src_w, uint32_t src_h) |
216 | { | | 216 | { |
217 | struct drm_device *dev = drm_plane->dev; | | 217 | struct drm_device *dev = drm_plane->dev; |
218 | struct drm_i915_private *dev_priv = dev->dev_private; | | 218 | struct drm_i915_private *dev_priv = dev->dev_private; |
219 | struct intel_plane *intel_plane = to_intel_plane(drm_plane); | | 219 | struct intel_plane *intel_plane = to_intel_plane(drm_plane); |
220 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | | 220 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
221 | const int pipe = intel_plane->pipe; | | 221 | const int pipe = intel_plane->pipe; |
222 | const int plane = intel_plane->plane + 1; | | 222 | const int plane = intel_plane->plane + 1; |
223 | u32 plane_ctl, stride_div, stride; | | 223 | u32 plane_ctl, stride_div, stride; |
224 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | | 224 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
225 | const struct drm_intel_sprite_colorkey *key = | | 225 | const struct drm_intel_sprite_colorkey *key = |
226 | &to_intel_plane_state(drm_plane->state)->ckey; | | 226 | &to_intel_plane_state(drm_plane->state)->ckey; |
227 | u32 surf_addr; | | 227 | u32 surf_addr; |
228 | u32 tile_height, plane_offset, plane_size; | | 228 | u32 tile_height, plane_offset, plane_size; |
229 | unsigned int rotation; | | 229 | unsigned int rotation; |
230 | int x_offset, y_offset; | | 230 | int x_offset, y_offset; |
231 | struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config; | | 231 | struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config; |
232 | int scaler_id; | | 232 | int scaler_id; |
233 | | | 233 | |
234 | plane_ctl = PLANE_CTL_ENABLE | | | 234 | plane_ctl = PLANE_CTL_ENABLE | |
235 | PLANE_CTL_PIPE_GAMMA_ENABLE | | | 235 | PLANE_CTL_PIPE_GAMMA_ENABLE | |
236 | PLANE_CTL_PIPE_CSC_ENABLE; | | 236 | PLANE_CTL_PIPE_CSC_ENABLE; |
237 | | | 237 | |
238 | plane_ctl |= skl_plane_ctl_format(fb->pixel_format); | | 238 | plane_ctl |= skl_plane_ctl_format(fb->pixel_format); |
239 | plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); | | 239 | plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]); |
240 | | | 240 | |
241 | rotation = drm_plane->state->rotation; | | 241 | rotation = drm_plane->state->rotation; |
242 | plane_ctl |= skl_plane_ctl_rotation(rotation); | | 242 | plane_ctl |= skl_plane_ctl_rotation(rotation); |
243 | | | 243 | |
244 | intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h, | | 244 | intel_update_sprite_watermarks(drm_plane, crtc, src_w, src_h, |
245 | pixel_size, true, | | 245 | pixel_size, true, |
246 | src_w != crtc_w || src_h != crtc_h); | | 246 | src_w != crtc_w || src_h != crtc_h); |
247 | | | 247 | |
248 | stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], | | 248 | stride_div = intel_fb_stride_alignment(dev, fb->modifier[0], |
249 | fb->pixel_format); | | 249 | fb->pixel_format); |
250 | | | 250 | |
251 | scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id; | | 251 | scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id; |
252 | | | 252 | |
253 | /* Sizes are 0 based */ | | 253 | /* Sizes are 0 based */ |
254 | src_w--; | | 254 | src_w--; |
255 | src_h--; | | 255 | src_h--; |
256 | crtc_w--; | | 256 | crtc_w--; |
257 | crtc_h--; | | 257 | crtc_h--; |
258 | | | 258 | |
259 | if (key->flags) { | | 259 | if (key->flags) { |
260 | I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); | | 260 | I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); |
261 | I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value); | | 261 | I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value); |
262 | I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask); | | 262 | I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask); |
263 | } | | 263 | } |
264 | | | 264 | |
265 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | | 265 | if (key->flags & I915_SET_COLORKEY_DESTINATION) |
266 | plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; | | 266 | plane_ctl |= PLANE_CTL_KEY_ENABLE_DESTINATION; |
267 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | | 267 | else if (key->flags & I915_SET_COLORKEY_SOURCE) |
268 | plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; | | 268 | plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE; |
269 | | | 269 | |
270 | surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); | | 270 | surf_addr = intel_plane_obj_offset(intel_plane, obj, 0); |
271 | | | 271 | |
272 | if (intel_rotation_90_or_270(rotation)) { | | 272 | if (intel_rotation_90_or_270(rotation)) { |
273 | /* stride: Surface height in tiles */ | | 273 | /* stride: Surface height in tiles */ |
274 | tile_height = intel_tile_height(dev, fb->pixel_format, | | 274 | tile_height = intel_tile_height(dev, fb->pixel_format, |
275 | fb->modifier[0], 0); | | 275 | fb->modifier[0], 0); |
276 | stride = DIV_ROUND_UP(fb->height, tile_height); | | 276 | stride = DIV_ROUND_UP(fb->height, tile_height); |
277 | plane_size = (src_w << 16) | src_h; | | 277 | plane_size = (src_w << 16) | src_h; |
278 | x_offset = stride * tile_height - y - (src_h + 1); | | 278 | x_offset = stride * tile_height - y - (src_h + 1); |
279 | y_offset = x; | | 279 | y_offset = x; |
280 | } else { | | 280 | } else { |
281 | stride = fb->pitches[0] / stride_div; | | 281 | stride = fb->pitches[0] / stride_div; |
282 | plane_size = (src_h << 16) | src_w; | | 282 | plane_size = (src_h << 16) | src_w; |
283 | x_offset = x; | | 283 | x_offset = x; |
284 | y_offset = y; | | 284 | y_offset = y; |
285 | } | | 285 | } |
286 | plane_offset = y_offset << 16 | x_offset; | | 286 | plane_offset = y_offset << 16 | x_offset; |
287 | | | 287 | |
288 | I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset); | | 288 | I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset); |
289 | I915_WRITE(PLANE_STRIDE(pipe, plane), stride); | | 289 | I915_WRITE(PLANE_STRIDE(pipe, plane), stride); |
290 | I915_WRITE(PLANE_SIZE(pipe, plane), plane_size); | | 290 | I915_WRITE(PLANE_SIZE(pipe, plane), plane_size); |
291 | | | 291 | |
292 | /* program plane scaler */ | | 292 | /* program plane scaler */ |
293 | if (scaler_id >= 0) { | | 293 | if (scaler_id >= 0) { |
294 | uint32_t ps_ctrl = 0; | | 294 | uint32_t ps_ctrl = 0; |
295 | | | 295 | |
296 | DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane, | | 296 | DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane, |
297 | PS_PLANE_SEL(plane)); | | 297 | PS_PLANE_SEL(plane)); |
298 | ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | | | 298 | ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) | |
299 | crtc_state->scaler_state.scalers[scaler_id].mode; | | 299 | crtc_state->scaler_state.scalers[scaler_id].mode; |
300 | I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl); | | 300 | I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl); |
301 | I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0); | | 301 | I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0); |
302 | I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); | | 302 | I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); |
303 | I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), | | 303 | I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), |
304 | ((crtc_w + 1) << 16)|(crtc_h + 1)); | | 304 | ((crtc_w + 1) << 16)|(crtc_h + 1)); |
305 | | | 305 | |
306 | I915_WRITE(PLANE_POS(pipe, plane), 0); | | 306 | I915_WRITE(PLANE_POS(pipe, plane), 0); |
307 | } else { | | 307 | } else { |
308 | I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x); | | 308 | I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x); |
309 | } | | 309 | } |
310 | | | 310 | |
311 | I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); | | 311 | I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl); |
312 | I915_WRITE(PLANE_SURF(pipe, plane), surf_addr); | | 312 | I915_WRITE(PLANE_SURF(pipe, plane), surf_addr); |
313 | POSTING_READ(PLANE_SURF(pipe, plane)); | | 313 | POSTING_READ(PLANE_SURF(pipe, plane)); |
314 | } | | 314 | } |
315 | | | 315 | |
316 | static void | | 316 | static void |
317 | skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | | 317 | skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) |
318 | { | | 318 | { |
319 | struct drm_device *dev = dplane->dev; | | 319 | struct drm_device *dev = dplane->dev; |
320 | struct drm_i915_private *dev_priv = dev->dev_private; | | 320 | struct drm_i915_private *dev_priv = dev->dev_private; |
321 | struct intel_plane *intel_plane = to_intel_plane(dplane); | | 321 | struct intel_plane *intel_plane = to_intel_plane(dplane); |
322 | const int pipe = intel_plane->pipe; | | 322 | const int pipe = intel_plane->pipe; |
323 | const int plane = intel_plane->plane + 1; | | 323 | const int plane = intel_plane->plane + 1; |
324 | | | 324 | |
325 | I915_WRITE(PLANE_CTL(pipe, plane), 0); | | 325 | I915_WRITE(PLANE_CTL(pipe, plane), 0); |
326 | | | 326 | |
327 | I915_WRITE(PLANE_SURF(pipe, plane), 0); | | 327 | I915_WRITE(PLANE_SURF(pipe, plane), 0); |
328 | POSTING_READ(PLANE_SURF(pipe, plane)); | | 328 | POSTING_READ(PLANE_SURF(pipe, plane)); |
329 | | | 329 | |
330 | intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false); | | 330 | intel_update_sprite_watermarks(dplane, crtc, 0, 0, 0, false, false); |
331 | } | | 331 | } |
332 | | | 332 | |
333 | static void | | 333 | static void |
334 | chv_update_csc(struct intel_plane *intel_plane, uint32_t format) | | 334 | chv_update_csc(struct intel_plane *intel_plane, uint32_t format) |
335 | { | | 335 | { |
336 | struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private; | | 336 | struct drm_i915_private *dev_priv = intel_plane->base.dev->dev_private; |
337 | int plane = intel_plane->plane; | | 337 | int plane = intel_plane->plane; |
338 | | | 338 | |
339 | /* Seems RGB data bypasses the CSC always */ | | 339 | /* Seems RGB data bypasses the CSC always */ |
340 | if (!format_is_yuv(format)) | | 340 | if (!format_is_yuv(format)) |
341 | return; | | 341 | return; |
342 | | | 342 | |
343 | /* | | 343 | /* |
344 | * BT.601 limited range YCbCr -> full range RGB | | 344 | * BT.601 limited range YCbCr -> full range RGB |
345 | * | | 345 | * |
346 | * |r| | 6537 4769 0| |cr | | | 346 | * |r| | 6537 4769 0| |cr | |
347 | * |g| = |-3330 4769 -1605| x |y-64| | | 347 | * |g| = |-3330 4769 -1605| x |y-64| |
348 | * |b| | 0 4769 8263| |cb | | | 348 | * |b| | 0 4769 8263| |cb | |
349 | * | | 349 | * |
350 | * Cb and Cr apparently come in as signed already, so no | | 350 | * Cb and Cr apparently come in as signed already, so no |
351 | * need for any offset. For Y we need to remove the offset. | | 351 | * need for any offset. For Y we need to remove the offset. |
352 | */ | | 352 | */ |
353 | I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); | | 353 | I915_WRITE(SPCSCYGOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(-64)); |
354 | I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | | 354 | I915_WRITE(SPCSCCBOFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); |
355 | I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); | | 355 | I915_WRITE(SPCSCCROFF(plane), SPCSC_OOFF(0) | SPCSC_IOFF(0)); |
356 | | | 356 | |
357 | I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537)); | | 357 | I915_WRITE(SPCSCC01(plane), SPCSC_C1(4769) | SPCSC_C0(6537)); |
358 | I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0)); | | 358 | I915_WRITE(SPCSCC23(plane), SPCSC_C1(-3330) | SPCSC_C0(0)); |
359 | I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769)); | | 359 | I915_WRITE(SPCSCC45(plane), SPCSC_C1(-1605) | SPCSC_C0(4769)); |
360 | I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0)); | | 360 | I915_WRITE(SPCSCC67(plane), SPCSC_C1(4769) | SPCSC_C0(0)); |
361 | I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263)); | | 361 | I915_WRITE(SPCSCC8(plane), SPCSC_C0(8263)); |
362 | | | 362 | |
363 | I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64)); | | 363 | I915_WRITE(SPCSCYGICLAMP(plane), SPCSC_IMAX(940) | SPCSC_IMIN(64)); |
364 | I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | | 364 | I915_WRITE(SPCSCCBICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); |
365 | I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); | | 365 | I915_WRITE(SPCSCCRICLAMP(plane), SPCSC_IMAX(448) | SPCSC_IMIN(-448)); |
366 | | | 366 | |
367 | I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | | 367 | I915_WRITE(SPCSCYGOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
368 | I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | | 368 | I915_WRITE(SPCSCCBOCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
369 | I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); | | 369 | I915_WRITE(SPCSCCROCLAMP(plane), SPCSC_OMAX(1023) | SPCSC_OMIN(0)); |
370 | } | | 370 | } |
371 | | | 371 | |
372 | static void | | 372 | static void |
373 | vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, | | 373 | vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc, |
374 | struct drm_framebuffer *fb, | | 374 | struct drm_framebuffer *fb, |
375 | int crtc_x, int crtc_y, | | 375 | int crtc_x, int crtc_y, |
376 | unsigned int crtc_w, unsigned int crtc_h, | | 376 | unsigned int crtc_w, unsigned int crtc_h, |
377 | uint32_t x, uint32_t y, | | 377 | uint32_t x, uint32_t y, |
378 | uint32_t src_w, uint32_t src_h) | | 378 | uint32_t src_w, uint32_t src_h) |
379 | { | | 379 | { |
380 | struct drm_device *dev = dplane->dev; | | 380 | struct drm_device *dev = dplane->dev; |
381 | struct drm_i915_private *dev_priv = dev->dev_private; | | 381 | struct drm_i915_private *dev_priv = dev->dev_private; |
382 | struct intel_plane *intel_plane = to_intel_plane(dplane); | | 382 | struct intel_plane *intel_plane = to_intel_plane(dplane); |
383 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | | 383 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
384 | int pipe = intel_plane->pipe; | | 384 | int pipe = intel_plane->pipe; |
385 | int plane = intel_plane->plane; | | 385 | int plane = intel_plane->plane; |
386 | u32 sprctl; | | 386 | u32 sprctl; |
387 | unsigned long sprsurf_offset, linear_offset; | | 387 | unsigned long sprsurf_offset, linear_offset; |
388 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | | 388 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
389 | const struct drm_intel_sprite_colorkey *key = | | 389 | const struct drm_intel_sprite_colorkey *key = |
390 | &to_intel_plane_state(dplane->state)->ckey; | | 390 | &to_intel_plane_state(dplane->state)->ckey; |
391 | | | 391 | |
392 | sprctl = SP_ENABLE; | | 392 | sprctl = SP_ENABLE; |
393 | | | 393 | |
394 | switch (fb->pixel_format) { | | 394 | switch (fb->pixel_format) { |
395 | case DRM_FORMAT_YUYV: | | 395 | case DRM_FORMAT_YUYV: |
396 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; | | 396 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV; |
397 | break; | | 397 | break; |
398 | case DRM_FORMAT_YVYU: | | 398 | case DRM_FORMAT_YVYU: |
399 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; | | 399 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU; |
400 | break; | | 400 | break; |
401 | case DRM_FORMAT_UYVY: | | 401 | case DRM_FORMAT_UYVY: |
402 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; | | 402 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY; |
403 | break; | | 403 | break; |
404 | case DRM_FORMAT_VYUY: | | 404 | case DRM_FORMAT_VYUY: |
405 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; | | 405 | sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY; |
406 | break; | | 406 | break; |
407 | case DRM_FORMAT_RGB565: | | 407 | case DRM_FORMAT_RGB565: |
408 | sprctl |= SP_FORMAT_BGR565; | | 408 | sprctl |= SP_FORMAT_BGR565; |
409 | break; | | 409 | break; |
410 | case DRM_FORMAT_XRGB8888: | | 410 | case DRM_FORMAT_XRGB8888: |
411 | sprctl |= SP_FORMAT_BGRX8888; | | 411 | sprctl |= SP_FORMAT_BGRX8888; |
412 | break; | | 412 | break; |
413 | case DRM_FORMAT_ARGB8888: | | 413 | case DRM_FORMAT_ARGB8888: |
414 | sprctl |= SP_FORMAT_BGRA8888; | | 414 | sprctl |= SP_FORMAT_BGRA8888; |
415 | break; | | 415 | break; |
416 | case DRM_FORMAT_XBGR2101010: | | 416 | case DRM_FORMAT_XBGR2101010: |
417 | sprctl |= SP_FORMAT_RGBX1010102; | | 417 | sprctl |= SP_FORMAT_RGBX1010102; |
418 | break; | | 418 | break; |
419 | case DRM_FORMAT_ABGR2101010: | | 419 | case DRM_FORMAT_ABGR2101010: |
420 | sprctl |= SP_FORMAT_RGBA1010102; | | 420 | sprctl |= SP_FORMAT_RGBA1010102; |
421 | break; | | 421 | break; |
422 | case DRM_FORMAT_XBGR8888: | | 422 | case DRM_FORMAT_XBGR8888: |
423 | sprctl |= SP_FORMAT_RGBX8888; | | 423 | sprctl |= SP_FORMAT_RGBX8888; |
424 | break; | | 424 | break; |
425 | case DRM_FORMAT_ABGR8888: | | 425 | case DRM_FORMAT_ABGR8888: |
426 | sprctl |= SP_FORMAT_RGBA8888; | | 426 | sprctl |= SP_FORMAT_RGBA8888; |
427 | break; | | 427 | break; |
428 | default: | | 428 | default: |
429 | /* | | 429 | /* |
430 | * If we get here one of the upper layers failed to filter | | 430 | * If we get here one of the upper layers failed to filter |
431 | * out the unsupported plane formats | | 431 | * out the unsupported plane formats |
432 | */ | | 432 | */ |
433 | BUG(); | | 433 | BUG(); |
434 | break; | | 434 | break; |
435 | } | | 435 | } |
436 | | | 436 | |
437 | /* | | 437 | /* |
438 | * Enable gamma to match primary/cursor plane behaviour. | | 438 | * Enable gamma to match primary/cursor plane behaviour. |
439 | * FIXME should be user controllable via propertiesa. | | 439 | * FIXME should be user controllable via propertiesa. |
440 | */ | | 440 | */ |
441 | sprctl |= SP_GAMMA_ENABLE; | | 441 | sprctl |= SP_GAMMA_ENABLE; |
442 | | | 442 | |
443 | if (obj->tiling_mode != I915_TILING_NONE) | | 443 | if (obj->tiling_mode != I915_TILING_NONE) |
444 | sprctl |= SP_TILED; | | 444 | sprctl |= SP_TILED; |
445 | | | 445 | |
446 | /* Sizes are 0 based */ | | 446 | /* Sizes are 0 based */ |
447 | src_w--; | | 447 | src_w--; |
448 | src_h--; | | 448 | src_h--; |
449 | crtc_w--; | | 449 | crtc_w--; |
450 | crtc_h--; | | 450 | crtc_h--; |
451 | | | 451 | |
452 | linear_offset = y * fb->pitches[0] + x * pixel_size; | | 452 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
453 | sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, | | 453 | sprsurf_offset = intel_gen4_compute_page_offset(dev_priv, |
454 | &x, &y, | | 454 | &x, &y, |
455 | obj->tiling_mode, | | 455 | obj->tiling_mode, |
456 | pixel_size, | | 456 | pixel_size, |
457 | fb->pitches[0]); | | 457 | fb->pitches[0]); |
458 | linear_offset -= sprsurf_offset; | | 458 | linear_offset -= sprsurf_offset; |
459 | | | 459 | |
460 | if (dplane->state->rotation == BIT(DRM_ROTATE_180)) { | | 460 | if (dplane->state->rotation == BIT(DRM_ROTATE_180)) { |
461 | sprctl |= SP_ROTATE_180; | | 461 | sprctl |= SP_ROTATE_180; |
462 | | | 462 | |
463 | x += src_w; | | 463 | x += src_w; |
464 | y += src_h; | | 464 | y += src_h; |
465 | linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; | | 465 | linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; |
466 | } | | 466 | } |
467 | | | 467 | |
468 | if (key->flags) { | | 468 | if (key->flags) { |
469 | I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); | | 469 | I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value); |
470 | I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); | | 470 | I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value); |
471 | I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); | | 471 | I915_WRITE(SPKEYMSK(pipe, plane), key->channel_mask); |
472 | } | | 472 | } |
473 | | | 473 | |
474 | if (key->flags & I915_SET_COLORKEY_SOURCE) | | 474 | if (key->flags & I915_SET_COLORKEY_SOURCE) |
475 | sprctl |= SP_SOURCE_KEY; | | 475 | sprctl |= SP_SOURCE_KEY; |
476 | | | 476 | |
477 | if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) | | 477 | if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) |
478 | chv_update_csc(intel_plane, fb->pixel_format); | | 478 | chv_update_csc(intel_plane, fb->pixel_format); |
479 | | | 479 | |
480 | I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); | | 480 | I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); |
481 | I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); | | 481 | I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x); |
482 | | | 482 | |
483 | if (obj->tiling_mode != I915_TILING_NONE) | | 483 | if (obj->tiling_mode != I915_TILING_NONE) |
484 | I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); | | 484 | I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x); |
485 | else | | 485 | else |
486 | I915_WRITE(SPLINOFF(pipe, plane), linear_offset); | | 486 | I915_WRITE(SPLINOFF(pipe, plane), linear_offset); |
487 | | | 487 | |
488 | I915_WRITE(SPCONSTALPHA(pipe, plane), 0); | | 488 | I915_WRITE(SPCONSTALPHA(pipe, plane), 0); |
489 | | | 489 | |
490 | I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); | | 490 | I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w); |
491 | I915_WRITE(SPCNTR(pipe, plane), sprctl); | | 491 | I915_WRITE(SPCNTR(pipe, plane), sprctl); |
492 | I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + | | 492 | I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) + |
493 | sprsurf_offset); | | 493 | sprsurf_offset); |
494 | POSTING_READ(SPSURF(pipe, plane)); | | 494 | POSTING_READ(SPSURF(pipe, plane)); |
495 | } | | 495 | } |
496 | | | 496 | |
497 | static void | | 497 | static void |
498 | vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | | 498 | vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) |
499 | { | | 499 | { |
500 | struct drm_device *dev = dplane->dev; | | 500 | struct drm_device *dev = dplane->dev; |
501 | struct drm_i915_private *dev_priv = dev->dev_private; | | 501 | struct drm_i915_private *dev_priv = dev->dev_private; |
502 | struct intel_plane *intel_plane = to_intel_plane(dplane); | | 502 | struct intel_plane *intel_plane = to_intel_plane(dplane); |
503 | int pipe = intel_plane->pipe; | | 503 | int pipe = intel_plane->pipe; |
504 | int plane = intel_plane->plane; | | 504 | int plane = intel_plane->plane; |
505 | | | 505 | |
506 | I915_WRITE(SPCNTR(pipe, plane), 0); | | 506 | I915_WRITE(SPCNTR(pipe, plane), 0); |
507 | | | 507 | |
508 | I915_WRITE(SPSURF(pipe, plane), 0); | | 508 | I915_WRITE(SPSURF(pipe, plane), 0); |
509 | POSTING_READ(SPSURF(pipe, plane)); | | 509 | POSTING_READ(SPSURF(pipe, plane)); |
510 | } | | 510 | } |
511 | | | 511 | |
512 | static void | | 512 | static void |
513 | ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | | 513 | ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
514 | struct drm_framebuffer *fb, | | 514 | struct drm_framebuffer *fb, |
515 | int crtc_x, int crtc_y, | | 515 | int crtc_x, int crtc_y, |
516 | unsigned int crtc_w, unsigned int crtc_h, | | 516 | unsigned int crtc_w, unsigned int crtc_h, |
517 | uint32_t x, uint32_t y, | | 517 | uint32_t x, uint32_t y, |
518 | uint32_t src_w, uint32_t src_h) | | 518 | uint32_t src_w, uint32_t src_h) |
519 | { | | 519 | { |
520 | struct drm_device *dev = plane->dev; | | 520 | struct drm_device *dev = plane->dev; |
521 | struct drm_i915_private *dev_priv = dev->dev_private; | | 521 | struct drm_i915_private *dev_priv = dev->dev_private; |
522 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 522 | struct intel_plane *intel_plane = to_intel_plane(plane); |
523 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | | 523 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
524 | enum pipe pipe = intel_plane->pipe; | | 524 | enum pipe pipe = intel_plane->pipe; |
525 | u32 sprctl, sprscale = 0; | | 525 | u32 sprctl, sprscale = 0; |
526 | unsigned long sprsurf_offset, linear_offset; | | 526 | unsigned long sprsurf_offset, linear_offset; |
527 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | | 527 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
528 | const struct drm_intel_sprite_colorkey *key = | | 528 | const struct drm_intel_sprite_colorkey *key = |
529 | &to_intel_plane_state(plane->state)->ckey; | | 529 | &to_intel_plane_state(plane->state)->ckey; |
530 | | | 530 | |
531 | sprctl = SPRITE_ENABLE; | | 531 | sprctl = SPRITE_ENABLE; |
532 | | | 532 | |
533 | switch (fb->pixel_format) { | | 533 | switch (fb->pixel_format) { |
534 | case DRM_FORMAT_XBGR8888: | | 534 | case DRM_FORMAT_XBGR8888: |
535 | sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; | | 535 | sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX; |
536 | break; | | 536 | break; |
537 | case DRM_FORMAT_XRGB8888: | | 537 | case DRM_FORMAT_XRGB8888: |
538 | sprctl |= SPRITE_FORMAT_RGBX888; | | 538 | sprctl |= SPRITE_FORMAT_RGBX888; |
539 | break; | | 539 | break; |
540 | case DRM_FORMAT_YUYV: | | 540 | case DRM_FORMAT_YUYV: |
541 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; | | 541 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV; |
542 | break; | | 542 | break; |
543 | case DRM_FORMAT_YVYU: | | 543 | case DRM_FORMAT_YVYU: |
544 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; | | 544 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU; |
545 | break; | | 545 | break; |
546 | case DRM_FORMAT_UYVY: | | 546 | case DRM_FORMAT_UYVY: |
547 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; | | 547 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY; |
548 | break; | | 548 | break; |
549 | case DRM_FORMAT_VYUY: | | 549 | case DRM_FORMAT_VYUY: |
550 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; | | 550 | sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY; |
551 | break; | | 551 | break; |
552 | default: | | 552 | default: |
553 | BUG(); | | 553 | BUG(); |
554 | } | | 554 | } |
555 | | | 555 | |
556 | /* | | 556 | /* |
557 | * Enable gamma to match primary/cursor plane behaviour. | | 557 | * Enable gamma to match primary/cursor plane behaviour. |
558 | * FIXME should be user controllable via propertiesa. | | 558 | * FIXME should be user controllable via propertiesa. |
559 | */ | | 559 | */ |
560 | sprctl |= SPRITE_GAMMA_ENABLE; | | 560 | sprctl |= SPRITE_GAMMA_ENABLE; |
561 | | | 561 | |
562 | if (obj->tiling_mode != I915_TILING_NONE) | | 562 | if (obj->tiling_mode != I915_TILING_NONE) |
563 | sprctl |= SPRITE_TILED; | | 563 | sprctl |= SPRITE_TILED; |
564 | | | 564 | |
565 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | | 565 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
566 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; | | 566 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; |
567 | else | | 567 | else |
568 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | | 568 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
569 | | | 569 | |
570 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | | 570 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
571 | sprctl |= SPRITE_PIPE_CSC_ENABLE; | | 571 | sprctl |= SPRITE_PIPE_CSC_ENABLE; |
572 | | | 572 | |
573 | intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size, | | 573 | intel_update_sprite_watermarks(plane, crtc, src_w, src_h, pixel_size, |
574 | true, | | 574 | true, |
575 | src_w != crtc_w || src_h != crtc_h); | | 575 | src_w != crtc_w || src_h != crtc_h); |
576 | | | 576 | |
577 | /* Sizes are 0 based */ | | 577 | /* Sizes are 0 based */ |
578 | src_w--; | | 578 | src_w--; |
579 | src_h--; | | 579 | src_h--; |
580 | crtc_w--; | | 580 | crtc_w--; |
581 | crtc_h--; | | 581 | crtc_h--; |
582 | | | 582 | |
583 | if (crtc_w != src_w || crtc_h != src_h) | | 583 | if (crtc_w != src_w || crtc_h != src_h) |
584 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; | | 584 | sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h; |
585 | | | 585 | |
586 | linear_offset = y * fb->pitches[0] + x * pixel_size; | | 586 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
587 | sprsurf_offset = | | 587 | sprsurf_offset = |
588 | intel_gen4_compute_page_offset(dev_priv, | | 588 | intel_gen4_compute_page_offset(dev_priv, |
589 | &x, &y, obj->tiling_mode, | | 589 | &x, &y, obj->tiling_mode, |
590 | pixel_size, fb->pitches[0]); | | 590 | pixel_size, fb->pitches[0]); |
591 | linear_offset -= sprsurf_offset; | | 591 | linear_offset -= sprsurf_offset; |
592 | | | 592 | |
593 | if (plane->state->rotation == BIT(DRM_ROTATE_180)) { | | 593 | if (plane->state->rotation == BIT(DRM_ROTATE_180)) { |
594 | sprctl |= SPRITE_ROTATE_180; | | 594 | sprctl |= SPRITE_ROTATE_180; |
595 | | | 595 | |
596 | /* HSW and BDW does this automagically in hardware */ | | 596 | /* HSW and BDW does this automagically in hardware */ |
597 | if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { | | 597 | if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { |
598 | x += src_w; | | 598 | x += src_w; |
599 | y += src_h; | | 599 | y += src_h; |
600 | linear_offset += src_h * fb->pitches[0] + | | 600 | linear_offset += src_h * fb->pitches[0] + |
601 | src_w * pixel_size; | | 601 | src_w * pixel_size; |
602 | } | | 602 | } |
603 | } | | 603 | } |
604 | | | 604 | |
605 | if (key->flags) { | | 605 | if (key->flags) { |
606 | I915_WRITE(SPRKEYVAL(pipe), key->min_value); | | 606 | I915_WRITE(SPRKEYVAL(pipe), key->min_value); |
607 | I915_WRITE(SPRKEYMAX(pipe), key->max_value); | | 607 | I915_WRITE(SPRKEYMAX(pipe), key->max_value); |
608 | I915_WRITE(SPRKEYMSK(pipe), key->channel_mask); | | 608 | I915_WRITE(SPRKEYMSK(pipe), key->channel_mask); |
609 | } | | 609 | } |
610 | | | 610 | |
611 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | | 611 | if (key->flags & I915_SET_COLORKEY_DESTINATION) |
612 | sprctl |= SPRITE_DEST_KEY; | | 612 | sprctl |= SPRITE_DEST_KEY; |
613 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | | 613 | else if (key->flags & I915_SET_COLORKEY_SOURCE) |
614 | sprctl |= SPRITE_SOURCE_KEY; | | 614 | sprctl |= SPRITE_SOURCE_KEY; |
615 | | | 615 | |
616 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); | | 616 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); |
617 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); | | 617 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
618 | | | 618 | |
619 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | | 619 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
620 | * register */ | | 620 | * register */ |
621 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | | 621 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) |
622 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); | | 622 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); |
623 | else if (obj->tiling_mode != I915_TILING_NONE) | | 623 | else if (obj->tiling_mode != I915_TILING_NONE) |
624 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); | | 624 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); |
625 | else | | 625 | else |
626 | I915_WRITE(SPRLINOFF(pipe), linear_offset); | | 626 | I915_WRITE(SPRLINOFF(pipe), linear_offset); |
627 | | | 627 | |
628 | I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); | | 628 | I915_WRITE(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); |
629 | if (intel_plane->can_scale) | | 629 | if (intel_plane->can_scale) |
630 | I915_WRITE(SPRSCALE(pipe), sprscale); | | 630 | I915_WRITE(SPRSCALE(pipe), sprscale); |
631 | I915_WRITE(SPRCTL(pipe), sprctl); | | 631 | I915_WRITE(SPRCTL(pipe), sprctl); |
632 | I915_WRITE(SPRSURF(pipe), | | 632 | I915_WRITE(SPRSURF(pipe), |
633 | i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); | | 633 | i915_gem_obj_ggtt_offset(obj) + sprsurf_offset); |
634 | POSTING_READ(SPRSURF(pipe)); | | 634 | POSTING_READ(SPRSURF(pipe)); |
635 | } | | 635 | } |
636 | | | 636 | |
637 | static void | | 637 | static void |
638 | ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | | 638 | ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) |
639 | { | | 639 | { |
640 | struct drm_device *dev = plane->dev; | | 640 | struct drm_device *dev = plane->dev; |
641 | struct drm_i915_private *dev_priv = dev->dev_private; | | 641 | struct drm_i915_private *dev_priv = dev->dev_private; |
642 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 642 | struct intel_plane *intel_plane = to_intel_plane(plane); |
643 | int pipe = intel_plane->pipe; | | 643 | int pipe = intel_plane->pipe; |
644 | | | 644 | |
645 | I915_WRITE(SPRCTL(pipe), 0); | | 645 | I915_WRITE(SPRCTL(pipe), 0); |
646 | /* Can't leave the scaler enabled... */ | | 646 | /* Can't leave the scaler enabled... */ |
647 | if (intel_plane->can_scale) | | 647 | if (intel_plane->can_scale) |
648 | I915_WRITE(SPRSCALE(pipe), 0); | | 648 | I915_WRITE(SPRSCALE(pipe), 0); |
649 | | | 649 | |
650 | I915_WRITE(SPRSURF(pipe), 0); | | 650 | I915_WRITE(SPRSURF(pipe), 0); |
651 | POSTING_READ(SPRSURF(pipe)); | | 651 | POSTING_READ(SPRSURF(pipe)); |
652 | } | | 652 | } |
653 | | | 653 | |
654 | static void | | 654 | static void |
655 | ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, | | 655 | ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, |
656 | struct drm_framebuffer *fb, | | 656 | struct drm_framebuffer *fb, |
657 | int crtc_x, int crtc_y, | | 657 | int crtc_x, int crtc_y, |
658 | unsigned int crtc_w, unsigned int crtc_h, | | 658 | unsigned int crtc_w, unsigned int crtc_h, |
659 | uint32_t x, uint32_t y, | | 659 | uint32_t x, uint32_t y, |
660 | uint32_t src_w, uint32_t src_h) | | 660 | uint32_t src_w, uint32_t src_h) |
661 | { | | 661 | { |
662 | struct drm_device *dev = plane->dev; | | 662 | struct drm_device *dev = plane->dev; |
663 | struct drm_i915_private *dev_priv = dev->dev_private; | | 663 | struct drm_i915_private *dev_priv = dev->dev_private; |
664 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 664 | struct intel_plane *intel_plane = to_intel_plane(plane); |
665 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | | 665 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
666 | int pipe = intel_plane->pipe; | | 666 | int pipe = intel_plane->pipe; |
667 | unsigned long dvssurf_offset, linear_offset; | | 667 | unsigned long dvssurf_offset, linear_offset; |
668 | u32 dvscntr, dvsscale; | | 668 | u32 dvscntr, dvsscale; |
669 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | | 669 | int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
670 | const struct drm_intel_sprite_colorkey *key = | | 670 | const struct drm_intel_sprite_colorkey *key = |
671 | &to_intel_plane_state(plane->state)->ckey; | | 671 | &to_intel_plane_state(plane->state)->ckey; |
672 | | | 672 | |
673 | dvscntr = DVS_ENABLE; | | 673 | dvscntr = DVS_ENABLE; |
674 | | | 674 | |
675 | switch (fb->pixel_format) { | | 675 | switch (fb->pixel_format) { |
676 | case DRM_FORMAT_XBGR8888: | | 676 | case DRM_FORMAT_XBGR8888: |
677 | dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; | | 677 | dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR; |
678 | break; | | 678 | break; |
679 | case DRM_FORMAT_XRGB8888: | | 679 | case DRM_FORMAT_XRGB8888: |
680 | dvscntr |= DVS_FORMAT_RGBX888; | | 680 | dvscntr |= DVS_FORMAT_RGBX888; |
681 | break; | | 681 | break; |
682 | case DRM_FORMAT_YUYV: | | 682 | case DRM_FORMAT_YUYV: |
683 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; | | 683 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV; |
684 | break; | | 684 | break; |
685 | case DRM_FORMAT_YVYU: | | 685 | case DRM_FORMAT_YVYU: |
686 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; | | 686 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU; |
687 | break; | | 687 | break; |
688 | case DRM_FORMAT_UYVY: | | 688 | case DRM_FORMAT_UYVY: |
689 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; | | 689 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY; |
690 | break; | | 690 | break; |
691 | case DRM_FORMAT_VYUY: | | 691 | case DRM_FORMAT_VYUY: |
692 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; | | 692 | dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY; |
693 | break; | | 693 | break; |
694 | default: | | 694 | default: |
695 | BUG(); | | 695 | BUG(); |
696 | } | | 696 | } |
697 | | | 697 | |
698 | /* | | 698 | /* |
699 | * Enable gamma to match primary/cursor plane behaviour. | | 699 | * Enable gamma to match primary/cursor plane behaviour. |
700 | * FIXME should be user controllable via propertiesa. | | 700 | * FIXME should be user controllable via propertiesa. |
701 | */ | | 701 | */ |
702 | dvscntr |= DVS_GAMMA_ENABLE; | | 702 | dvscntr |= DVS_GAMMA_ENABLE; |
703 | | | 703 | |
704 | if (obj->tiling_mode != I915_TILING_NONE) | | 704 | if (obj->tiling_mode != I915_TILING_NONE) |
705 | dvscntr |= DVS_TILED; | | 705 | dvscntr |= DVS_TILED; |
706 | | | 706 | |
707 | if (IS_GEN6(dev)) | | 707 | if (IS_GEN6(dev)) |
708 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ | | 708 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ |
709 | | | 709 | |
710 | intel_update_sprite_watermarks(plane, crtc, src_w, src_h, | | 710 | intel_update_sprite_watermarks(plane, crtc, src_w, src_h, |
711 | pixel_size, true, | | 711 | pixel_size, true, |
712 | src_w != crtc_w || src_h != crtc_h); | | 712 | src_w != crtc_w || src_h != crtc_h); |
713 | | | 713 | |
714 | /* Sizes are 0 based */ | | 714 | /* Sizes are 0 based */ |
715 | src_w--; | | 715 | src_w--; |
716 | src_h--; | | 716 | src_h--; |
717 | crtc_w--; | | 717 | crtc_w--; |
718 | crtc_h--; | | 718 | crtc_h--; |
719 | | | 719 | |
720 | dvsscale = 0; | | 720 | dvsscale = 0; |
721 | if (crtc_w != src_w || crtc_h != src_h) | | 721 | if (crtc_w != src_w || crtc_h != src_h) |
722 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; | | 722 | dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h; |
723 | | | 723 | |
724 | linear_offset = y * fb->pitches[0] + x * pixel_size; | | 724 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
725 | dvssurf_offset = | | 725 | dvssurf_offset = |
726 | intel_gen4_compute_page_offset(dev_priv, | | 726 | intel_gen4_compute_page_offset(dev_priv, |
727 | &x, &y, obj->tiling_mode, | | 727 | &x, &y, obj->tiling_mode, |
728 | pixel_size, fb->pitches[0]); | | 728 | pixel_size, fb->pitches[0]); |
729 | linear_offset -= dvssurf_offset; | | 729 | linear_offset -= dvssurf_offset; |
730 | | | 730 | |
731 | if (plane->state->rotation == BIT(DRM_ROTATE_180)) { | | 731 | if (plane->state->rotation == BIT(DRM_ROTATE_180)) { |
732 | dvscntr |= DVS_ROTATE_180; | | 732 | dvscntr |= DVS_ROTATE_180; |
733 | | | 733 | |
734 | x += src_w; | | 734 | x += src_w; |
735 | y += src_h; | | 735 | y += src_h; |
736 | linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; | | 736 | linear_offset += src_h * fb->pitches[0] + src_w * pixel_size; |
737 | } | | 737 | } |
738 | | | 738 | |
739 | if (key->flags) { | | 739 | if (key->flags) { |
740 | I915_WRITE(DVSKEYVAL(pipe), key->min_value); | | 740 | I915_WRITE(DVSKEYVAL(pipe), key->min_value); |
741 | I915_WRITE(DVSKEYMAX(pipe), key->max_value); | | 741 | I915_WRITE(DVSKEYMAX(pipe), key->max_value); |
742 | I915_WRITE(DVSKEYMSK(pipe), key->channel_mask); | | 742 | I915_WRITE(DVSKEYMSK(pipe), key->channel_mask); |
743 | } | | 743 | } |
744 | | | 744 | |
745 | if (key->flags & I915_SET_COLORKEY_DESTINATION) | | 745 | if (key->flags & I915_SET_COLORKEY_DESTINATION) |
746 | dvscntr |= DVS_DEST_KEY; | | 746 | dvscntr |= DVS_DEST_KEY; |
747 | else if (key->flags & I915_SET_COLORKEY_SOURCE) | | 747 | else if (key->flags & I915_SET_COLORKEY_SOURCE) |
748 | dvscntr |= DVS_SOURCE_KEY; | | 748 | dvscntr |= DVS_SOURCE_KEY; |
749 | | | 749 | |
750 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); | | 750 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); |
751 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); | | 751 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); |
752 | | | 752 | |
753 | if (obj->tiling_mode != I915_TILING_NONE) | | 753 | if (obj->tiling_mode != I915_TILING_NONE) |
754 | I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); | | 754 | I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x); |
755 | else | | 755 | else |
756 | I915_WRITE(DVSLINOFF(pipe), linear_offset); | | 756 | I915_WRITE(DVSLINOFF(pipe), linear_offset); |
757 | | | 757 | |
758 | I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); | | 758 | I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w); |
759 | I915_WRITE(DVSSCALE(pipe), dvsscale); | | 759 | I915_WRITE(DVSSCALE(pipe), dvsscale); |
760 | I915_WRITE(DVSCNTR(pipe), dvscntr); | | 760 | I915_WRITE(DVSCNTR(pipe), dvscntr); |
761 | I915_WRITE(DVSSURF(pipe), | | 761 | I915_WRITE(DVSSURF(pipe), |
762 | i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); | | 762 | i915_gem_obj_ggtt_offset(obj) + dvssurf_offset); |
763 | POSTING_READ(DVSSURF(pipe)); | | 763 | POSTING_READ(DVSSURF(pipe)); |
764 | } | | 764 | } |
765 | | | 765 | |
766 | static void | | 766 | static void |
767 | ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) | | 767 | ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc) |
768 | { | | 768 | { |
769 | struct drm_device *dev = plane->dev; | | 769 | struct drm_device *dev = plane->dev; |
770 | struct drm_i915_private *dev_priv = dev->dev_private; | | 770 | struct drm_i915_private *dev_priv = dev->dev_private; |
771 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 771 | struct intel_plane *intel_plane = to_intel_plane(plane); |
772 | int pipe = intel_plane->pipe; | | 772 | int pipe = intel_plane->pipe; |
773 | | | 773 | |
774 | I915_WRITE(DVSCNTR(pipe), 0); | | 774 | I915_WRITE(DVSCNTR(pipe), 0); |
775 | /* Disable the scaler */ | | 775 | /* Disable the scaler */ |
776 | I915_WRITE(DVSSCALE(pipe), 0); | | 776 | I915_WRITE(DVSSCALE(pipe), 0); |
777 | | | 777 | |
778 | I915_WRITE(DVSSURF(pipe), 0); | | 778 | I915_WRITE(DVSSURF(pipe), 0); |
779 | POSTING_READ(DVSSURF(pipe)); | | 779 | POSTING_READ(DVSSURF(pipe)); |
780 | } | | 780 | } |
781 | | | 781 | |
782 | static int | | 782 | static int |
783 | intel_check_sprite_plane(struct drm_plane *plane, | | 783 | intel_check_sprite_plane(struct drm_plane *plane, |
784 | struct intel_crtc_state *crtc_state, | | 784 | struct intel_crtc_state *crtc_state, |
785 | struct intel_plane_state *state) | | 785 | struct intel_plane_state *state) |
786 | { | | 786 | { |
787 | struct drm_device *dev = plane->dev; | | 787 | struct drm_device *dev = plane->dev; |
788 | struct drm_crtc *crtc = state->base.crtc; | | 788 | struct drm_crtc *crtc = state->base.crtc; |
789 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | | 789 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
790 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 790 | struct intel_plane *intel_plane = to_intel_plane(plane); |
791 | struct drm_framebuffer *fb = state->base.fb; | | 791 | struct drm_framebuffer *fb = state->base.fb; |
792 | int crtc_x, crtc_y; | | 792 | int crtc_x, crtc_y; |
793 | unsigned int crtc_w, crtc_h; | | 793 | unsigned int crtc_w, crtc_h; |
794 | uint32_t src_x, src_y, src_w, src_h; | | 794 | uint32_t src_x, src_y, src_w, src_h; |
795 | struct drm_rect *src = &state->src; | | 795 | struct drm_rect *src = &state->src; |
796 | struct drm_rect *dst = &state->dst; | | 796 | struct drm_rect *dst = &state->dst; |
797 | const struct drm_rect *clip = &state->clip; | | 797 | const struct drm_rect *clip = &state->clip; |
798 | int hscale, vscale; | | 798 | int hscale, vscale; |
799 | int max_scale, min_scale; | | 799 | int max_scale, min_scale; |
800 | bool can_scale; | | 800 | bool can_scale; |
801 | int pixel_size; | | 801 | int pixel_size; |
802 | | | 802 | |
803 | if (!fb) { | | 803 | if (!fb) { |
804 | state->visible = false; | | 804 | state->visible = false; |
805 | return 0; | | 805 | return 0; |
806 | } | | 806 | } |
807 | | | 807 | |
808 | /* Don't modify another pipe's plane */ | | 808 | /* Don't modify another pipe's plane */ |
809 | if (intel_plane->pipe != intel_crtc->pipe) { | | 809 | if (intel_plane->pipe != intel_crtc->pipe) { |
810 | DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); | | 810 | DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); |
811 | return -EINVAL; | | 811 | return -EINVAL; |
812 | } | | 812 | } |
813 | | | 813 | |
814 | /* FIXME check all gen limits */ | | 814 | /* FIXME check all gen limits */ |
815 | if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { | | 815 | if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > 16384) { |
816 | DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); | | 816 | DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); |
817 | return -EINVAL; | | 817 | return -EINVAL; |
818 | } | | 818 | } |
819 | | | 819 | |
820 | /* setup can_scale, min_scale, max_scale */ | | 820 | /* setup can_scale, min_scale, max_scale */ |
821 | if (INTEL_INFO(dev)->gen >= 9) { | | 821 | if (INTEL_INFO(dev)->gen >= 9) { |
822 | /* use scaler when colorkey is not required */ | | 822 | /* use scaler when colorkey is not required */ |
823 | if (state->ckey.flags == I915_SET_COLORKEY_NONE) { | | 823 | if (state->ckey.flags == I915_SET_COLORKEY_NONE) { |
824 | can_scale = 1; | | 824 | can_scale = 1; |
825 | min_scale = 1; | | 825 | min_scale = 1; |
826 | max_scale = skl_max_scale(intel_crtc, crtc_state); | | 826 | max_scale = skl_max_scale(intel_crtc, crtc_state); |
827 | } else { | | 827 | } else { |
828 | can_scale = 0; | | 828 | can_scale = 0; |
829 | min_scale = DRM_PLANE_HELPER_NO_SCALING; | | 829 | min_scale = DRM_PLANE_HELPER_NO_SCALING; |
830 | max_scale = DRM_PLANE_HELPER_NO_SCALING; | | 830 | max_scale = DRM_PLANE_HELPER_NO_SCALING; |
831 | } | | 831 | } |
832 | } else { | | 832 | } else { |
833 | can_scale = intel_plane->can_scale; | | 833 | can_scale = intel_plane->can_scale; |
834 | max_scale = intel_plane->max_downscale << 16; | | 834 | max_scale = intel_plane->max_downscale << 16; |
835 | min_scale = intel_plane->can_scale ? 1 : (1 << 16); | | 835 | min_scale = intel_plane->can_scale ? 1 : (1 << 16); |
836 | } | | 836 | } |
837 | | | 837 | |
838 | /* | | 838 | /* |
839 | * FIXME the following code does a bunch of fuzzy adjustments to the | | 839 | * FIXME the following code does a bunch of fuzzy adjustments to the |
840 | * coordinates and sizes. We probably need some way to decide whether | | 840 | * coordinates and sizes. We probably need some way to decide whether |
841 | * more strict checking should be done instead. | | 841 | * more strict checking should be done instead. |
842 | */ | | 842 | */ |
843 | drm_rect_rotate(src, fb->width << 16, fb->height << 16, | | 843 | drm_rect_rotate(src, fb->width << 16, fb->height << 16, |
844 | state->base.rotation); | | 844 | state->base.rotation); |
845 | | | 845 | |
846 | hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale); | | 846 | hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale); |
847 | BUG_ON(hscale < 0); | | 847 | BUG_ON(hscale < 0); |
848 | | | 848 | |
849 | vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); | | 849 | vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale); |
850 | BUG_ON(vscale < 0); | | 850 | BUG_ON(vscale < 0); |
851 | | | 851 | |
852 | state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); | | 852 | state->visible = drm_rect_clip_scaled(src, dst, clip, hscale, vscale); |
853 | | | 853 | |
854 | crtc_x = dst->x1; | | 854 | crtc_x = dst->x1; |
855 | crtc_y = dst->y1; | | 855 | crtc_y = dst->y1; |
856 | crtc_w = drm_rect_width(dst); | | 856 | crtc_w = drm_rect_width(dst); |
857 | crtc_h = drm_rect_height(dst); | | 857 | crtc_h = drm_rect_height(dst); |
858 | | | 858 | |
859 | if (state->visible) { | | 859 | if (state->visible) { |
860 | /* check again in case clipping clamped the results */ | | 860 | /* check again in case clipping clamped the results */ |
861 | hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); | | 861 | hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale); |
862 | if (hscale < 0) { | | 862 | if (hscale < 0) { |
863 | DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); | | 863 | DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n"); |
864 | drm_rect_debug_print(src, true); | | 864 | drm_rect_debug_print(src, true); |
865 | drm_rect_debug_print(dst, false); | | 865 | drm_rect_debug_print(dst, false); |
866 | | | 866 | |
867 | return hscale; | | 867 | return hscale; |
868 | } | | 868 | } |
869 | | | 869 | |
870 | vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); | | 870 | vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale); |
871 | if (vscale < 0) { | | 871 | if (vscale < 0) { |
872 | DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); | | 872 | DRM_DEBUG_KMS("Vertical scaling factor out of limits\n"); |
873 | drm_rect_debug_print(src, true); | | 873 | drm_rect_debug_print(src, true); |
874 | drm_rect_debug_print(dst, false); | | 874 | drm_rect_debug_print(dst, false); |
875 | | | 875 | |
876 | return vscale; | | 876 | return vscale; |
877 | } | | 877 | } |
878 | | | 878 | |
879 | /* Make the source viewport size an exact multiple of the scaling factors. */ | | 879 | /* Make the source viewport size an exact multiple of the scaling factors. */ |
880 | drm_rect_adjust_size(src, | | 880 | drm_rect_adjust_size(src, |
881 | drm_rect_width(dst) * hscale - drm_rect_width(src), | | 881 | drm_rect_width(dst) * hscale - drm_rect_width(src), |
882 | drm_rect_height(dst) * vscale - drm_rect_height(src)); | | 882 | drm_rect_height(dst) * vscale - drm_rect_height(src)); |
883 | | | 883 | |
884 | drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, | | 884 | drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, |
885 | state->base.rotation); | | 885 | state->base.rotation); |
886 | | | 886 | |
887 | /* sanity check to make sure the src viewport wasn't enlarged */ | | 887 | /* sanity check to make sure the src viewport wasn't enlarged */ |
888 | WARN_ON(src->x1 < (int) state->base.src_x || | | 888 | WARN_ON(src->x1 < (int) state->base.src_x || |
889 | src->y1 < (int) state->base.src_y || | | 889 | src->y1 < (int) state->base.src_y || |
890 | src->x2 > (int) state->base.src_x + state->base.src_w || | | 890 | src->x2 > (int) state->base.src_x + state->base.src_w || |
891 | src->y2 > (int) state->base.src_y + state->base.src_h); | | 891 | src->y2 > (int) state->base.src_y + state->base.src_h); |
892 | | | 892 | |
893 | /* | | 893 | /* |
894 | * Hardware doesn't handle subpixel coordinates. | | 894 | * Hardware doesn't handle subpixel coordinates. |
895 | * Adjust to (macro)pixel boundary, but be careful not to | | 895 | * Adjust to (macro)pixel boundary, but be careful not to |
896 | * increase the source viewport size, because that could | | 896 | * increase the source viewport size, because that could |
897 | * push the downscaling factor out of bounds. | | 897 | * push the downscaling factor out of bounds. |
898 | */ | | 898 | */ |
899 | src_x = src->x1 >> 16; | | 899 | src_x = src->x1 >> 16; |
900 | src_w = drm_rect_width(src) >> 16; | | 900 | src_w = drm_rect_width(src) >> 16; |
901 | src_y = src->y1 >> 16; | | 901 | src_y = src->y1 >> 16; |
902 | src_h = drm_rect_height(src) >> 16; | | 902 | src_h = drm_rect_height(src) >> 16; |
903 | | | 903 | |
904 | if (format_is_yuv(fb->pixel_format)) { | | 904 | if (format_is_yuv(fb->pixel_format)) { |
905 | src_x &= ~1; | | 905 | src_x &= ~1; |
906 | src_w &= ~1; | | 906 | src_w &= ~1; |
907 | | | 907 | |
908 | /* | | 908 | /* |
909 | * Must keep src and dst the | | 909 | * Must keep src and dst the |
910 | * same if we can't scale. | | 910 | * same if we can't scale. |
911 | */ | | 911 | */ |
912 | if (!can_scale) | | 912 | if (!can_scale) |
913 | crtc_w &= ~1; | | 913 | crtc_w &= ~1; |
914 | | | 914 | |
915 | if (crtc_w == 0) | | 915 | if (crtc_w == 0) |
916 | state->visible = false; | | 916 | state->visible = false; |
917 | } | | 917 | } |
918 | } | | 918 | } |
919 | | | 919 | |
920 | /* Check size restrictions when scaling */ | | 920 | /* Check size restrictions when scaling */ |
921 | if (state->visible && (src_w != crtc_w || src_h != crtc_h)) { | | 921 | if (state->visible && (src_w != crtc_w || src_h != crtc_h)) { |
922 | unsigned int width_bytes; | | 922 | unsigned int width_bytes; |
923 | | | 923 | |
924 | WARN_ON(!can_scale); | | 924 | WARN_ON(!can_scale); |
925 | | | 925 | |
926 | /* FIXME interlacing min height is 6 */ | | 926 | /* FIXME interlacing min height is 6 */ |
927 | | | 927 | |
928 | if (crtc_w < 3 || crtc_h < 3) | | 928 | if (crtc_w < 3 || crtc_h < 3) |
929 | state->visible = false; | | 929 | state->visible = false; |
930 | | | 930 | |
931 | if (src_w < 3 || src_h < 3) | | 931 | if (src_w < 3 || src_h < 3) |
932 | state->visible = false; | | 932 | state->visible = false; |
933 | | | 933 | |
934 | pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); | | 934 | pixel_size = drm_format_plane_cpp(fb->pixel_format, 0); |
935 | width_bytes = ((src_x * pixel_size) & 63) + | | 935 | width_bytes = ((src_x * pixel_size) & 63) + |
936 | src_w * pixel_size; | | 936 | src_w * pixel_size; |
937 | | | 937 | |
938 | if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || | | 938 | if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || |
939 | width_bytes > 4096 || fb->pitches[0] > 4096)) { | | 939 | width_bytes > 4096 || fb->pitches[0] > 4096)) { |
940 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); | | 940 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); |
941 | return -EINVAL; | | 941 | return -EINVAL; |
942 | } | | 942 | } |
943 | } | | 943 | } |
944 | | | 944 | |
945 | if (state->visible) { | | 945 | if (state->visible) { |
946 | src->x1 = src_x << 16; | | 946 | src->x1 = src_x << 16; |
947 | src->x2 = (src_x + src_w) << 16; | | 947 | src->x2 = (src_x + src_w) << 16; |
948 | src->y1 = src_y << 16; | | 948 | src->y1 = src_y << 16; |
949 | src->y2 = (src_y + src_h) << 16; | | 949 | src->y2 = (src_y + src_h) << 16; |
950 | } | | 950 | } |
951 | | | 951 | |
952 | dst->x1 = crtc_x; | | 952 | dst->x1 = crtc_x; |
953 | dst->x2 = crtc_x + crtc_w; | | 953 | dst->x2 = crtc_x + crtc_w; |
954 | dst->y1 = crtc_y; | | 954 | dst->y1 = crtc_y; |
955 | dst->y2 = crtc_y + crtc_h; | | 955 | dst->y2 = crtc_y + crtc_h; |
956 | | | 956 | |
957 | return 0; | | 957 | return 0; |
958 | } | | 958 | } |
959 | | | 959 | |
960 | static void | | 960 | static void |
961 | intel_commit_sprite_plane(struct drm_plane *plane, | | 961 | intel_commit_sprite_plane(struct drm_plane *plane, |
962 | struct intel_plane_state *state) | | 962 | struct intel_plane_state *state) |
963 | { | | 963 | { |
964 | struct drm_crtc *crtc = state->base.crtc; | | 964 | struct drm_crtc *crtc = state->base.crtc; |
965 | struct intel_plane *intel_plane = to_intel_plane(plane); | | 965 | struct intel_plane *intel_plane = to_intel_plane(plane); |
966 | struct drm_framebuffer *fb = state->base.fb; | | 966 | struct drm_framebuffer *fb = state->base.fb; |
967 | | | 967 | |
968 | crtc = crtc ? crtc : plane->crtc; | | 968 | crtc = crtc ? crtc : plane->crtc; |
969 | | | 969 | |
970 | if (!crtc->state->active) | | 970 | if (!crtc->state->active) |
971 | return; | | 971 | return; |
972 | | | 972 | |
973 | if (state->visible) { | | 973 | if (state->visible) { |
974 | intel_plane->update_plane(plane, crtc, fb, | | 974 | intel_plane->update_plane(plane, crtc, fb, |
975 | state->dst.x1, state->dst.y1, | | 975 | state->dst.x1, state->dst.y1, |
976 | drm_rect_width(&state->dst), | | 976 | drm_rect_width(&state->dst), |
977 | drm_rect_height(&state->dst), | | 977 | drm_rect_height(&state->dst), |
978 | state->src.x1 >> 16, | | 978 | state->src.x1 >> 16, |
979 | state->src.y1 >> 16, | | 979 | state->src.y1 >> 16, |
980 | drm_rect_width(&state->src) >> 16, | | 980 | drm_rect_width(&state->src) >> 16, |
981 | drm_rect_height(&state->src) >> 16); | | 981 | drm_rect_height(&state->src) >> 16); |
982 | } else { | | 982 | } else { |
983 | intel_plane->disable_plane(plane, crtc); | | 983 | intel_plane->disable_plane(plane, crtc); |
984 | } | | 984 | } |
985 | } | | 985 | } |
986 | | | 986 | |
987 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | | 987 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, |
988 | struct drm_file *file_priv) | | 988 | struct drm_file *file_priv) |
989 | { | | 989 | { |
990 | struct drm_intel_sprite_colorkey *set = data; | | 990 | struct drm_intel_sprite_colorkey *set = data; |
991 | struct drm_plane *plane; | | 991 | struct drm_plane *plane; |
992 | struct drm_plane_state *plane_state; | | 992 | struct drm_plane_state *plane_state; |
993 | struct drm_atomic_state *state; | | 993 | struct drm_atomic_state *state; |
994 | struct drm_modeset_acquire_ctx ctx; | | 994 | struct drm_modeset_acquire_ctx ctx; |
995 | int ret = 0; | | 995 | int ret = 0; |
996 | | | 996 | |
997 | /* Make sure we don't try to enable both src & dest simultaneously */ | | 997 | /* Make sure we don't try to enable both src & dest simultaneously */ |
998 | if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) | | 998 | if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) |
999 | return -EINVAL; | | 999 | return -EINVAL; |
1000 | | | 1000 | |
1001 | if (IS_VALLEYVIEW(dev) && | | 1001 | if (IS_VALLEYVIEW(dev) && |
1002 | set->flags & I915_SET_COLORKEY_DESTINATION) | | 1002 | set->flags & I915_SET_COLORKEY_DESTINATION) |
1003 | return -EINVAL; | | 1003 | return -EINVAL; |
1004 | | | 1004 | |
1005 | plane = drm_plane_find(dev, set->plane_id); | | 1005 | plane = drm_plane_find(dev, set->plane_id); |
1006 | if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) | | 1006 | if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) |
1007 | return -ENOENT; | | 1007 | return -ENOENT; |
1008 | | | 1008 | |
1009 | drm_modeset_acquire_init(&ctx, 0); | | 1009 | drm_modeset_acquire_init(&ctx, 0); |
1010 | | | 1010 | |
1011 | state = drm_atomic_state_alloc(plane->dev); | | 1011 | state = drm_atomic_state_alloc(plane->dev); |
1012 | if (!state) { | | 1012 | if (!state) { |
1013 | ret = -ENOMEM; | | 1013 | ret = -ENOMEM; |
1014 | goto out; | | 1014 | goto out; |
1015 | } | | 1015 | } |
1016 | state->acquire_ctx = &ctx; | | 1016 | state->acquire_ctx = &ctx; |
1017 | | | 1017 | |
1018 | while (1) { | | 1018 | while (1) { |
1019 | plane_state = drm_atomic_get_plane_state(state, plane); | | 1019 | plane_state = drm_atomic_get_plane_state(state, plane); |
1020 | ret = PTR_ERR_OR_ZERO(plane_state); | | 1020 | ret = PTR_ERR_OR_ZERO(plane_state); |
1021 | if (!ret) { | | 1021 | if (!ret) { |
1022 | to_intel_plane_state(plane_state)->ckey = *set; | | 1022 | to_intel_plane_state(plane_state)->ckey = *set; |
1023 | ret = drm_atomic_commit(state); | | 1023 | ret = drm_atomic_commit(state); |
1024 | } | | 1024 | } |
1025 | | | 1025 | |
1026 | if (ret != -EDEADLK) | | 1026 | if (ret != -EDEADLK) |
1027 | break; | | 1027 | break; |
1028 | | | 1028 | |
1029 | drm_atomic_state_clear(state); | | 1029 | drm_atomic_state_clear(state); |
1030 | drm_modeset_backoff(&ctx); | | 1030 | drm_modeset_backoff(&ctx); |
1031 | } | | 1031 | } |
1032 | | | 1032 | |
1033 | if (ret) | | 1033 | if (ret) |
1034 | drm_atomic_state_free(state); | | 1034 | drm_atomic_state_free(state); |
1035 | | | 1035 | |
1036 | out: | | 1036 | out: |
1037 | drm_modeset_drop_locks(&ctx); | | 1037 | drm_modeset_drop_locks(&ctx); |
1038 | drm_modeset_acquire_fini(&ctx); | | 1038 | drm_modeset_acquire_fini(&ctx); |
1039 | return ret; | | 1039 | return ret; |
1040 | } | | 1040 | } |
1041 | | | 1041 | |
1042 | static const uint32_t ilk_plane_formats[] = { | | 1042 | static const uint32_t ilk_plane_formats[] = { |
1043 | DRM_FORMAT_XRGB8888, | | 1043 | DRM_FORMAT_XRGB8888, |
1044 | DRM_FORMAT_YUYV, | | 1044 | DRM_FORMAT_YUYV, |
1045 | DRM_FORMAT_YVYU, | | 1045 | DRM_FORMAT_YVYU, |
1046 | DRM_FORMAT_UYVY, | | 1046 | DRM_FORMAT_UYVY, |
1047 | DRM_FORMAT_VYUY, | | 1047 | DRM_FORMAT_VYUY, |
1048 | }; | | 1048 | }; |
1049 | | | 1049 | |
1050 | static const uint32_t snb_plane_formats[] = { | | 1050 | static const uint32_t snb_plane_formats[] = { |
1051 | DRM_FORMAT_XBGR8888, | | 1051 | DRM_FORMAT_XBGR8888, |
1052 | DRM_FORMAT_XRGB8888, | | 1052 | DRM_FORMAT_XRGB8888, |
1053 | DRM_FORMAT_YUYV, | | 1053 | DRM_FORMAT_YUYV, |
1054 | DRM_FORMAT_YVYU, | | 1054 | DRM_FORMAT_YVYU, |
1055 | DRM_FORMAT_UYVY, | | 1055 | DRM_FORMAT_UYVY, |
1056 | DRM_FORMAT_VYUY, | | 1056 | DRM_FORMAT_VYUY, |
1057 | }; | | 1057 | }; |
1058 | | | 1058 | |
1059 | static const uint32_t vlv_plane_formats[] = { | | 1059 | static const uint32_t vlv_plane_formats[] = { |
1060 | DRM_FORMAT_RGB565, | | 1060 | DRM_FORMAT_RGB565, |
1061 | DRM_FORMAT_ABGR8888, | | 1061 | DRM_FORMAT_ABGR8888, |
1062 | DRM_FORMAT_ARGB8888, | | 1062 | DRM_FORMAT_ARGB8888, |
1063 | DRM_FORMAT_XBGR8888, | | 1063 | DRM_FORMAT_XBGR8888, |
1064 | DRM_FORMAT_XRGB8888, | | 1064 | DRM_FORMAT_XRGB8888, |
1065 | DRM_FORMAT_XBGR2101010, | | 1065 | DRM_FORMAT_XBGR2101010, |
1066 | DRM_FORMAT_ABGR2101010, | | 1066 | DRM_FORMAT_ABGR2101010, |
1067 | DRM_FORMAT_YUYV, | | 1067 | DRM_FORMAT_YUYV, |
1068 | DRM_FORMAT_YVYU, | | 1068 | DRM_FORMAT_YVYU, |
1069 | DRM_FORMAT_UYVY, | | 1069 | DRM_FORMAT_UYVY, |
1070 | DRM_FORMAT_VYUY, | | 1070 | DRM_FORMAT_VYUY, |
1071 | }; | | 1071 | }; |
1072 | | | 1072 | |
1073 | static uint32_t skl_plane_formats[] = { | | 1073 | static uint32_t skl_plane_formats[] = { |
1074 | DRM_FORMAT_RGB565, | | 1074 | DRM_FORMAT_RGB565, |
1075 | DRM_FORMAT_ABGR8888, | | 1075 | DRM_FORMAT_ABGR8888, |
1076 | DRM_FORMAT_ARGB8888, | | 1076 | DRM_FORMAT_ARGB8888, |
1077 | DRM_FORMAT_XBGR8888, | | 1077 | DRM_FORMAT_XBGR8888, |
1078 | DRM_FORMAT_XRGB8888, | | 1078 | DRM_FORMAT_XRGB8888, |
1079 | DRM_FORMAT_YUYV, | | 1079 | DRM_FORMAT_YUYV, |
1080 | DRM_FORMAT_YVYU, | | 1080 | DRM_FORMAT_YVYU, |
1081 | DRM_FORMAT_UYVY, | | 1081 | DRM_FORMAT_UYVY, |
1082 | DRM_FORMAT_VYUY, | | 1082 | DRM_FORMAT_VYUY, |
1083 | }; | | 1083 | }; |
1084 | | | 1084 | |
1085 | int | | 1085 | int |
1086 | intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | | 1086 | intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) |
1087 | { | | 1087 | { |
1088 | struct intel_plane *intel_plane; | | 1088 | struct intel_plane *intel_plane; |
1089 | struct intel_plane_state *state; | | 1089 | struct intel_plane_state *state; |
1090 | unsigned long possible_crtcs; | | 1090 | unsigned long possible_crtcs; |
1091 | const uint32_t *plane_formats; | | 1091 | const uint32_t *plane_formats; |
1092 | int num_plane_formats; | | 1092 | int num_plane_formats; |
1093 | int ret; | | 1093 | int ret; |
1094 | | | 1094 | |
1095 | if (INTEL_INFO(dev)->gen < 5) | | 1095 | if (INTEL_INFO(dev)->gen < 5) |
1096 | return -ENODEV; | | 1096 | return -ENODEV; |
1097 | | | 1097 | |
1098 | intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); | | 1098 | intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL); |
1099 | if (!intel_plane) | | 1099 | if (!intel_plane) |
1100 | return -ENOMEM; | | 1100 | return -ENOMEM; |
1101 | | | 1101 | |
1102 | state = intel_create_plane_state(&intel_plane->base); | | 1102 | state = intel_create_plane_state(&intel_plane->base); |
1103 | if (!state) { | | 1103 | if (!state) { |
1104 | kfree(intel_plane); | | 1104 | kfree(intel_plane); |
1105 | return -ENOMEM; | | 1105 | return -ENOMEM; |
1106 | } | | 1106 | } |
1107 | intel_plane->base.state = &state->base; | | 1107 | intel_plane->base.state = &state->base; |
1108 | | | 1108 | |
1109 | switch (INTEL_INFO(dev)->gen) { | | 1109 | switch (INTEL_INFO(dev)->gen) { |
1110 | case 5: | | 1110 | case 5: |
1111 | case 6: | | 1111 | case 6: |
1112 | intel_plane->can_scale = true; | | 1112 | intel_plane->can_scale = true; |
1113 | intel_plane->max_downscale = 16; | | 1113 | intel_plane->max_downscale = 16; |
1114 | intel_plane->update_plane = ilk_update_plane; | | 1114 | intel_plane->update_plane = ilk_update_plane; |
1115 | intel_plane->disable_plane = ilk_disable_plane; | | 1115 | intel_plane->disable_plane = ilk_disable_plane; |
1116 | | | 1116 | |
1117 | if (IS_GEN6(dev)) { | | 1117 | if (IS_GEN6(dev)) { |
1118 | plane_formats = snb_plane_formats; | | 1118 | plane_formats = snb_plane_formats; |
1119 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | | 1119 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); |
1120 | } else { | | 1120 | } else { |
1121 | plane_formats = ilk_plane_formats; | | 1121 | plane_formats = ilk_plane_formats; |
1122 | num_plane_formats = ARRAY_SIZE(ilk_plane_formats); | | 1122 | num_plane_formats = ARRAY_SIZE(ilk_plane_formats); |
1123 | } | | 1123 | } |
1124 | break; | | 1124 | break; |
1125 | | | 1125 | |
1126 | case 7: | | 1126 | case 7: |