]> Git Repo - linux.git/blame - drivers/gpu/drm/i915/intel_sprite.c
drm/i915: Extract per-platform plane->check() functions
[linux.git] / drivers / gpu / drm / i915 / intel_sprite.c
CommitLineData
b840d907
JB
1/*
2 * Copyright © 2011 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 FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Jesse Barnes <[email protected]>
25 *
26 * New plane/sprite handling.
27 *
28 * The older chips had a separate interface for programming plane related
29 * registers; newer ones are much simpler and we can use the new DRM plane
30 * support.
31 */
760285e7 32#include <drm/drmP.h>
714244e2 33#include <drm/drm_atomic_helper.h>
760285e7
DH
34#include <drm/drm_crtc.h>
35#include <drm/drm_fourcc.h>
1731693a 36#include <drm/drm_rect.h>
c331879c 37#include <drm/drm_atomic.h>
ea2c67bb 38#include <drm/drm_plane_helper.h>
b840d907 39#include "intel_drv.h"
5d723d7a 40#include "intel_frontbuffer.h"
760285e7 41#include <drm/i915_drm.h>
b840d907
JB
42#include "i915_drv.h"
43
dfd2e9ab
VS
44int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
45 int usecs)
8d7849db
VS
46{
47 /* paranoia */
5e7234c9 48 if (!adjusted_mode->crtc_htotal)
8d7849db
VS
49 return 1;
50
5e7234c9
VS
51 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
52 1000 * adjusted_mode->crtc_htotal);
8d7849db
VS
53}
54
69208c9e
SV
55/* FIXME: We should instead only take spinlocks once for the entire update
56 * instead of once per mmio. */
57#if IS_ENABLED(CONFIG_PROVE_LOCKING)
58#define VBLANK_EVASION_TIME_US 250
59#else
e1edbd44 60#define VBLANK_EVASION_TIME_US 100
69208c9e 61#endif
e1edbd44 62
26ff2762
ACO
63/**
64 * intel_pipe_update_start() - start update of a set of display registers
d3a8fb32 65 * @new_crtc_state: the new crtc state
26ff2762
ACO
66 *
67 * Mark the start of an update to pipe registers that should be updated
68 * atomically regarding vblank. If the next vblank will happens within
69 * the next 100 us, this function waits until the vblank passes.
70 *
71 * After a successful call to this function, interrupts will be disabled
72 * until a subsequent call to intel_pipe_update_end(). That is done to
d3a8fb32 73 * avoid random delays.
26ff2762 74 */
d3a8fb32 75void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
8d7849db 76{
d3a8fb32 77 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
ec1b4ee2 78 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
d3a8fb32 79 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
8d7849db
VS
80 long timeout = msecs_to_jiffies_timeout(1);
81 int scanline, min, max, vblank_start;
210871b6 82 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
ec1b4ee2 83 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
d3a8fb32 84 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
8d7849db 85 DEFINE_WAIT(wait);
63ec132d 86 u32 psr_status;
8d7849db 87
124abe07
VS
88 vblank_start = adjusted_mode->crtc_vblank_start;
89 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
8d7849db
VS
90 vblank_start = DIV_ROUND_UP(vblank_start, 2);
91
92 /* FIXME needs to be calibrated sensibly */
e1edbd44
ML
93 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
94 VBLANK_EVASION_TIME_US);
8d7849db
VS
95 max = vblank_start - 1;
96
97 if (min <= 0 || max <= 0)
a6089879 98 goto irq_disable;
8d7849db 99
1e3feefd 100 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
a6089879
TV
101 goto irq_disable;
102
103 /*
104 * Wait for psr to idle out after enabling the VBL interrupts
105 * VBL interrupts will start the PSR exit and prevent a PSR
106 * re-entry as well.
107 */
63ec132d
DP
108 if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
109 DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
110 psr_status);
a6089879
TV
111
112 local_irq_disable();
8d7849db 113
d637ce3f
JB
114 crtc->debug.min_vbl = min;
115 crtc->debug.max_vbl = max;
116 trace_i915_pipe_update_start(crtc);
25ef284a 117
8d7849db
VS
118 for (;;) {
119 /*
120 * prepare_to_wait() has a memory barrier, which guarantees
121 * other CPUs can see the task state update by the time we
122 * read the scanline.
123 */
210871b6 124 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
8d7849db
VS
125
126 scanline = intel_get_crtc_scanline(crtc);
127 if (scanline < min || scanline > max)
128 break;
129
9ba59b79 130 if (!timeout) {
8d7849db
VS
131 DRM_ERROR("Potential atomic update failure on pipe %c\n",
132 pipe_name(crtc->pipe));
133 break;
134 }
135
136 local_irq_enable();
137
138 timeout = schedule_timeout(timeout);
139
140 local_irq_disable();
141 }
142
210871b6 143 finish_wait(wq, &wait);
8d7849db 144
1e3feefd 145 drm_crtc_vblank_put(&crtc->base);
8d7849db 146
ec1b4ee2
VS
147 /*
148 * On VLV/CHV DSI the scanline counter would appear to
149 * increment approx. 1/3 of a scanline before start of vblank.
150 * The registers still get latched at start of vblank however.
151 * This means we must not write any registers on the first
152 * line of vblank (since not the whole line is actually in
153 * vblank). And unfortunately we can't use the interrupt to
154 * wait here since it will fire too soon. We could use the
155 * frame start interrupt instead since it will fire after the
156 * critical scanline, but that would require more changes
157 * in the interrupt code. So for now we'll just do the nasty
158 * thing and poll for the bad scanline to pass us by.
159 *
160 * FIXME figure out if BXT+ DSI suffers from this as well
161 */
162 while (need_vlv_dsi_wa && scanline == vblank_start)
163 scanline = intel_get_crtc_scanline(crtc);
164
eb120ef6
JB
165 crtc->debug.scanline_start = scanline;
166 crtc->debug.start_vbl_time = ktime_get();
a2991414 167 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
8d7849db 168
d637ce3f 169 trace_i915_pipe_update_vblank_evaded(crtc);
a6089879
TV
170 return;
171
172irq_disable:
173 local_irq_disable();
8d7849db
VS
174}
175
26ff2762
ACO
176/**
177 * intel_pipe_update_end() - end update of a set of display registers
d3a8fb32 178 * @new_crtc_state: the new crtc state
26ff2762
ACO
179 *
180 * Mark the end of an update started with intel_pipe_update_start(). This
181 * re-enables interrupts and verifies the update was actually completed
d3a8fb32 182 * before a vblank.
26ff2762 183 */
d3a8fb32 184void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
8d7849db 185{
d3a8fb32 186 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
8d7849db 187 enum pipe pipe = crtc->pipe;
eb120ef6 188 int scanline_end = intel_get_crtc_scanline(crtc);
a2991414 189 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
85a62bf9 190 ktime_t end_vbl_time = ktime_get();
a94f2b92 191 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
8d7849db 192
d637ce3f 193 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
25ef284a 194
1f7528c4
SV
195 /* We're still in the vblank-evade critical section, this can't race.
196 * Would be slightly nice to just grab the vblank count and arm the
197 * event outside of the critical section - the spinlock might spin for a
198 * while ... */
d3a8fb32 199 if (new_crtc_state->base.event) {
1f7528c4
SV
200 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
201
202 spin_lock(&crtc->base.dev->event_lock);
d3a8fb32 203 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
1f7528c4
SV
204 spin_unlock(&crtc->base.dev->event_lock);
205
d3a8fb32 206 new_crtc_state->base.event = NULL;
1f7528c4
SV
207 }
208
8d7849db
VS
209 local_irq_enable();
210
a94f2b92
BN
211 if (intel_vgpu_active(dev_priv))
212 return;
213
eb120ef6
JB
214 if (crtc->debug.start_vbl_count &&
215 crtc->debug.start_vbl_count != end_vbl_count) {
216 DRM_ERROR("Atomic update failure on pipe %c (start=%u end=%u) time %lld us, min %d, max %d, scanline start %d, end %d\n",
217 pipe_name(pipe), crtc->debug.start_vbl_count,
218 end_vbl_count,
219 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
220 crtc->debug.min_vbl, crtc->debug.max_vbl,
221 crtc->debug.scanline_start, scanline_end);
7b8cd336
VS
222 }
223#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
224 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
225 VBLANK_EVASION_TIME_US)
e1edbd44
ML
226 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
227 pipe_name(pipe),
228 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
229 VBLANK_EVASION_TIME_US);
7b8cd336 230#endif
8d7849db
VS
231}
232
4e0b83a5
VS
233int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
234{
235 const struct drm_framebuffer *fb = plane_state->base.fb;
236 struct drm_rect *src = &plane_state->base.src;
237 u32 src_x, src_y, src_w, src_h;
238
239 /*
240 * Hardware doesn't handle subpixel coordinates.
241 * Adjust to (macro)pixel boundary, but be careful not to
242 * increase the source viewport size, because that could
243 * push the downscaling factor out of bounds.
244 */
245 src_x = src->x1 >> 16;
246 src_w = drm_rect_width(src) >> 16;
247 src_y = src->y1 >> 16;
248 src_h = drm_rect_height(src) >> 16;
249
250 src->x1 = src_x << 16;
251 src->x2 = (src_x + src_w) << 16;
252 src->y1 = src_y << 16;
253 src->y2 = (src_y + src_h) << 16;
254
255 if (fb->format->is_yuv &&
256 fb->format->format != DRM_FORMAT_NV12 &&
257 (src_x & 1 || src_w & 1)) {
258 DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
259 src_x, src_w);
260 return -EINVAL;
261 }
262
263 return 0;
264}
265
ddd5713d
VS
266unsigned int
267skl_plane_max_stride(struct intel_plane *plane,
268 u32 pixel_format, u64 modifier,
269 unsigned int rotation)
270{
271 int cpp = drm_format_plane_cpp(pixel_format, 0);
272
273 /*
274 * "The stride in bytes must not exceed the
275 * of the size of 8K pixels and 32K bytes."
276 */
277 if (drm_rotation_90_or_270(rotation))
278 return min(8192, 32768 / cpp);
279 else
280 return min(8192 * cpp, 32768);
281}
282
9a8cc576 283void
282dbf9b 284skl_update_plane(struct intel_plane *plane,
2fde1391
ML
285 const struct intel_crtc_state *crtc_state,
286 const struct intel_plane_state *plane_state)
dc2a41b4 287{
282dbf9b
VS
288 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
289 const struct drm_framebuffer *fb = plane_state->base.fb;
290 enum plane_id plane_id = plane->id;
291 enum pipe pipe = plane->pipe;
a0864d59 292 u32 plane_ctl = plane_state->ctl;
2fde1391 293 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
c11ada07 294 u32 surf_addr = plane_state->color_plane[0].offset;
df79cf44
VS
295 u32 stride = skl_plane_stride(plane_state, 0);
296 u32 aux_stride = skl_plane_stride(plane_state, 1);
936e71e3
VS
297 int crtc_x = plane_state->base.dst.x1;
298 int crtc_y = plane_state->base.dst.y1;
299 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
300 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
c11ada07
VS
301 uint32_t x = plane_state->color_plane[0].x;
302 uint32_t y = plane_state->color_plane[0].y;
936e71e3
VS
303 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
304 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
dd584fc0 305 unsigned long irqflags;
dc2a41b4 306
6687c906
VS
307 /* Sizes are 0 based */
308 src_w--;
309 src_h--;
310 crtc_w--;
311 crtc_h--;
312
dd584fc0
VS
313 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
314
4036c78c 315 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
dd584fc0 316 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
4036c78c 317 plane_state->color_ctl);
38f24f21 318
78587de2 319 if (key->flags) {
dd584fc0
VS
320 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
321 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
322 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
78587de2
VS
323 }
324
dd584fc0
VS
325 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
326 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
327 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
2e2adb05 328 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
c11ada07 329 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
2e2adb05 330 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
c11ada07
VS
331 (plane_state->color_plane[1].y << 16) |
332 plane_state->color_plane[1].x);
c331879c
CK
333
334 /* program plane scaler */
2fde1391 335 if (plane_state->scaler_id >= 0) {
2fde1391 336 int scaler_id = plane_state->scaler_id;
0a59952b
VS
337 const struct intel_scaler *scaler =
338 &crtc_state->scaler_state.scalers[scaler_id];
339 u16 y_hphase, uv_rgb_hphase;
340 u16 y_vphase, uv_rgb_vphase;
341
342 /* TODO: handle sub-pixel coordinates */
343 if (fb->format->format == DRM_FORMAT_NV12) {
344 y_hphase = skl_scaler_calc_phase(1, false);
345 y_vphase = skl_scaler_calc_phase(1, false);
346
347 /* MPEG2 chroma siting convention */
348 uv_rgb_hphase = skl_scaler_calc_phase(2, true);
349 uv_rgb_vphase = skl_scaler_calc_phase(2, false);
350 } else {
351 /* not used */
352 y_hphase = 0;
353 y_vphase = 0;
c331879c 354
0a59952b
VS
355 uv_rgb_hphase = skl_scaler_calc_phase(1, false);
356 uv_rgb_vphase = skl_scaler_calc_phase(1, false);
357 }
7494bcdc 358
dd584fc0
VS
359 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
360 PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
361 I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
0a59952b
VS
362 I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
363 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
364 I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
365 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
dd584fc0
VS
366 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
367 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
368 ((crtc_w + 1) << 16)|(crtc_h + 1));
c331879c 369
dd584fc0 370 I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
c331879c 371 } else {
dd584fc0 372 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
c331879c
CK
373 }
374
dd584fc0
VS
375 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
376 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
377 intel_plane_ggtt_offset(plane_state) + surf_addr);
378 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
379
380 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
dc2a41b4
DL
381}
382
779d4d8f 383void
282dbf9b 384skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
dc2a41b4 385{
282dbf9b
VS
386 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
387 enum plane_id plane_id = plane->id;
388 enum pipe pipe = plane->pipe;
dd584fc0
VS
389 unsigned long irqflags;
390
391 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
dc2a41b4 392
dd584fc0 393 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
dc2a41b4 394
dd584fc0
VS
395 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
396 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
397
398 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
dc2a41b4
DL
399}
400
51f5a096 401bool
eade6c89
VS
402skl_plane_get_hw_state(struct intel_plane *plane,
403 enum pipe *pipe)
51f5a096
VS
404{
405 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
406 enum intel_display_power_domain power_domain;
407 enum plane_id plane_id = plane->id;
51f5a096
VS
408 bool ret;
409
eade6c89 410 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
51f5a096
VS
411 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
412 return false;
413
eade6c89
VS
414 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
415
416 *pipe = plane->pipe;
51f5a096
VS
417
418 intel_display_power_put(dev_priv, power_domain);
419
420 return ret;
421}
422
6ca2aeb2 423static void
5deae919 424chv_update_csc(const struct intel_plane_state *plane_state)
6ca2aeb2 425{
5deae919 426 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
282dbf9b 427 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
5deae919 428 const struct drm_framebuffer *fb = plane_state->base.fb;
282dbf9b 429 enum plane_id plane_id = plane->id;
6ca2aeb2 430 /*
b0f5c0ba
VS
431 * |r| | c0 c1 c2 | |cr|
432 * |g| = | c3 c4 c5 | x |y |
433 * |b| | c6 c7 c8 | |cb|
6ca2aeb2 434 *
b0f5c0ba 435 * Coefficients are s3.12.
6ca2aeb2 436 *
b0f5c0ba
VS
437 * Cb and Cr apparently come in as signed already, and
438 * we always get full range data in on account of CLRC0/1.
6ca2aeb2 439 */
b0f5c0ba
VS
440 static const s16 csc_matrix[][9] = {
441 /* BT.601 full range YCbCr -> full range RGB */
442 [DRM_COLOR_YCBCR_BT601] = {
443 5743, 4096, 0,
444 -2925, 4096, -1410,
445 0, 4096, 7258,
446 },
447 /* BT.709 full range YCbCr -> full range RGB */
448 [DRM_COLOR_YCBCR_BT709] = {
449 6450, 4096, 0,
450 -1917, 4096, -767,
451 0, 4096, 7601,
452 },
453 };
454 const s16 *csc = csc_matrix[plane_state->base.color_encoding];
6ca2aeb2
VS
455
456 /* Seems RGB data bypasses the CSC always */
9bace659 457 if (!fb->format->is_yuv)
6ca2aeb2
VS
458 return;
459
5deae919 460 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
dd584fc0
VS
461 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
462 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
463
b0f5c0ba
VS
464 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
465 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
466 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
467 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
468 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
dd584fc0 469
5deae919
VS
470 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
471 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
472 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
dd584fc0
VS
473
474 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
475 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
476 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
6ca2aeb2
VS
477}
478
5deae919
VS
479#define SIN_0 0
480#define COS_0 1
481
482static void
483vlv_update_clrc(const struct intel_plane_state *plane_state)
484{
485 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
486 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
487 const struct drm_framebuffer *fb = plane_state->base.fb;
488 enum pipe pipe = plane->pipe;
489 enum plane_id plane_id = plane->id;
490 int contrast, brightness, sh_scale, sh_sin, sh_cos;
491
9bace659 492 if (fb->format->is_yuv &&
c8624ede 493 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
5deae919
VS
494 /*
495 * Expand limited range to full range:
496 * Contrast is applied first and is used to expand Y range.
497 * Brightness is applied second and is used to remove the
498 * offset from Y. Saturation/hue is used to expand CbCr range.
499 */
500 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
501 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
502 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
503 sh_sin = SIN_0 * sh_scale;
504 sh_cos = COS_0 * sh_scale;
505 } else {
506 /* Pass-through everything. */
507 contrast = 1 << 6;
508 brightness = 0;
509 sh_scale = 1 << 7;
510 sh_sin = SIN_0 * sh_scale;
511 sh_cos = COS_0 * sh_scale;
512 }
513
514 /* FIXME these register are single buffered :( */
515 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
516 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
517 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
518 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
519}
520
96ef6854
VS
521static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
522 const struct intel_plane_state *plane_state)
7f1f3851 523{
96ef6854 524 const struct drm_framebuffer *fb = plane_state->base.fb;
11df4d95 525 unsigned int rotation = plane_state->base.rotation;
2fde1391 526 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
96ef6854 527 u32 sprctl;
7f1f3851 528
96ef6854 529 sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
7f1f3851 530
438b74a5 531 switch (fb->format->format) {
7f1f3851
JB
532 case DRM_FORMAT_YUYV:
533 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
534 break;
535 case DRM_FORMAT_YVYU:
536 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
537 break;
538 case DRM_FORMAT_UYVY:
539 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
540 break;
541 case DRM_FORMAT_VYUY:
542 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
543 break;
544 case DRM_FORMAT_RGB565:
545 sprctl |= SP_FORMAT_BGR565;
546 break;
547 case DRM_FORMAT_XRGB8888:
548 sprctl |= SP_FORMAT_BGRX8888;
549 break;
550 case DRM_FORMAT_ARGB8888:
551 sprctl |= SP_FORMAT_BGRA8888;
552 break;
553 case DRM_FORMAT_XBGR2101010:
554 sprctl |= SP_FORMAT_RGBX1010102;
555 break;
556 case DRM_FORMAT_ABGR2101010:
557 sprctl |= SP_FORMAT_RGBA1010102;
558 break;
559 case DRM_FORMAT_XBGR8888:
560 sprctl |= SP_FORMAT_RGBX8888;
561 break;
562 case DRM_FORMAT_ABGR8888:
563 sprctl |= SP_FORMAT_RGBA8888;
564 break;
565 default:
96ef6854
VS
566 MISSING_CASE(fb->format->format);
567 return 0;
7f1f3851
JB
568 }
569
b0f5c0ba
VS
570 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
571 sprctl |= SP_YUV_FORMAT_BT709;
572
bae781b2 573 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
7f1f3851
JB
574 sprctl |= SP_TILED;
575
c2c446ad 576 if (rotation & DRM_MODE_ROTATE_180)
df0cd455
VS
577 sprctl |= SP_ROTATE_180;
578
c2c446ad 579 if (rotation & DRM_MODE_REFLECT_X)
4ea7be2b
VS
580 sprctl |= SP_MIRROR;
581
78587de2
VS
582 if (key->flags & I915_SET_COLORKEY_SOURCE)
583 sprctl |= SP_SOURCE_KEY;
584
96ef6854
VS
585 return sprctl;
586}
587
588static void
282dbf9b 589vlv_update_plane(struct intel_plane *plane,
96ef6854
VS
590 const struct intel_crtc_state *crtc_state,
591 const struct intel_plane_state *plane_state)
592{
282dbf9b
VS
593 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
594 const struct drm_framebuffer *fb = plane_state->base.fb;
595 enum pipe pipe = plane->pipe;
596 enum plane_id plane_id = plane->id;
a0864d59 597 u32 sprctl = plane_state->ctl;
c11ada07 598 u32 sprsurf_offset = plane_state->color_plane[0].offset;
f9407ae1 599 u32 linear_offset;
96ef6854
VS
600 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
601 int crtc_x = plane_state->base.dst.x1;
602 int crtc_y = plane_state->base.dst.y1;
603 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
604 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
c11ada07
VS
605 uint32_t x = plane_state->color_plane[0].x;
606 uint32_t y = plane_state->color_plane[0].y;
96ef6854
VS
607 unsigned long irqflags;
608
7f1f3851 609 /* Sizes are 0 based */
7f1f3851
JB
610 crtc_w--;
611 crtc_h--;
612
2949056c 613 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
6687c906 614
dd584fc0
VS
615 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
616
5deae919
VS
617 vlv_update_clrc(plane_state);
618
78587de2 619 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
5deae919 620 chv_update_csc(plane_state);
78587de2 621
47ecbb20 622 if (key->flags) {
dd584fc0
VS
623 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
624 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
625 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
47ecbb20 626 }
df79cf44
VS
627 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
628 plane_state->color_plane[0].stride);
dd584fc0 629 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
ca6ad025 630
bae781b2 631 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dd584fc0 632 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
7f1f3851 633 else
dd584fc0 634 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
7f1f3851 635
dd584fc0 636 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
c14b0485 637
dd584fc0
VS
638 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
639 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
640 I915_WRITE_FW(SPSURF(pipe, plane_id),
641 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
642 POSTING_READ_FW(SPSURF(pipe, plane_id));
643
644 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
7f1f3851
JB
645}
646
647static void
282dbf9b 648vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
7f1f3851 649{
282dbf9b
VS
650 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
651 enum pipe pipe = plane->pipe;
652 enum plane_id plane_id = plane->id;
dd584fc0
VS
653 unsigned long irqflags;
654
655 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
7f1f3851 656
dd584fc0 657 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
48fe4691 658
dd584fc0
VS
659 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
660 POSTING_READ_FW(SPSURF(pipe, plane_id));
661
662 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
7f1f3851
JB
663}
664
51f5a096 665static bool
eade6c89
VS
666vlv_plane_get_hw_state(struct intel_plane *plane,
667 enum pipe *pipe)
51f5a096
VS
668{
669 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
670 enum intel_display_power_domain power_domain;
671 enum plane_id plane_id = plane->id;
51f5a096
VS
672 bool ret;
673
eade6c89 674 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
51f5a096
VS
675 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
676 return false;
677
eade6c89
VS
678 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
679
680 *pipe = plane->pipe;
51f5a096
VS
681
682 intel_display_power_put(dev_priv, power_domain);
683
684 return ret;
685}
686
45dea7b0
VS
687static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
688 const struct intel_plane_state *plane_state)
b840d907 689{
45dea7b0
VS
690 struct drm_i915_private *dev_priv =
691 to_i915(plane_state->base.plane->dev);
692 const struct drm_framebuffer *fb = plane_state->base.fb;
8d0deca8 693 unsigned int rotation = plane_state->base.rotation;
2fde1391 694 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
45dea7b0
VS
695 u32 sprctl;
696
697 sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
b840d907 698
45dea7b0
VS
699 if (IS_IVYBRIDGE(dev_priv))
700 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
701
702 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
703 sprctl |= SPRITE_PIPE_CSC_ENABLE;
b840d907 704
438b74a5 705 switch (fb->format->format) {
b840d907 706 case DRM_FORMAT_XBGR8888:
5ee36913 707 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
b840d907
JB
708 break;
709 case DRM_FORMAT_XRGB8888:
5ee36913 710 sprctl |= SPRITE_FORMAT_RGBX888;
b840d907
JB
711 break;
712 case DRM_FORMAT_YUYV:
713 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
b840d907
JB
714 break;
715 case DRM_FORMAT_YVYU:
716 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
b840d907
JB
717 break;
718 case DRM_FORMAT_UYVY:
719 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
b840d907
JB
720 break;
721 case DRM_FORMAT_VYUY:
722 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
b840d907
JB
723 break;
724 default:
45dea7b0
VS
725 MISSING_CASE(fb->format->format);
726 return 0;
b840d907
JB
727 }
728
b0f5c0ba
VS
729 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
730 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
731
c8624ede
VS
732 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
733 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
734
bae781b2 735 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
b840d907
JB
736 sprctl |= SPRITE_TILED;
737
c2c446ad 738 if (rotation & DRM_MODE_ROTATE_180)
df0cd455
VS
739 sprctl |= SPRITE_ROTATE_180;
740
78587de2
VS
741 if (key->flags & I915_SET_COLORKEY_DESTINATION)
742 sprctl |= SPRITE_DEST_KEY;
743 else if (key->flags & I915_SET_COLORKEY_SOURCE)
744 sprctl |= SPRITE_SOURCE_KEY;
745
45dea7b0
VS
746 return sprctl;
747}
748
749static void
282dbf9b 750ivb_update_plane(struct intel_plane *plane,
45dea7b0
VS
751 const struct intel_crtc_state *crtc_state,
752 const struct intel_plane_state *plane_state)
753{
282dbf9b
VS
754 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
755 const struct drm_framebuffer *fb = plane_state->base.fb;
756 enum pipe pipe = plane->pipe;
a0864d59 757 u32 sprctl = plane_state->ctl, sprscale = 0;
c11ada07 758 u32 sprsurf_offset = plane_state->color_plane[0].offset;
f9407ae1 759 u32 linear_offset;
45dea7b0
VS
760 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
761 int crtc_x = plane_state->base.dst.x1;
762 int crtc_y = plane_state->base.dst.y1;
763 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
764 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
c11ada07
VS
765 uint32_t x = plane_state->color_plane[0].x;
766 uint32_t y = plane_state->color_plane[0].y;
45dea7b0
VS
767 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
768 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
769 unsigned long irqflags;
770
b840d907
JB
771 /* Sizes are 0 based */
772 src_w--;
773 src_h--;
774 crtc_w--;
775 crtc_h--;
776
8553c18e 777 if (crtc_w != src_w || crtc_h != src_h)
b840d907 778 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
b840d907 779
2949056c 780 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
6687c906 781
dd584fc0
VS
782 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
783
47ecbb20 784 if (key->flags) {
dd584fc0
VS
785 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
786 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
787 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
47ecbb20
VS
788 }
789
df79cf44 790 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
dd584fc0 791 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
ca6ad025 792
5a35e99e
DL
793 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
794 * register */
8652744b 795 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
dd584fc0 796 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
bae781b2 797 else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dd584fc0 798 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
5a35e99e 799 else
dd584fc0 800 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
c54173a8 801
dd584fc0 802 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
fd6e3c6c 803 if (IS_IVYBRIDGE(dev_priv))
dd584fc0
VS
804 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
805 I915_WRITE_FW(SPRCTL(pipe), sprctl);
806 I915_WRITE_FW(SPRSURF(pipe),
807 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
808 POSTING_READ_FW(SPRSURF(pipe));
809
810 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
b840d907
JB
811}
812
813static void
282dbf9b 814ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
b840d907 815{
282dbf9b
VS
816 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
817 enum pipe pipe = plane->pipe;
dd584fc0
VS
818 unsigned long irqflags;
819
820 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
b840d907 821
dd584fc0 822 I915_WRITE_FW(SPRCTL(pipe), 0);
b840d907 823 /* Can't leave the scaler enabled... */
fd6e3c6c 824 if (IS_IVYBRIDGE(dev_priv))
dd584fc0 825 I915_WRITE_FW(SPRSCALE(pipe), 0);
5b633d6b 826
dd584fc0
VS
827 I915_WRITE_FW(SPRSURF(pipe), 0);
828 POSTING_READ_FW(SPRSURF(pipe));
829
830 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
b840d907
JB
831}
832
51f5a096 833static bool
eade6c89
VS
834ivb_plane_get_hw_state(struct intel_plane *plane,
835 enum pipe *pipe)
51f5a096
VS
836{
837 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
838 enum intel_display_power_domain power_domain;
51f5a096
VS
839 bool ret;
840
eade6c89 841 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
51f5a096
VS
842 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
843 return false;
844
eade6c89
VS
845 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
846
847 *pipe = plane->pipe;
51f5a096
VS
848
849 intel_display_power_put(dev_priv, power_domain);
850
851 return ret;
852}
853
ddd5713d
VS
854static unsigned int
855g4x_sprite_max_stride(struct intel_plane *plane,
856 u32 pixel_format, u64 modifier,
857 unsigned int rotation)
858{
859 return 16384;
860}
861
ab33081a 862static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
0a375147 863 const struct intel_plane_state *plane_state)
b840d907 864{
0a375147
VS
865 struct drm_i915_private *dev_priv =
866 to_i915(plane_state->base.plane->dev);
867 const struct drm_framebuffer *fb = plane_state->base.fb;
8d0deca8 868 unsigned int rotation = plane_state->base.rotation;
2fde1391 869 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
0a375147
VS
870 u32 dvscntr;
871
872 dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
b840d907 873
0a375147
VS
874 if (IS_GEN6(dev_priv))
875 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
b840d907 876
438b74a5 877 switch (fb->format->format) {
b840d907 878 case DRM_FORMAT_XBGR8888:
ab2f9df1 879 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
b840d907
JB
880 break;
881 case DRM_FORMAT_XRGB8888:
ab2f9df1 882 dvscntr |= DVS_FORMAT_RGBX888;
b840d907
JB
883 break;
884 case DRM_FORMAT_YUYV:
885 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
b840d907
JB
886 break;
887 case DRM_FORMAT_YVYU:
888 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
b840d907
JB
889 break;
890 case DRM_FORMAT_UYVY:
891 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
b840d907
JB
892 break;
893 case DRM_FORMAT_VYUY:
894 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
b840d907
JB
895 break;
896 default:
0a375147
VS
897 MISSING_CASE(fb->format->format);
898 return 0;
b840d907
JB
899 }
900
b0f5c0ba
VS
901 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
902 dvscntr |= DVS_YUV_FORMAT_BT709;
903
c8624ede
VS
904 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
905 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
906
bae781b2 907 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
b840d907
JB
908 dvscntr |= DVS_TILED;
909
c2c446ad 910 if (rotation & DRM_MODE_ROTATE_180)
df0cd455
VS
911 dvscntr |= DVS_ROTATE_180;
912
78587de2
VS
913 if (key->flags & I915_SET_COLORKEY_DESTINATION)
914 dvscntr |= DVS_DEST_KEY;
915 else if (key->flags & I915_SET_COLORKEY_SOURCE)
916 dvscntr |= DVS_SOURCE_KEY;
917
0a375147
VS
918 return dvscntr;
919}
920
921static void
282dbf9b 922g4x_update_plane(struct intel_plane *plane,
0a375147
VS
923 const struct intel_crtc_state *crtc_state,
924 const struct intel_plane_state *plane_state)
925{
282dbf9b
VS
926 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
927 const struct drm_framebuffer *fb = plane_state->base.fb;
928 enum pipe pipe = plane->pipe;
f9407ae1 929 u32 dvscntr = plane_state->ctl, dvsscale = 0;
c11ada07 930 u32 dvssurf_offset = plane_state->color_plane[0].offset;
f9407ae1 931 u32 linear_offset;
0a375147
VS
932 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
933 int crtc_x = plane_state->base.dst.x1;
934 int crtc_y = plane_state->base.dst.y1;
935 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
936 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
c11ada07
VS
937 uint32_t x = plane_state->color_plane[0].x;
938 uint32_t y = plane_state->color_plane[0].y;
0a375147
VS
939 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
940 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
941 unsigned long irqflags;
942
b840d907
JB
943 /* Sizes are 0 based */
944 src_w--;
945 src_h--;
946 crtc_w--;
947 crtc_h--;
948
8368f014 949 if (crtc_w != src_w || crtc_h != src_h)
b840d907
JB
950 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
951
2949056c 952 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
6687c906 953
dd584fc0
VS
954 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
955
47ecbb20 956 if (key->flags) {
dd584fc0
VS
957 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
958 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
959 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
47ecbb20
VS
960 }
961
df79cf44 962 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
dd584fc0 963 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
ca6ad025 964
bae781b2 965 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
dd584fc0 966 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
5a35e99e 967 else
dd584fc0
VS
968 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
969
970 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
971 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
972 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
973 I915_WRITE_FW(DVSSURF(pipe),
974 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
975 POSTING_READ_FW(DVSSURF(pipe));
976
977 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
b840d907
JB
978}
979
980static void
282dbf9b 981g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
b840d907 982{
282dbf9b
VS
983 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
984 enum pipe pipe = plane->pipe;
dd584fc0 985 unsigned long irqflags;
b840d907 986
dd584fc0
VS
987 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
988
989 I915_WRITE_FW(DVSCNTR(pipe), 0);
b840d907 990 /* Disable the scaler */
dd584fc0
VS
991 I915_WRITE_FW(DVSSCALE(pipe), 0);
992
993 I915_WRITE_FW(DVSSURF(pipe), 0);
994 POSTING_READ_FW(DVSSURF(pipe));
48fe4691 995
dd584fc0 996 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
b840d907
JB
997}
998
51f5a096 999static bool
eade6c89
VS
1000g4x_plane_get_hw_state(struct intel_plane *plane,
1001 enum pipe *pipe)
51f5a096
VS
1002{
1003 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1004 enum intel_display_power_domain power_domain;
51f5a096
VS
1005 bool ret;
1006
eade6c89 1007 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
51f5a096
VS
1008 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
1009 return false;
1010
eade6c89
VS
1011 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1012
1013 *pipe = plane->pipe;
51f5a096
VS
1014
1015 intel_display_power_put(dev_priv, power_domain);
1016
1017 return ret;
1018}
1019
b840d907 1020static int
4e0b83a5
VS
1021g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1022 struct intel_plane_state *plane_state)
b840d907 1023{
4e0b83a5
VS
1024 const struct drm_framebuffer *fb = plane_state->base.fb;
1025 const struct drm_rect *src = &plane_state->base.src;
1026 const struct drm_rect *dst = &plane_state->base.dst;
1027 int src_x, src_y, src_w, src_h, crtc_w, crtc_h;
1028 const struct drm_display_mode *adjusted_mode =
1029 &crtc_state->base.adjusted_mode;
1030 unsigned int cpp = fb->format->cpp[0];
1031 unsigned int width_bytes;
1032 int min_width, min_height;
1033
1034 crtc_w = drm_rect_width(dst);
1035 crtc_h = drm_rect_height(dst);
1036
1037 src_x = src->x1 >> 16;
1038 src_y = src->y1 >> 16;
1039 src_w = drm_rect_width(src) >> 16;
1040 src_h = drm_rect_height(src) >> 16;
1041
1042 if (src_w == crtc_w && src_h == crtc_h)
da20eabd 1043 return 0;
4e0b83a5
VS
1044
1045 min_width = 3;
1046
1047 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1048 if (src_h & 1) {
1049 DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1050 return -EINVAL;
1051 }
1052 min_height = 6;
1053 } else {
1054 min_height = 3;
cf4c7c12 1055 }
5e1bac2f 1056
4e0b83a5
VS
1057 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1058
1059 if (src_w < min_width || src_h < min_height ||
1060 src_w > 2048 || src_h > 2048) {
1061 DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1062 src_w, src_h, min_width, min_height, 2048, 2048);
b840d907 1063 return -EINVAL;
1731693a 1064 }
b840d907 1065
4e0b83a5
VS
1066 if (width_bytes > 4096) {
1067 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1068 width_bytes, 4096);
b840d907 1069 return -EINVAL;
1731693a 1070 }
b840d907 1071
4e0b83a5
VS
1072 if (width_bytes > 4096 || fb->pitches[0] > 4096) {
1073 DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1074 fb->pitches[0], 4096);
1075 return -EINVAL;
1076 }
1077
1078 return 0;
1079}
1080
1081static int
1082g4x_sprite_check(struct intel_crtc_state *crtc_state,
1083 struct intel_plane_state *plane_state)
1084{
1085 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1086 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1087 int max_scale, min_scale;
1088 int ret;
1089
1090 if (INTEL_GEN(dev_priv) < 7) {
1091 min_scale = 1;
1092 max_scale = 16 << 16;
1093 } else if (IS_IVYBRIDGE(dev_priv)) {
1094 min_scale = 1;
1095 max_scale = 2 << 16;
225c228a 1096 } else {
4e0b83a5
VS
1097 min_scale = DRM_PLANE_HELPER_NO_SCALING;
1098 max_scale = DRM_PLANE_HELPER_NO_SCALING;
225c228a
CK
1099 }
1100
4e0b83a5 1101 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
9c1659eb
ML
1102 &crtc_state->base,
1103 min_scale, max_scale,
1104 true, true);
1105 if (ret)
1106 return ret;
2d354c34 1107
4e0b83a5
VS
1108 if (!plane_state->base.visible)
1109 return 0;
1731693a 1110
4e0b83a5
VS
1111 ret = intel_plane_check_src_coordinates(plane_state);
1112 if (ret)
1113 return ret;
1731693a 1114
4e0b83a5
VS
1115 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1116 if (ret)
1117 return ret;
1731693a 1118
4e0b83a5
VS
1119 ret = i9xx_check_plane_surface(plane_state);
1120 if (ret)
1121 return ret;
a0864d59 1122
4e0b83a5
VS
1123 if (INTEL_GEN(dev_priv) >= 7)
1124 plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1125 else
1126 plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
f9407ae1 1127
4e0b83a5
VS
1128 return 0;
1129}
f9407ae1 1130
4e0b83a5
VS
1131static int
1132vlv_sprite_check(struct intel_crtc_state *crtc_state,
1133 struct intel_plane_state *plane_state)
1134{
1135 int ret;
1136
1137 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1138 &crtc_state->base,
1139 DRM_PLANE_HELPER_NO_SCALING,
1140 DRM_PLANE_HELPER_NO_SCALING,
1141 true, true);
1142 if (ret)
1143 return ret;
1144
1145 if (!plane_state->base.visible)
1146 return 0;
1147
1148 ret = intel_plane_check_src_coordinates(plane_state);
1149 if (ret)
1150 return ret;
1151
1152 ret = i9xx_check_plane_surface(plane_state);
1153 if (ret)
1154 return ret;
1155
1156 plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
f9407ae1 1157
4e0b83a5
VS
1158 return 0;
1159}
1160
1161int skl_plane_check(struct intel_crtc_state *crtc_state,
1162 struct intel_plane_state *plane_state)
1163{
1164 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1165 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1166 int max_scale, min_scale;
1167 int ret;
1168
1169 /* use scaler when colorkey is not required */
1170 if (!plane_state->ckey.flags) {
1171 const struct drm_framebuffer *fb = plane_state->base.fb;
1172
1173 min_scale = 1;
1174 max_scale = skl_max_scale(crtc_state,
1175 fb ? fb->format->format : 0);
1176 } else {
1177 min_scale = DRM_PLANE_HELPER_NO_SCALING;
1178 max_scale = DRM_PLANE_HELPER_NO_SCALING;
b63a16f6
VS
1179 }
1180
4e0b83a5
VS
1181 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1182 &crtc_state->base,
1183 min_scale, max_scale,
1184 true, true);
1185 if (ret)
1186 return ret;
1187
1188 if (!plane_state->base.visible)
1189 return 0;
1190
1191 ret = intel_plane_check_src_coordinates(plane_state);
1192 if (ret)
1193 return ret;
1194
1195 ret = skl_check_plane_surface(crtc_state, plane_state);
1196 if (ret)
1197 return ret;
1198
1199 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1200
4036c78c 1201 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
4e0b83a5
VS
1202 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1203 plane_state);
4036c78c 1204
96d61a7f
GP
1205 return 0;
1206}
1207
672b3c4b
VS
1208static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1209{
1210 return INTEL_GEN(dev_priv) >= 9;
1211}
1212
1213static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1214 const struct drm_intel_sprite_colorkey *set)
1215{
1216 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1217 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1218 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1219
1220 *key = *set;
1221
1222 /*
1223 * We want src key enabled on the
1224 * sprite and not on the primary.
1225 */
1226 if (plane->id == PLANE_PRIMARY &&
1227 set->flags & I915_SET_COLORKEY_SOURCE)
1228 key->flags = 0;
1229
1230 /*
1231 * On SKL+ we want dst key enabled on
1232 * the primary and not on the sprite.
1233 */
1234 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1235 set->flags & I915_SET_COLORKEY_DESTINATION)
1236 key->flags = 0;
1237}
1238
6a20fe7b
VS
1239int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1240 struct drm_file *file_priv)
8ea30864 1241{
920a14b2 1242 struct drm_i915_private *dev_priv = to_i915(dev);
8ea30864 1243 struct drm_intel_sprite_colorkey *set = data;
8ea30864 1244 struct drm_plane *plane;
818ed961
ML
1245 struct drm_plane_state *plane_state;
1246 struct drm_atomic_state *state;
1247 struct drm_modeset_acquire_ctx ctx;
8ea30864
JB
1248 int ret = 0;
1249
6ec5bd34
VS
1250 /* ignore the pointless "none" flag */
1251 set->flags &= ~I915_SET_COLORKEY_NONE;
1252
89746e79
VS
1253 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1254 return -EINVAL;
1255
8ea30864
JB
1256 /* Make sure we don't try to enable both src & dest simultaneously */
1257 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1258 return -EINVAL;
1259
920a14b2 1260 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
47ecbb20
VS
1261 set->flags & I915_SET_COLORKEY_DESTINATION)
1262 return -EINVAL;
1263
418da172 1264 plane = drm_plane_find(dev, file_priv, set->plane_id);
818ed961
ML
1265 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1266 return -ENOENT;
8ea30864 1267
672b3c4b
VS
1268 /*
1269 * SKL+ only plane 2 can do destination keying against plane 1.
1270 * Also multiple planes can't do destination keying on the same
1271 * pipe simultaneously.
1272 */
1273 if (INTEL_GEN(dev_priv) >= 9 &&
1274 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1275 set->flags & I915_SET_COLORKEY_DESTINATION)
1276 return -EINVAL;
1277
818ed961 1278 drm_modeset_acquire_init(&ctx, 0);
6156a456 1279
818ed961
ML
1280 state = drm_atomic_state_alloc(plane->dev);
1281 if (!state) {
1282 ret = -ENOMEM;
1283 goto out;
6156a456 1284 }
818ed961
ML
1285 state->acquire_ctx = &ctx;
1286
1287 while (1) {
1288 plane_state = drm_atomic_get_plane_state(state, plane);
1289 ret = PTR_ERR_OR_ZERO(plane_state);
672b3c4b
VS
1290 if (!ret)
1291 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1292
1293 /*
1294 * On some platforms we have to configure
1295 * the dst colorkey on the primary plane.
1296 */
1297 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1298 struct intel_crtc *crtc =
1299 intel_get_crtc_for_pipe(dev_priv,
1300 to_intel_plane(plane)->pipe);
1301
1302 plane_state = drm_atomic_get_plane_state(state,
1303 crtc->base.primary);
1304 ret = PTR_ERR_OR_ZERO(plane_state);
1305 if (!ret)
1306 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
818ed961 1307 }
6156a456 1308
672b3c4b
VS
1309 if (!ret)
1310 ret = drm_atomic_commit(state);
1311
818ed961
ML
1312 if (ret != -EDEADLK)
1313 break;
8ea30864 1314
818ed961
ML
1315 drm_atomic_state_clear(state);
1316 drm_modeset_backoff(&ctx);
1317 }
8ea30864 1318
0853695c 1319 drm_atomic_state_put(state);
818ed961
ML
1320out:
1321 drm_modeset_drop_locks(&ctx);
1322 drm_modeset_acquire_fini(&ctx);
1323 return ret;
5e1bac2f
JB
1324}
1325
ab33081a 1326static const uint32_t g4x_plane_formats[] = {
d1686ae3
CW
1327 DRM_FORMAT_XRGB8888,
1328 DRM_FORMAT_YUYV,
1329 DRM_FORMAT_YVYU,
1330 DRM_FORMAT_UYVY,
1331 DRM_FORMAT_VYUY,
1332};
1333
714244e2
BW
1334static const uint64_t i9xx_plane_format_modifiers[] = {
1335 I915_FORMAT_MOD_X_TILED,
1336 DRM_FORMAT_MOD_LINEAR,
1337 DRM_FORMAT_MOD_INVALID
1338};
1339
dada2d53 1340static const uint32_t snb_plane_formats[] = {
b840d907
JB
1341 DRM_FORMAT_XBGR8888,
1342 DRM_FORMAT_XRGB8888,
1343 DRM_FORMAT_YUYV,
1344 DRM_FORMAT_YVYU,
1345 DRM_FORMAT_UYVY,
1346 DRM_FORMAT_VYUY,
1347};
1348
dada2d53 1349static const uint32_t vlv_plane_formats[] = {
7f1f3851
JB
1350 DRM_FORMAT_RGB565,
1351 DRM_FORMAT_ABGR8888,
1352 DRM_FORMAT_ARGB8888,
1353 DRM_FORMAT_XBGR8888,
1354 DRM_FORMAT_XRGB8888,
1355 DRM_FORMAT_XBGR2101010,
1356 DRM_FORMAT_ABGR2101010,
1357 DRM_FORMAT_YUYV,
1358 DRM_FORMAT_YVYU,
1359 DRM_FORMAT_UYVY,
1360 DRM_FORMAT_VYUY,
1361};
1362
dc2a41b4
DL
1363static uint32_t skl_plane_formats[] = {
1364 DRM_FORMAT_RGB565,
1365 DRM_FORMAT_ABGR8888,
1366 DRM_FORMAT_ARGB8888,
1367 DRM_FORMAT_XBGR8888,
1368 DRM_FORMAT_XRGB8888,
1369 DRM_FORMAT_YUYV,
1370 DRM_FORMAT_YVYU,
1371 DRM_FORMAT_UYVY,
1372 DRM_FORMAT_VYUY,
1373};
1374
429204f1
CK
1375static uint32_t skl_planar_formats[] = {
1376 DRM_FORMAT_RGB565,
1377 DRM_FORMAT_ABGR8888,
1378 DRM_FORMAT_ARGB8888,
1379 DRM_FORMAT_XBGR8888,
1380 DRM_FORMAT_XRGB8888,
1381 DRM_FORMAT_YUYV,
1382 DRM_FORMAT_YVYU,
1383 DRM_FORMAT_UYVY,
1384 DRM_FORMAT_VYUY,
1385 DRM_FORMAT_NV12,
1386};
1387
77064e2e
VS
1388static const uint64_t skl_plane_format_modifiers_noccs[] = {
1389 I915_FORMAT_MOD_Yf_TILED,
1390 I915_FORMAT_MOD_Y_TILED,
1391 I915_FORMAT_MOD_X_TILED,
1392 DRM_FORMAT_MOD_LINEAR,
1393 DRM_FORMAT_MOD_INVALID
1394};
1395
1396static const uint64_t skl_plane_format_modifiers_ccs[] = {
1397 I915_FORMAT_MOD_Yf_TILED_CCS,
1398 I915_FORMAT_MOD_Y_TILED_CCS,
74ac160b
VS
1399 I915_FORMAT_MOD_Yf_TILED,
1400 I915_FORMAT_MOD_Y_TILED,
714244e2
BW
1401 I915_FORMAT_MOD_X_TILED,
1402 DRM_FORMAT_MOD_LINEAR,
1403 DRM_FORMAT_MOD_INVALID
1404};
1405
a38189c5
VS
1406static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1407 u32 format, u64 modifier)
714244e2 1408{
a38189c5
VS
1409 switch (modifier) {
1410 case DRM_FORMAT_MOD_LINEAR:
1411 case I915_FORMAT_MOD_X_TILED:
1412 break;
1413 default:
1414 return false;
1415 }
1416
714244e2 1417 switch (format) {
714244e2
BW
1418 case DRM_FORMAT_XRGB8888:
1419 case DRM_FORMAT_YUYV:
1420 case DRM_FORMAT_YVYU:
1421 case DRM_FORMAT_UYVY:
1422 case DRM_FORMAT_VYUY:
1423 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1424 modifier == I915_FORMAT_MOD_X_TILED)
1425 return true;
1426 /* fall through */
1427 default:
1428 return false;
1429 }
1430}
1431
a38189c5
VS
1432static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1433 u32 format, u64 modifier)
714244e2 1434{
a38189c5
VS
1435 switch (modifier) {
1436 case DRM_FORMAT_MOD_LINEAR:
1437 case I915_FORMAT_MOD_X_TILED:
1438 break;
1439 default:
1440 return false;
1441 }
1442
714244e2 1443 switch (format) {
c21f7904
VS
1444 case DRM_FORMAT_XRGB8888:
1445 case DRM_FORMAT_XBGR8888:
714244e2
BW
1446 case DRM_FORMAT_YUYV:
1447 case DRM_FORMAT_YVYU:
1448 case DRM_FORMAT_UYVY:
1449 case DRM_FORMAT_VYUY:
c21f7904
VS
1450 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1451 modifier == I915_FORMAT_MOD_X_TILED)
1452 return true;
1453 /* fall through */
1454 default:
1455 return false;
1456 }
1457}
1458
a38189c5
VS
1459static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1460 u32 format, u64 modifier)
c21f7904 1461{
a38189c5
VS
1462 switch (modifier) {
1463 case DRM_FORMAT_MOD_LINEAR:
1464 case I915_FORMAT_MOD_X_TILED:
1465 break;
1466 default:
1467 return false;
1468 }
1469
c21f7904 1470 switch (format) {
714244e2 1471 case DRM_FORMAT_RGB565:
c21f7904 1472 case DRM_FORMAT_ABGR8888:
714244e2 1473 case DRM_FORMAT_ARGB8888:
c21f7904
VS
1474 case DRM_FORMAT_XBGR8888:
1475 case DRM_FORMAT_XRGB8888:
714244e2
BW
1476 case DRM_FORMAT_XBGR2101010:
1477 case DRM_FORMAT_ABGR2101010:
c21f7904
VS
1478 case DRM_FORMAT_YUYV:
1479 case DRM_FORMAT_YVYU:
1480 case DRM_FORMAT_UYVY:
1481 case DRM_FORMAT_VYUY:
714244e2
BW
1482 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1483 modifier == I915_FORMAT_MOD_X_TILED)
1484 return true;
1485 /* fall through */
1486 default:
1487 return false;
1488 }
1489}
1490
a38189c5
VS
1491static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1492 u32 format, u64 modifier)
714244e2 1493{
a38189c5
VS
1494 struct intel_plane *plane = to_intel_plane(_plane);
1495
1496 switch (modifier) {
1497 case DRM_FORMAT_MOD_LINEAR:
1498 case I915_FORMAT_MOD_X_TILED:
1499 case I915_FORMAT_MOD_Y_TILED:
1500 case I915_FORMAT_MOD_Yf_TILED:
1501 break;
1502 case I915_FORMAT_MOD_Y_TILED_CCS:
1503 case I915_FORMAT_MOD_Yf_TILED_CCS:
1504 if (!plane->has_ccs)
1505 return false;
1506 break;
1507 default:
1508 return false;
1509 }
1510
714244e2
BW
1511 switch (format) {
1512 case DRM_FORMAT_XRGB8888:
1513 case DRM_FORMAT_XBGR8888:
1514 case DRM_FORMAT_ARGB8888:
1515 case DRM_FORMAT_ABGR8888:
63eaf9ac 1516 if (is_ccs_modifier(modifier))
77064e2e
VS
1517 return true;
1518 /* fall through */
714244e2
BW
1519 case DRM_FORMAT_RGB565:
1520 case DRM_FORMAT_XRGB2101010:
1521 case DRM_FORMAT_XBGR2101010:
1522 case DRM_FORMAT_YUYV:
1523 case DRM_FORMAT_YVYU:
1524 case DRM_FORMAT_UYVY:
1525 case DRM_FORMAT_VYUY:
429204f1 1526 case DRM_FORMAT_NV12:
714244e2
BW
1527 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1528 return true;
1529 /* fall through */
1530 case DRM_FORMAT_C8:
1531 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1532 modifier == I915_FORMAT_MOD_X_TILED ||
1533 modifier == I915_FORMAT_MOD_Y_TILED)
1534 return true;
1535 /* fall through */
1536 default:
1537 return false;
1538 }
1539}
1540
a38189c5
VS
1541static const struct drm_plane_funcs g4x_sprite_funcs = {
1542 .update_plane = drm_atomic_helper_update_plane,
1543 .disable_plane = drm_atomic_helper_disable_plane,
1544 .destroy = intel_plane_destroy,
1545 .atomic_get_property = intel_plane_atomic_get_property,
1546 .atomic_set_property = intel_plane_atomic_set_property,
1547 .atomic_duplicate_state = intel_plane_duplicate_state,
1548 .atomic_destroy_state = intel_plane_destroy_state,
1549 .format_mod_supported = g4x_sprite_format_mod_supported,
1550};
714244e2 1551
a38189c5
VS
1552static const struct drm_plane_funcs snb_sprite_funcs = {
1553 .update_plane = drm_atomic_helper_update_plane,
1554 .disable_plane = drm_atomic_helper_disable_plane,
1555 .destroy = intel_plane_destroy,
1556 .atomic_get_property = intel_plane_atomic_get_property,
1557 .atomic_set_property = intel_plane_atomic_set_property,
1558 .atomic_duplicate_state = intel_plane_duplicate_state,
1559 .atomic_destroy_state = intel_plane_destroy_state,
1560 .format_mod_supported = snb_sprite_format_mod_supported,
1561};
714244e2 1562
a38189c5
VS
1563static const struct drm_plane_funcs vlv_sprite_funcs = {
1564 .update_plane = drm_atomic_helper_update_plane,
1565 .disable_plane = drm_atomic_helper_disable_plane,
1566 .destroy = intel_plane_destroy,
1567 .atomic_get_property = intel_plane_atomic_get_property,
1568 .atomic_set_property = intel_plane_atomic_set_property,
1569 .atomic_duplicate_state = intel_plane_duplicate_state,
1570 .atomic_destroy_state = intel_plane_destroy_state,
1571 .format_mod_supported = vlv_sprite_format_mod_supported,
1572};
714244e2 1573
a38189c5 1574static const struct drm_plane_funcs skl_plane_funcs = {
b4686c48
VS
1575 .update_plane = drm_atomic_helper_update_plane,
1576 .disable_plane = drm_atomic_helper_disable_plane,
1577 .destroy = intel_plane_destroy,
1578 .atomic_get_property = intel_plane_atomic_get_property,
1579 .atomic_set_property = intel_plane_atomic_set_property,
1580 .atomic_duplicate_state = intel_plane_duplicate_state,
1581 .atomic_destroy_state = intel_plane_destroy_state,
a38189c5 1582 .format_mod_supported = skl_plane_format_mod_supported,
714244e2
BW
1583};
1584
77064e2e
VS
1585bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1586 enum pipe pipe, enum plane_id plane_id)
1587{
1588 if (plane_id == PLANE_CURSOR)
1589 return false;
1590
1591 if (INTEL_GEN(dev_priv) >= 10)
1592 return true;
1593
1594 if (IS_GEMINILAKE(dev_priv))
1595 return pipe != PIPE_C;
1596
1597 return pipe != PIPE_C &&
1598 (plane_id == PLANE_PRIMARY ||
1599 plane_id == PLANE_SPRITE0);
1600}
1601
b079bd17 1602struct intel_plane *
580503c7
VS
1603intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1604 enum pipe pipe, int plane)
b840d907 1605{
fca0ce2a
VS
1606 struct intel_plane *intel_plane = NULL;
1607 struct intel_plane_state *state = NULL;
a38189c5 1608 const struct drm_plane_funcs *plane_funcs;
b840d907 1609 unsigned long possible_crtcs;
d1686ae3 1610 const uint32_t *plane_formats;
714244e2 1611 const uint64_t *modifiers;
93ca7e00 1612 unsigned int supported_rotations;
d1686ae3 1613 int num_plane_formats;
b840d907
JB
1614 int ret;
1615
b14c5679 1616 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
fca0ce2a
VS
1617 if (!intel_plane) {
1618 ret = -ENOMEM;
1619 goto fail;
1620 }
b840d907 1621
8e7d688b
MR
1622 state = intel_create_plane_state(&intel_plane->base);
1623 if (!state) {
fca0ce2a
VS
1624 ret = -ENOMEM;
1625 goto fail;
ea2c67bb 1626 }
8e7d688b 1627 intel_plane->base.state = &state->base;
ea2c67bb 1628
77064e2e 1629 if (INTEL_GEN(dev_priv) >= 9) {
714244e2
BW
1630 state->scaler_id = -1;
1631
a38189c5
VS
1632 intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
1633 PLANE_SPRITE0 + plane);
1634
ddd5713d 1635 intel_plane->max_stride = skl_plane_max_stride;
714244e2
BW
1636 intel_plane->update_plane = skl_update_plane;
1637 intel_plane->disable_plane = skl_disable_plane;
51f5a096 1638 intel_plane->get_hw_state = skl_plane_get_hw_state;
4e0b83a5 1639 intel_plane->check_plane = skl_plane_check;
714244e2 1640
429204f1
CK
1641 if (skl_plane_has_planar(dev_priv, pipe,
1642 PLANE_SPRITE0 + plane)) {
1643 plane_formats = skl_planar_formats;
1644 num_plane_formats = ARRAY_SIZE(skl_planar_formats);
1645 } else {
1646 plane_formats = skl_plane_formats;
1647 num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1648 }
d1686ae3 1649
a38189c5 1650 if (intel_plane->has_ccs)
77064e2e
VS
1651 modifiers = skl_plane_format_modifiers_ccs;
1652 else
1653 modifiers = skl_plane_format_modifiers_noccs;
a38189c5
VS
1654
1655 plane_funcs = &skl_plane_funcs;
1890ae64 1656 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
ddd5713d 1657 intel_plane->max_stride = i9xx_plane_max_stride;
1890ae64
VS
1658 intel_plane->update_plane = vlv_update_plane;
1659 intel_plane->disable_plane = vlv_disable_plane;
51f5a096 1660 intel_plane->get_hw_state = vlv_plane_get_hw_state;
4e0b83a5 1661 intel_plane->check_plane = vlv_sprite_check;
d1686ae3 1662
1890ae64
VS
1663 plane_formats = vlv_plane_formats;
1664 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
714244e2 1665 modifiers = i9xx_plane_format_modifiers;
a38189c5
VS
1666
1667 plane_funcs = &vlv_sprite_funcs;
1890ae64 1668 } else if (INTEL_GEN(dev_priv) >= 7) {
ddd5713d 1669 intel_plane->max_stride = g4x_sprite_max_stride;
1890ae64
VS
1670 intel_plane->update_plane = ivb_update_plane;
1671 intel_plane->disable_plane = ivb_disable_plane;
51f5a096 1672 intel_plane->get_hw_state = ivb_plane_get_hw_state;
4e0b83a5 1673 intel_plane->check_plane = g4x_sprite_check;
7f1f3851 1674
1890ae64
VS
1675 plane_formats = snb_plane_formats;
1676 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
714244e2 1677 modifiers = i9xx_plane_format_modifiers;
a38189c5
VS
1678
1679 plane_funcs = &snb_sprite_funcs;
1890ae64 1680 } else {
ddd5713d 1681 intel_plane->max_stride = g4x_sprite_max_stride;
ab33081a
VS
1682 intel_plane->update_plane = g4x_update_plane;
1683 intel_plane->disable_plane = g4x_disable_plane;
51f5a096 1684 intel_plane->get_hw_state = g4x_plane_get_hw_state;
4e0b83a5 1685 intel_plane->check_plane = g4x_sprite_check;
7f1f3851 1686
714244e2 1687 modifiers = i9xx_plane_format_modifiers;
1890ae64 1688 if (IS_GEN6(dev_priv)) {
7f1f3851
JB
1689 plane_formats = snb_plane_formats;
1690 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
a38189c5
VS
1691
1692 plane_funcs = &snb_sprite_funcs;
1890ae64 1693 } else {
ab33081a
VS
1694 plane_formats = g4x_plane_formats;
1695 num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
a38189c5
VS
1696
1697 plane_funcs = &g4x_sprite_funcs;
7f1f3851 1698 }
b840d907
JB
1699 }
1700
5481e27f 1701 if (INTEL_GEN(dev_priv) >= 9) {
93ca7e00 1702 supported_rotations =
c2c446ad
RF
1703 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
1704 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
4ea7be2b
VS
1705 } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1706 supported_rotations =
c2c446ad
RF
1707 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1708 DRM_MODE_REFLECT_X;
93ca7e00
VS
1709 } else {
1710 supported_rotations =
c2c446ad 1711 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
93ca7e00
VS
1712 }
1713
b840d907 1714 intel_plane->pipe = pipe;
ed15030d 1715 intel_plane->i9xx_plane = plane;
b14e5848 1716 intel_plane->id = PLANE_SPRITE0 + plane;
c19e1124 1717 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
fca0ce2a 1718
b840d907 1719 possible_crtcs = (1 << pipe);
fca0ce2a 1720
1890ae64 1721 if (INTEL_GEN(dev_priv) >= 9)
580503c7 1722 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
a38189c5 1723 possible_crtcs, plane_funcs,
38573dc1 1724 plane_formats, num_plane_formats,
714244e2
BW
1725 modifiers,
1726 DRM_PLANE_TYPE_OVERLAY,
38573dc1
VS
1727 "plane %d%c", plane + 2, pipe_name(pipe));
1728 else
580503c7 1729 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
a38189c5 1730 possible_crtcs, plane_funcs,
38573dc1 1731 plane_formats, num_plane_formats,
714244e2
BW
1732 modifiers,
1733 DRM_PLANE_TYPE_OVERLAY,
38573dc1 1734 "sprite %c", sprite_name(pipe, plane));
fca0ce2a
VS
1735 if (ret)
1736 goto fail;
7ed6eeee 1737
93ca7e00 1738 drm_plane_create_rotation_property(&intel_plane->base,
c2c446ad 1739 DRM_MODE_ROTATE_0,
93ca7e00 1740 supported_rotations);
b840d907 1741
b0f5c0ba
VS
1742 drm_plane_create_color_properties(&intel_plane->base,
1743 BIT(DRM_COLOR_YCBCR_BT601) |
1744 BIT(DRM_COLOR_YCBCR_BT709),
c8624ede
VS
1745 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1746 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
23b28089 1747 DRM_COLOR_YCBCR_BT709,
b0f5c0ba
VS
1748 DRM_COLOR_YCBCR_LIMITED_RANGE);
1749
ea2c67bb
MR
1750 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1751
b079bd17 1752 return intel_plane;
fca0ce2a
VS
1753
1754fail:
1755 kfree(state);
1756 kfree(intel_plane);
1757
b079bd17 1758 return ERR_PTR(ret);
b840d907 1759}
This page took 1.215159 seconds and 4 git commands to generate.