blob: 5fd425ac1b3be5cf44bb706b3ff898437a4f722b [file] [log] [blame]
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001/*
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 <jbarnes@virtuousgeek.org>
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 */
David Howells760285e2012-10-02 18:01:07 +010032#include <drm/drmP.h>
Ben Widawsky714244e2017-08-01 09:58:16 -070033#include <drm/drm_atomic_helper.h>
David Howells760285e2012-10-02 18:01:07 +010034#include <drm/drm_crtc.h>
35#include <drm/drm_fourcc.h>
Ville Syrjälä17316932013-04-24 18:52:38 +030036#include <drm/drm_rect.h>
Chandra Konduruc3318792015-04-15 15:15:02 -070037#include <drm/drm_atomic.h>
Matt Roperea2c67b2014-12-23 10:41:52 -080038#include <drm/drm_plane_helper.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080039#include "intel_drv.h"
Chris Wilson5d723d72016-08-04 16:32:35 +010040#include "intel_frontbuffer.h"
David Howells760285e2012-10-02 18:01:07 +010041#include <drm/i915_drm.h>
Jesse Barnesb840d907f2011-12-13 13:19:38 -080042#include "i915_drv.h"
43
Ville Syrjälädfd2e9a2016-05-18 11:34:38 +030044int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
45 int usecs)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030046{
47 /* paranoia */
Ville Syrjälä5e7234c2015-09-25 16:37:43 +030048 if (!adjusted_mode->crtc_htotal)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030049 return 1;
50
Ville Syrjälä5e7234c2015-09-25 16:37:43 +030051 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
52 1000 * adjusted_mode->crtc_htotal);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030053}
54
Daniel Vetter69208c92017-10-10 11:18:16 +020055/* 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
Maarten Lankhorste1edbd42017-02-28 15:28:48 +010060#define VBLANK_EVASION_TIME_US 100
Daniel Vetter69208c92017-10-10 11:18:16 +020061#endif
Maarten Lankhorste1edbd42017-02-28 15:28:48 +010062
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020063/**
64 * intel_pipe_update_start() - start update of a set of display registers
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030065 * @new_crtc_state: the new crtc state
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020066 *
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
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030073 * avoid random delays.
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020074 */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030075void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030076{
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030077 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +020078 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030079 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030080 long timeout = msecs_to_jiffies_timeout(1);
81 int scanline, min, max, vblank_start;
Ville Syrjälä210871b62014-05-22 19:00:50 +030082 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +020083 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030084 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030085 DEFINE_WAIT(wait);
Dhinakaran Pandiyan63ec1322018-08-21 15:11:54 -070086 u32 psr_status;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030087
Ville Syrjälä124abe02015-09-08 13:40:45 +030088 vblank_start = adjusted_mode->crtc_vblank_start;
89 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030090 vblank_start = DIV_ROUND_UP(vblank_start, 2);
91
92 /* FIXME needs to be calibrated sensibly */
Maarten Lankhorste1edbd42017-02-28 15:28:48 +010093 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
94 VBLANK_EVASION_TIME_US);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030095 max = vblank_start - 1;
96
97 if (min <= 0 || max <= 0)
Tarun Vyasa6089872018-06-27 13:02:50 -070098 goto irq_disable;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030099
Daniel Vetter1e3feef2015-02-13 21:03:45 +0100100 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
Tarun Vyasa6089872018-06-27 13:02:50 -0700101 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 */
Dhinakaran Pandiyan63ec1322018-08-21 15:11:54 -0700108 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);
Tarun Vyasa6089872018-06-27 13:02:50 -0700111
112 local_irq_disable();
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300113
Jesse Barnesd637ce32015-09-17 08:08:32 -0700114 crtc->debug.min_vbl = min;
115 crtc->debug.max_vbl = max;
116 trace_i915_pipe_update_start(crtc);
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300117
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300118 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 */
Ville Syrjälä210871b62014-05-22 19:00:50 +0300124 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300125
126 scanline = intel_get_crtc_scanline(crtc);
127 if (scanline < min || scanline > max)
128 break;
129
Tarun9ba59b72018-05-02 16:33:00 -0700130 if (!timeout) {
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300131 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
Ville Syrjälä210871b62014-05-22 19:00:50 +0300143 finish_wait(wq, &wait);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300144
Daniel Vetter1e3feef2015-02-13 21:03:45 +0100145 drm_crtc_vblank_put(&crtc->base);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300146
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +0200147 /*
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
Jesse Barneseb120ef2015-09-15 14:19:32 -0700165 crtc->debug.scanline_start = scanline;
166 crtc->debug.start_vbl_time = ktime_get();
Maarten Lankhorsta2991412016-05-17 15:07:48 +0200167 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300168
Jesse Barnesd637ce32015-09-17 08:08:32 -0700169 trace_i915_pipe_update_vblank_evaded(crtc);
Tarun Vyasa6089872018-06-27 13:02:50 -0700170 return;
171
172irq_disable:
173 local_irq_disable();
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300174}
175
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200176/**
177 * intel_pipe_update_end() - end update of a set of display registers
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300178 * @new_crtc_state: the new crtc state
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200179 *
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
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300182 * before a vblank.
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200183 */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300184void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300185{
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300186 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300187 enum pipe pipe = crtc->pipe;
Jesse Barneseb120ef2015-09-15 14:19:32 -0700188 int scanline_end = intel_get_crtc_scanline(crtc);
Maarten Lankhorsta2991412016-05-17 15:07:48 +0200189 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
Maarten Lankhorst85a62bf2015-09-01 12:15:33 +0200190 ktime_t end_vbl_time = ktime_get();
Bing Niua94f2b92017-03-08 15:14:03 -0500191 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300192
Jesse Barnesd637ce32015-09-17 08:08:32 -0700193 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300194
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200195 /* 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 ... */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300199 if (new_crtc_state->base.event) {
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200200 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
201
202 spin_lock(&crtc->base.dev->event_lock);
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300203 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200204 spin_unlock(&crtc->base.dev->event_lock);
205
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300206 new_crtc_state->base.event = NULL;
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200207 }
208
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300209 local_irq_enable();
210
Bing Niua94f2b92017-03-08 15:14:03 -0500211 if (intel_vgpu_active(dev_priv))
212 return;
213
Jesse Barneseb120ef2015-09-15 14:19:32 -0700214 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);
Ville Syrjälä7b8cd332017-05-07 20:12:52 +0300222 }
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)
Maarten Lankhorste1edbd42017-02-28 15:28:48 +0100226 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);
Ville Syrjälä7b8cd332017-05-07 20:12:52 +0300230#endif
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300231}
232
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +0300233int 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
Ville Syrjäläddd57132018-09-07 18:24:02 +0300266unsigned 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
Juha-Pekka Heikkila9a8cc572017-10-17 23:08:09 +0300283void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300284skl_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100285 const struct intel_crtc_state *crtc_state,
286 const struct intel_plane_state *plane_state)
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000287{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300288 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;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200292 u32 plane_ctl = plane_state->ctl;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100293 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300294 u32 surf_addr = plane_state->color_plane[0].offset;
Ville Syrjälädf79cf42018-09-11 18:01:39 +0300295 u32 stride = skl_plane_stride(plane_state, 0);
296 u32 aux_stride = skl_plane_stride(plane_state, 1);
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300297 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);
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300301 uint32_t x = plane_state->color_plane[0].x;
302 uint32_t y = plane_state->color_plane[0].y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300303 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;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200305 unsigned long irqflags;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000306
Ville Syrjälä6687c902015-09-15 13:16:41 +0300307 /* Sizes are 0 based */
308 src_w--;
309 src_h--;
310 crtc_w--;
311 crtc_h--;
312
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200313 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
314
James Ausmus4036c782017-11-13 10:11:28 -0800315 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200316 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
James Ausmus4036c782017-11-13 10:11:28 -0800317 plane_state->color_ctl);
Ville Syrjälä38f24f22018-02-14 21:23:24 +0200318
Ville Syrjälä78587de2017-03-09 17:44:32 +0200319 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200320 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);
Ville Syrjälä78587de2017-03-09 17:44:32 +0200323 }
324
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200325 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);
Ville Syrjälä2e2adb02017-08-01 09:58:13 -0700328 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300329 (plane_state->color_plane[1].offset - surf_addr) | aux_stride);
Ville Syrjälä2e2adb02017-08-01 09:58:13 -0700330 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300331 (plane_state->color_plane[1].y << 16) |
332 plane_state->color_plane[1].x);
Chandra Konduruc3318792015-04-15 15:15:02 -0700333
334 /* program plane scaler */
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100335 if (plane_state->scaler_id >= 0) {
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100336 int scaler_id = plane_state->scaler_id;
Ville Syrjälä0a599522018-05-21 21:56:13 +0300337 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;
Chandra Konduruc3318792015-04-15 15:15:02 -0700341
Ville Syrjälä0a599522018-05-21 21:56:13 +0300342 /* 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;
354
355 uv_rgb_hphase = skl_scaler_calc_phase(1, false);
356 uv_rgb_vphase = skl_scaler_calc_phase(1, false);
357 }
Imre Deak7494bcd2016-05-12 16:18:49 +0300358
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200359 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);
Ville Syrjälä0a599522018-05-21 21:56:13 +0300362 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));
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200366 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));
Chandra Konduruc3318792015-04-15 15:15:02 -0700369
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200370 I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
Chandra Konduruc3318792015-04-15 15:15:02 -0700371 } else {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200372 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
Chandra Konduruc3318792015-04-15 15:15:02 -0700373 }
374
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200375 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);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000381}
382
Juha-Pekka Heikkila779d4d82017-10-17 23:08:10 +0300383void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300384skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000385{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300386 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;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200389 unsigned long irqflags;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000390
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200391 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000392
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200393 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
394
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);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000399}
400
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200401bool
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200402skl_plane_get_hw_state(struct intel_plane *plane,
403 enum pipe *pipe)
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200404{
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;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200408 bool ret;
409
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200410 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200411 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
412 return false;
413
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200414 ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
415
416 *pipe = plane->pipe;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200417
418 intel_display_power_put(dev_priv, power_domain);
419
420 return ret;
421}
422
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000423static void
Ville Syrjälä5deae912018-02-14 21:23:23 +0200424chv_update_csc(const struct intel_plane_state *plane_state)
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300425{
Ville Syrjälä5deae912018-02-14 21:23:23 +0200426 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300427 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
Ville Syrjälä5deae912018-02-14 21:23:23 +0200428 const struct drm_framebuffer *fb = plane_state->base.fb;
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300429 enum plane_id plane_id = plane->id;
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +0200430 /*
431 * |r| | c0 c1 c2 | |cr|
432 * |g| = | c3 c4 c5 | x |y |
433 * |b| | c6 c7 c8 | |cb|
434 *
435 * Coefficients are s3.12.
436 *
437 * Cb and Cr apparently come in as signed already, and
438 * we always get full range data in on account of CLRC0/1.
439 */
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];
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300455
456 /* Seems RGB data bypasses the CSC always */
Ayan Kumar Halder9bace652018-07-17 18:13:43 +0100457 if (!fb->format->is_yuv)
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300458 return;
459
Ville Syrjälä5deae912018-02-14 21:23:23 +0200460 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200461 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));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300463
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +0200464 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]));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300469
Ville Syrjälä5deae912018-02-14 21:23:23 +0200470 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));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300473
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200474 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));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300477}
478
Ville Syrjälä5deae912018-02-14 21:23:23 +0200479#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
Ayan Kumar Halder9bace652018-07-17 18:13:43 +0100492 if (fb->format->is_yuv &&
Ville Syrjäläc8624ed2018-02-14 21:23:27 +0200493 plane_state->base.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
Ville Syrjälä5deae912018-02-14 21:23:23 +0200494 /*
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
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200521static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
522 const struct intel_plane_state *plane_state)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700523{
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200524 const struct drm_framebuffer *fb = plane_state->base.fb;
Ville Syrjälä11df4d92016-11-07 22:20:55 +0200525 unsigned int rotation = plane_state->base.rotation;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100526 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200527 u32 sprctl;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700528
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200529 sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700530
Ville Syrjälä438b74a2016-12-14 23:32:55 +0200531 switch (fb->format->format) {
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700532 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:
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200566 MISSING_CASE(fb->format->format);
567 return 0;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700568 }
569
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +0200570 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
571 sprctl |= SP_YUV_FORMAT_BT709;
572
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200573 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700574 sprctl |= SP_TILED;
575
Robert Fossc2c446a2017-05-19 16:50:17 -0400576 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälädf0cd452016-11-14 18:53:59 +0200577 sprctl |= SP_ROTATE_180;
578
Robert Fossc2c446a2017-05-19 16:50:17 -0400579 if (rotation & DRM_MODE_REFLECT_X)
Ville Syrjälä4ea7be22016-11-14 18:54:00 +0200580 sprctl |= SP_MIRROR;
581
Ville Syrjälä78587de2017-03-09 17:44:32 +0200582 if (key->flags & I915_SET_COLORKEY_SOURCE)
583 sprctl |= SP_SOURCE_KEY;
584
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200585 return sprctl;
586}
587
588static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300589vlv_update_plane(struct intel_plane *plane,
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200590 const struct intel_crtc_state *crtc_state,
591 const struct intel_plane_state *plane_state)
592{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300593 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;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200597 u32 sprctl = plane_state->ctl;
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300598 u32 sprsurf_offset = plane_state->color_plane[0].offset;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200599 u32 linear_offset;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200600 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);
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300605 uint32_t x = plane_state->color_plane[0].x;
606 uint32_t y = plane_state->color_plane[0].y;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200607 unsigned long irqflags;
608
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700609 /* Sizes are 0 based */
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700610 crtc_w--;
611 crtc_h--;
612
Ville Syrjälä29490562016-01-20 18:02:50 +0200613 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300614
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200615 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
616
Ville Syrjälä5deae912018-02-14 21:23:23 +0200617 vlv_update_clrc(plane_state);
618
Ville Syrjälä78587de2017-03-09 17:44:32 +0200619 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
Ville Syrjälä5deae912018-02-14 21:23:23 +0200620 chv_update_csc(plane_state);
Ville Syrjälä78587de2017-03-09 17:44:32 +0200621
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200622 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200623 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);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200626 }
Ville Syrjälädf79cf42018-09-11 18:01:39 +0300627 I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
628 plane_state->color_plane[0].stride);
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200629 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200630
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200631 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200632 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700633 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200634 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700635
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200636 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
Ville Syrjäläc14b0482014-10-16 20:52:34 +0300637
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200638 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);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700645}
646
647static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300648vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700649{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300650 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;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200653 unsigned long irqflags;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700654
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200655 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
Ville Syrjälä48fe4692015-03-19 17:57:13 +0200656
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200657 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
658
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);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700663}
664
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200665static bool
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200666vlv_plane_get_hw_state(struct intel_plane *plane,
667 enum pipe *pipe)
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200668{
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;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200672 bool ret;
673
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200674 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200675 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
676 return false;
677
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200678 ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
679
680 *pipe = plane->pipe;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200681
682 intel_display_power_put(dev_priv, power_domain);
683
684 return ret;
685}
686
Ville Syrjälä45dea7b2017-03-17 23:17:59 +0200687static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
688 const struct intel_plane_state *plane_state)
689{
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;
693 unsigned int rotation = plane_state->base.rotation;
694 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
695 u32 sprctl;
696
697 sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
698
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;
704
705 switch (fb->format->format) {
706 case DRM_FORMAT_XBGR8888:
707 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
708 break;
709 case DRM_FORMAT_XRGB8888:
710 sprctl |= SPRITE_FORMAT_RGBX888;
711 break;
712 case DRM_FORMAT_YUYV:
713 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
714 break;
715 case DRM_FORMAT_YVYU:
716 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
717 break;
718 case DRM_FORMAT_UYVY:
719 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
720 break;
721 case DRM_FORMAT_VYUY:
722 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
723 break;
724 default:
725 MISSING_CASE(fb->format->format);
726 return 0;
727 }
728
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +0200729 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
730 sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
731
Ville Syrjäläc8624ed2018-02-14 21:23:27 +0200732 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
733 sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
734
Ville Syrjälä45dea7b2017-03-17 23:17:59 +0200735 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
736 sprctl |= SPRITE_TILED;
737
Robert Fossc2c446a2017-05-19 16:50:17 -0400738 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälä45dea7b2017-03-17 23:17:59 +0200739 sprctl |= SPRITE_ROTATE_180;
740
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
746 return sprctl;
747}
748
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700749static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300750ivb_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100751 const struct intel_crtc_state *crtc_state,
752 const struct intel_plane_state *plane_state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800753{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300754 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;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200757 u32 sprctl = plane_state->ctl, sprscale = 0;
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300758 u32 sprsurf_offset = plane_state->color_plane[0].offset;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200759 u32 linear_offset;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100760 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300761 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);
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300765 uint32_t x = plane_state->color_plane[0].x;
766 uint32_t y = plane_state->color_plane[0].y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300767 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;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200769 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800770
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800771 /* Sizes are 0 based */
772 src_w--;
773 src_h--;
774 crtc_w--;
775 crtc_h--;
776
Ville Syrjälä8553c182013-12-05 15:51:39 +0200777 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800778 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800779
Ville Syrjälä29490562016-01-20 18:02:50 +0200780 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300781
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200782 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
783
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200784 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200785 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);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200788 }
789
Ville Syrjälädf79cf42018-09-11 18:01:39 +0300790 I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200791 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200792
Damien Lespiau5a35e992012-10-26 18:20:12 +0100793 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
794 * register */
Tvrtko Ursulin86527442016-10-13 11:03:00 +0100795 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200796 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200797 else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200798 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100799 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200800 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100801
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200802 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
Ville Syrjäläfd6e3c62018-09-07 18:24:08 +0300803 if (IS_IVYBRIDGE(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200804 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);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800811}
812
813static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300814ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800815{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300816 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
817 enum pipe pipe = plane->pipe;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200818 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800819
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200820 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
821
822 I915_WRITE_FW(SPRCTL(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800823 /* Can't leave the scaler enabled... */
Ville Syrjäläfd6e3c62018-09-07 18:24:08 +0300824 if (IS_IVYBRIDGE(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200825 I915_WRITE_FW(SPRSCALE(pipe), 0);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300826
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200827 I915_WRITE_FW(SPRSURF(pipe), 0);
828 POSTING_READ_FW(SPRSURF(pipe));
829
830 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800831}
832
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200833static bool
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200834ivb_plane_get_hw_state(struct intel_plane *plane,
835 enum pipe *pipe)
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200836{
837 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
838 enum intel_display_power_domain power_domain;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200839 bool ret;
840
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200841 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200842 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
843 return false;
844
Ville Syrjäläeade6c82018-01-30 22:38:03 +0200845 ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
846
847 *pipe = plane->pipe;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200848
849 intel_display_power_put(dev_priv, power_domain);
850
851 return ret;
852}
853
Ville Syrjäläddd57132018-09-07 18:24:02 +0300854static 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
Ville Syrjäläab330812017-04-21 21:14:32 +0300862static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
Ville Syrjälä0a375142017-03-17 23:18:00 +0200863 const struct intel_plane_state *plane_state)
864{
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;
868 unsigned int rotation = plane_state->base.rotation;
869 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
870 u32 dvscntr;
871
872 dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
873
874 if (IS_GEN6(dev_priv))
875 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
876
877 switch (fb->format->format) {
878 case DRM_FORMAT_XBGR8888:
879 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
880 break;
881 case DRM_FORMAT_XRGB8888:
882 dvscntr |= DVS_FORMAT_RGBX888;
883 break;
884 case DRM_FORMAT_YUYV:
885 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
886 break;
887 case DRM_FORMAT_YVYU:
888 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
889 break;
890 case DRM_FORMAT_UYVY:
891 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
892 break;
893 case DRM_FORMAT_VYUY:
894 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
895 break;
896 default:
897 MISSING_CASE(fb->format->format);
898 return 0;
899 }
900
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +0200901 if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
902 dvscntr |= DVS_YUV_FORMAT_BT709;
903
Ville Syrjäläc8624ed2018-02-14 21:23:27 +0200904 if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
905 dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
906
Ville Syrjälä0a375142017-03-17 23:18:00 +0200907 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
908 dvscntr |= DVS_TILED;
909
Robert Fossc2c446a2017-05-19 16:50:17 -0400910 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälä0a375142017-03-17 23:18:00 +0200911 dvscntr |= DVS_ROTATE_180;
912
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
918 return dvscntr;
919}
920
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800921static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300922g4x_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100923 const struct intel_crtc_state *crtc_state,
924 const struct intel_plane_state *plane_state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800925{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300926 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;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200929 u32 dvscntr = plane_state->ctl, dvsscale = 0;
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300930 u32 dvssurf_offset = plane_state->color_plane[0].offset;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200931 u32 linear_offset;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100932 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300933 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);
Ville Syrjäläc11ada02018-09-07 18:24:04 +0300937 uint32_t x = plane_state->color_plane[0].x;
938 uint32_t y = plane_state->color_plane[0].y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300939 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;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200941 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800942
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800943 /* Sizes are 0 based */
944 src_w--;
945 src_h--;
946 crtc_w--;
947 crtc_h--;
948
Ville Syrjälä8368f012013-12-05 15:51:31 +0200949 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800950 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
951
Ville Syrjälä29490562016-01-20 18:02:50 +0200952 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300953
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200954 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
955
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200956 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200957 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);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200960 }
961
Ville Syrjälädf79cf42018-09-11 18:01:39 +0300962 I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200963 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200964
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200965 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200966 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100967 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200968 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100969
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200970 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);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800978}
979
980static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300981g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800982{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300983 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
984 enum pipe pipe = plane->pipe;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200985 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800986
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200987 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
988
989 I915_WRITE_FW(DVSCNTR(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800990 /* Disable the scaler */
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200991 I915_WRITE_FW(DVSSCALE(pipe), 0);
Ville Syrjälä48fe4692015-03-19 17:57:13 +0200992
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200993 I915_WRITE_FW(DVSSURF(pipe), 0);
994 POSTING_READ_FW(DVSSURF(pipe));
995
996 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800997}
998
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200999static bool
Ville Syrjäläeade6c82018-01-30 22:38:03 +02001000g4x_plane_get_hw_state(struct intel_plane *plane,
1001 enum pipe *pipe)
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001002{
1003 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1004 enum intel_display_power_domain power_domain;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001005 bool ret;
1006
Ville Syrjäläeade6c82018-01-30 22:38:03 +02001007 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001008 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
1009 return false;
1010
Ville Syrjäläeade6c82018-01-30 22:38:03 +02001011 ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1012
1013 *pipe = plane->pipe;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001014
1015 intel_display_power_put(dev_priv, power_domain);
1016
1017 return ret;
1018}
1019
Jesse Barnes8ea30862012-01-03 08:05:39 -08001020static int
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001021g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1022 struct intel_plane_state *plane_state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001023{
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001024 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)
1043 return 0;
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;
1055 }
1056
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);
1063 return -EINVAL;
1064 }
1065
1066 if (width_bytes > 4096) {
1067 DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1068 width_bytes, 4096);
1069 return -EINVAL;
1070 }
1071
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);
Ville Syrjälä282dbf92017-03-27 21:55:33 +03001086 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
Ville Syrjälä17316932013-04-24 18:52:38 +03001087 int max_scale, min_scale;
Ville Syrjäläb63a16f2016-01-28 16:53:54 +02001088 int ret;
Matt Ropercf4c7c12014-12-04 10:27:42 -08001089
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001090 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;
Chandra Konduru225c2282015-05-18 16:18:44 -07001096 } else {
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001097 min_scale = DRM_PLANE_HELPER_NO_SCALING;
1098 max_scale = DRM_PLANE_HELPER_NO_SCALING;
Chandra Konduru225c2282015-05-18 16:18:44 -07001099 }
1100
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001101 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
Maarten Lankhorst9c1659e2018-05-03 13:22:15 +02001102 &crtc_state->base,
1103 min_scale, max_scale,
1104 true, true);
1105 if (ret)
1106 return ret;
Damien Lespiau2d354c32012-10-22 18:19:27 +01001107
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001108 if (!plane_state->base.visible)
1109 return 0;
Ville Syrjälä17316932013-04-24 18:52:38 +03001110
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001111 ret = intel_plane_check_src_coordinates(plane_state);
1112 if (ret)
1113 return ret;
Ville Syrjälä17316932013-04-24 18:52:38 +03001114
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001115 ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1116 if (ret)
1117 return ret;
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001118
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001119 ret = i9xx_check_plane_surface(plane_state);
1120 if (ret)
1121 return ret;
Maarten Lankhorst9c1659e2018-05-03 13:22:15 +02001122
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001123 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);
Maarten Lankhorst9c1659e2018-05-03 13:22:15 +02001127
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001128 return 0;
1129}
Maarten Lankhorst9c1659e2018-05-03 13:22:15 +02001130
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001131static int
1132vlv_sprite_check(struct intel_crtc_state *crtc_state,
1133 struct intel_plane_state *plane_state)
1134{
1135 int ret;
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001136
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001137 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;
Ville Syrjäläa0864d52017-03-23 21:27:09 +02001144
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001145 if (!plane_state->base.visible)
1146 return 0;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +02001147
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001148 ret = intel_plane_check_src_coordinates(plane_state);
1149 if (ret)
1150 return ret;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +02001151
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001152 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);
1157
1158 return 0;
1159}
1160
Ville Syrjäläe21c2d32018-09-07 18:24:10 +03001161static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
1162 const struct intel_plane_state *plane_state)
1163{
1164 const struct drm_framebuffer *fb = plane_state->base.fb;
1165 unsigned int rotation = plane_state->base.rotation;
1166 struct drm_format_name_buf format_name;
1167
1168 if (!fb)
1169 return 0;
1170
1171 if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
1172 (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS &&
1173 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1174 DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
1175 rotation);
1176 return -EINVAL;
1177 }
1178
1179 if (rotation & DRM_MODE_REFLECT_X &&
1180 fb->modifier == DRM_FORMAT_MOD_LINEAR) {
1181 DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
1182 return -EINVAL;
1183 }
1184
1185 if (drm_rotation_90_or_270(rotation)) {
1186 if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
1187 fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
1188 DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
1189 return -EINVAL;
1190 }
1191
1192 /*
1193 * 90/270 is not allowed with RGB64 16:16:16:16,
1194 * RGB 16-bit 5:6:5, and Indexed 8-bit.
1195 * TBD: Add RGB64 case once its added in supported format list.
1196 */
1197 switch (fb->format->format) {
1198 case DRM_FORMAT_C8:
1199 case DRM_FORMAT_RGB565:
1200 DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
1201 drm_get_format_name(fb->format->format,
1202 &format_name));
1203 return -EINVAL;
1204 default:
1205 break;
1206 }
1207 }
1208
1209 /* Y-tiling is not supported in IF-ID Interlace mode */
1210 if (crtc_state->base.enable &&
1211 crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
1212 (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
1213 fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
1214 fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
1215 fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) {
1216 DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
1217 return -EINVAL;
1218 }
1219
1220 return 0;
1221}
1222
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001223int skl_plane_check(struct intel_crtc_state *crtc_state,
1224 struct intel_plane_state *plane_state)
1225{
1226 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1227 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1228 int max_scale, min_scale;
1229 int ret;
1230
Ville Syrjäläe21c2d32018-09-07 18:24:10 +03001231 ret = skl_plane_check_fb(crtc_state, plane_state);
1232 if (ret)
1233 return ret;
1234
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001235 /* use scaler when colorkey is not required */
1236 if (!plane_state->ckey.flags) {
1237 const struct drm_framebuffer *fb = plane_state->base.fb;
1238
1239 min_scale = 1;
1240 max_scale = skl_max_scale(crtc_state,
1241 fb ? fb->format->format : 0);
Ville Syrjäläa0864d52017-03-23 21:27:09 +02001242 } else {
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001243 min_scale = DRM_PLANE_HELPER_NO_SCALING;
1244 max_scale = DRM_PLANE_HELPER_NO_SCALING;
Ville Syrjäläb63a16f2016-01-28 16:53:54 +02001245 }
1246
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001247 ret = drm_atomic_helper_check_plane_state(&plane_state->base,
1248 &crtc_state->base,
1249 min_scale, max_scale,
1250 true, true);
1251 if (ret)
1252 return ret;
1253
1254 if (!plane_state->base.visible)
1255 return 0;
1256
1257 ret = intel_plane_check_src_coordinates(plane_state);
1258 if (ret)
1259 return ret;
1260
1261 ret = skl_check_plane_surface(crtc_state, plane_state);
1262 if (ret)
1263 return ret;
1264
1265 plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
1266
James Ausmus4036c782017-11-13 10:11:28 -08001267 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001268 plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
1269 plane_state);
James Ausmus4036c782017-11-13 10:11:28 -08001270
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001271 return 0;
1272}
1273
Ville Syrjälä672b3c42018-05-29 21:28:00 +03001274static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
1275{
1276 return INTEL_GEN(dev_priv) >= 9;
1277}
1278
1279static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
1280 const struct drm_intel_sprite_colorkey *set)
1281{
1282 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
1283 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1284 struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1285
1286 *key = *set;
1287
1288 /*
1289 * We want src key enabled on the
1290 * sprite and not on the primary.
1291 */
1292 if (plane->id == PLANE_PRIMARY &&
1293 set->flags & I915_SET_COLORKEY_SOURCE)
1294 key->flags = 0;
1295
1296 /*
1297 * On SKL+ we want dst key enabled on
1298 * the primary and not on the sprite.
1299 */
1300 if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
1301 set->flags & I915_SET_COLORKEY_DESTINATION)
1302 key->flags = 0;
1303}
1304
Ville Syrjälä6a20fe72018-02-07 18:48:41 +02001305int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
1306 struct drm_file *file_priv)
Jesse Barnes8ea30862012-01-03 08:05:39 -08001307{
Tvrtko Ursulin920a14b2016-10-14 10:13:44 +01001308 struct drm_i915_private *dev_priv = to_i915(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001309 struct drm_intel_sprite_colorkey *set = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001310 struct drm_plane *plane;
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001311 struct drm_plane_state *plane_state;
1312 struct drm_atomic_state *state;
1313 struct drm_modeset_acquire_ctx ctx;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001314 int ret = 0;
1315
Ville Syrjälä6ec5bd32018-02-02 22:42:31 +02001316 /* ignore the pointless "none" flag */
1317 set->flags &= ~I915_SET_COLORKEY_NONE;
1318
Ville Syrjälä89746e72018-02-06 22:43:33 +02001319 if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1320 return -EINVAL;
1321
Jesse Barnes8ea30862012-01-03 08:05:39 -08001322 /* Make sure we don't try to enable both src & dest simultaneously */
1323 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1324 return -EINVAL;
1325
Tvrtko Ursulin920a14b2016-10-14 10:13:44 +01001326 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
Ville Syrjälä47ecbb22015-03-19 21:18:57 +02001327 set->flags & I915_SET_COLORKEY_DESTINATION)
1328 return -EINVAL;
1329
Keith Packard418da172017-03-14 23:25:07 -07001330 plane = drm_plane_find(dev, file_priv, set->plane_id);
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001331 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1332 return -ENOENT;
1333
Ville Syrjälä672b3c42018-05-29 21:28:00 +03001334 /*
1335 * SKL+ only plane 2 can do destination keying against plane 1.
1336 * Also multiple planes can't do destination keying on the same
1337 * pipe simultaneously.
1338 */
1339 if (INTEL_GEN(dev_priv) >= 9 &&
1340 to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
1341 set->flags & I915_SET_COLORKEY_DESTINATION)
1342 return -EINVAL;
1343
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001344 drm_modeset_acquire_init(&ctx, 0);
1345
1346 state = drm_atomic_state_alloc(plane->dev);
1347 if (!state) {
1348 ret = -ENOMEM;
1349 goto out;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001350 }
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001351 state->acquire_ctx = &ctx;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001352
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001353 while (1) {
1354 plane_state = drm_atomic_get_plane_state(state, plane);
1355 ret = PTR_ERR_OR_ZERO(plane_state);
Ville Syrjälä672b3c42018-05-29 21:28:00 +03001356 if (!ret)
1357 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
1358
1359 /*
1360 * On some platforms we have to configure
1361 * the dst colorkey on the primary plane.
1362 */
1363 if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
1364 struct intel_crtc *crtc =
1365 intel_get_crtc_for_pipe(dev_priv,
1366 to_intel_plane(plane)->pipe);
1367
1368 plane_state = drm_atomic_get_plane_state(state,
1369 crtc->base.primary);
1370 ret = PTR_ERR_OR_ZERO(plane_state);
1371 if (!ret)
1372 intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
Chandra Konduru6156a452015-04-27 13:48:39 -07001373 }
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001374
Ville Syrjälä672b3c42018-05-29 21:28:00 +03001375 if (!ret)
1376 ret = drm_atomic_commit(state);
1377
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001378 if (ret != -EDEADLK)
1379 break;
1380
1381 drm_atomic_state_clear(state);
1382 drm_modeset_backoff(&ctx);
Chandra Konduru6156a452015-04-27 13:48:39 -07001383 }
1384
Chris Wilson08536952016-10-14 13:18:18 +01001385 drm_atomic_state_put(state);
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001386out:
1387 drm_modeset_drop_locks(&ctx);
1388 drm_modeset_acquire_fini(&ctx);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001389 return ret;
1390}
1391
Ville Syrjäläab330812017-04-21 21:14:32 +03001392static const uint32_t g4x_plane_formats[] = {
Chris Wilsond1686ae2012-04-10 11:41:49 +01001393 DRM_FORMAT_XRGB8888,
1394 DRM_FORMAT_YUYV,
1395 DRM_FORMAT_YVYU,
1396 DRM_FORMAT_UYVY,
1397 DRM_FORMAT_VYUY,
1398};
1399
Ben Widawsky714244e2017-08-01 09:58:16 -07001400static const uint64_t i9xx_plane_format_modifiers[] = {
1401 I915_FORMAT_MOD_X_TILED,
1402 DRM_FORMAT_MOD_LINEAR,
1403 DRM_FORMAT_MOD_INVALID
1404};
1405
Damien Lespiaudada2d52015-05-12 16:13:22 +01001406static const uint32_t snb_plane_formats[] = {
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001407 DRM_FORMAT_XBGR8888,
1408 DRM_FORMAT_XRGB8888,
1409 DRM_FORMAT_YUYV,
1410 DRM_FORMAT_YVYU,
1411 DRM_FORMAT_UYVY,
1412 DRM_FORMAT_VYUY,
1413};
1414
Damien Lespiaudada2d52015-05-12 16:13:22 +01001415static const uint32_t vlv_plane_formats[] = {
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001416 DRM_FORMAT_RGB565,
1417 DRM_FORMAT_ABGR8888,
1418 DRM_FORMAT_ARGB8888,
1419 DRM_FORMAT_XBGR8888,
1420 DRM_FORMAT_XRGB8888,
1421 DRM_FORMAT_XBGR2101010,
1422 DRM_FORMAT_ABGR2101010,
1423 DRM_FORMAT_YUYV,
1424 DRM_FORMAT_YVYU,
1425 DRM_FORMAT_UYVY,
1426 DRM_FORMAT_VYUY,
1427};
1428
Damien Lespiaudc2a41b2013-12-04 00:49:41 +00001429static uint32_t skl_plane_formats[] = {
1430 DRM_FORMAT_RGB565,
1431 DRM_FORMAT_ABGR8888,
1432 DRM_FORMAT_ARGB8888,
1433 DRM_FORMAT_XBGR8888,
1434 DRM_FORMAT_XRGB8888,
1435 DRM_FORMAT_YUYV,
1436 DRM_FORMAT_YVYU,
1437 DRM_FORMAT_UYVY,
1438 DRM_FORMAT_VYUY,
1439};
1440
Chandra Konduru429204f2018-05-12 03:03:17 +05301441static uint32_t skl_planar_formats[] = {
1442 DRM_FORMAT_RGB565,
1443 DRM_FORMAT_ABGR8888,
1444 DRM_FORMAT_ARGB8888,
1445 DRM_FORMAT_XBGR8888,
1446 DRM_FORMAT_XRGB8888,
1447 DRM_FORMAT_YUYV,
1448 DRM_FORMAT_YVYU,
1449 DRM_FORMAT_UYVY,
1450 DRM_FORMAT_VYUY,
1451 DRM_FORMAT_NV12,
1452};
1453
Ville Syrjälä77064e22017-12-22 21:22:28 +02001454static const uint64_t skl_plane_format_modifiers_noccs[] = {
1455 I915_FORMAT_MOD_Yf_TILED,
1456 I915_FORMAT_MOD_Y_TILED,
1457 I915_FORMAT_MOD_X_TILED,
1458 DRM_FORMAT_MOD_LINEAR,
1459 DRM_FORMAT_MOD_INVALID
1460};
1461
1462static const uint64_t skl_plane_format_modifiers_ccs[] = {
1463 I915_FORMAT_MOD_Yf_TILED_CCS,
1464 I915_FORMAT_MOD_Y_TILED_CCS,
Ville Syrjälä74ac1602017-12-22 21:22:26 +02001465 I915_FORMAT_MOD_Yf_TILED,
1466 I915_FORMAT_MOD_Y_TILED,
Ben Widawsky714244e2017-08-01 09:58:16 -07001467 I915_FORMAT_MOD_X_TILED,
1468 DRM_FORMAT_MOD_LINEAR,
1469 DRM_FORMAT_MOD_INVALID
1470};
1471
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001472static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1473 u32 format, u64 modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001474{
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001475 switch (modifier) {
1476 case DRM_FORMAT_MOD_LINEAR:
1477 case I915_FORMAT_MOD_X_TILED:
1478 break;
1479 default:
1480 return false;
1481 }
1482
Ben Widawsky714244e2017-08-01 09:58:16 -07001483 switch (format) {
Ben Widawsky714244e2017-08-01 09:58:16 -07001484 case DRM_FORMAT_XRGB8888:
1485 case DRM_FORMAT_YUYV:
1486 case DRM_FORMAT_YVYU:
1487 case DRM_FORMAT_UYVY:
1488 case DRM_FORMAT_VYUY:
1489 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1490 modifier == I915_FORMAT_MOD_X_TILED)
1491 return true;
1492 /* fall through */
1493 default:
1494 return false;
1495 }
1496}
1497
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001498static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1499 u32 format, u64 modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001500{
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001501 switch (modifier) {
1502 case DRM_FORMAT_MOD_LINEAR:
1503 case I915_FORMAT_MOD_X_TILED:
1504 break;
1505 default:
1506 return false;
1507 }
1508
Ben Widawsky714244e2017-08-01 09:58:16 -07001509 switch (format) {
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001510 case DRM_FORMAT_XRGB8888:
1511 case DRM_FORMAT_XBGR8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001512 case DRM_FORMAT_YUYV:
1513 case DRM_FORMAT_YVYU:
1514 case DRM_FORMAT_UYVY:
1515 case DRM_FORMAT_VYUY:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001516 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1517 modifier == I915_FORMAT_MOD_X_TILED)
1518 return true;
1519 /* fall through */
1520 default:
1521 return false;
1522 }
1523}
1524
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001525static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1526 u32 format, u64 modifier)
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001527{
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001528 switch (modifier) {
1529 case DRM_FORMAT_MOD_LINEAR:
1530 case I915_FORMAT_MOD_X_TILED:
1531 break;
1532 default:
1533 return false;
1534 }
1535
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001536 switch (format) {
Ben Widawsky714244e2017-08-01 09:58:16 -07001537 case DRM_FORMAT_RGB565:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001538 case DRM_FORMAT_ABGR8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001539 case DRM_FORMAT_ARGB8888:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001540 case DRM_FORMAT_XBGR8888:
1541 case DRM_FORMAT_XRGB8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001542 case DRM_FORMAT_XBGR2101010:
1543 case DRM_FORMAT_ABGR2101010:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001544 case DRM_FORMAT_YUYV:
1545 case DRM_FORMAT_YVYU:
1546 case DRM_FORMAT_UYVY:
1547 case DRM_FORMAT_VYUY:
Ben Widawsky714244e2017-08-01 09:58:16 -07001548 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1549 modifier == I915_FORMAT_MOD_X_TILED)
1550 return true;
1551 /* fall through */
1552 default:
1553 return false;
1554 }
1555}
1556
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001557static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
1558 u32 format, u64 modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001559{
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001560 struct intel_plane *plane = to_intel_plane(_plane);
1561
1562 switch (modifier) {
1563 case DRM_FORMAT_MOD_LINEAR:
1564 case I915_FORMAT_MOD_X_TILED:
1565 case I915_FORMAT_MOD_Y_TILED:
1566 case I915_FORMAT_MOD_Yf_TILED:
1567 break;
1568 case I915_FORMAT_MOD_Y_TILED_CCS:
1569 case I915_FORMAT_MOD_Yf_TILED_CCS:
1570 if (!plane->has_ccs)
1571 return false;
1572 break;
1573 default:
1574 return false;
1575 }
1576
Ben Widawsky714244e2017-08-01 09:58:16 -07001577 switch (format) {
1578 case DRM_FORMAT_XRGB8888:
1579 case DRM_FORMAT_XBGR8888:
1580 case DRM_FORMAT_ARGB8888:
1581 case DRM_FORMAT_ABGR8888:
Dhinakaran Pandiyan63eaf9a2018-08-22 12:38:27 -07001582 if (is_ccs_modifier(modifier))
Ville Syrjälä77064e22017-12-22 21:22:28 +02001583 return true;
1584 /* fall through */
Ben Widawsky714244e2017-08-01 09:58:16 -07001585 case DRM_FORMAT_RGB565:
1586 case DRM_FORMAT_XRGB2101010:
1587 case DRM_FORMAT_XBGR2101010:
1588 case DRM_FORMAT_YUYV:
1589 case DRM_FORMAT_YVYU:
1590 case DRM_FORMAT_UYVY:
1591 case DRM_FORMAT_VYUY:
Chandra Konduru429204f2018-05-12 03:03:17 +05301592 case DRM_FORMAT_NV12:
Ben Widawsky714244e2017-08-01 09:58:16 -07001593 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1594 return true;
1595 /* fall through */
1596 case DRM_FORMAT_C8:
1597 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1598 modifier == I915_FORMAT_MOD_X_TILED ||
1599 modifier == I915_FORMAT_MOD_Y_TILED)
1600 return true;
1601 /* fall through */
1602 default:
1603 return false;
1604 }
1605}
1606
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001607static const struct drm_plane_funcs g4x_sprite_funcs = {
Ville Syrjäläb4686c42018-05-30 19:59:22 +03001608 .update_plane = drm_atomic_helper_update_plane,
1609 .disable_plane = drm_atomic_helper_disable_plane,
1610 .destroy = intel_plane_destroy,
1611 .atomic_get_property = intel_plane_atomic_get_property,
1612 .atomic_set_property = intel_plane_atomic_set_property,
1613 .atomic_duplicate_state = intel_plane_duplicate_state,
1614 .atomic_destroy_state = intel_plane_destroy_state,
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001615 .format_mod_supported = g4x_sprite_format_mod_supported,
1616};
Ben Widawsky714244e2017-08-01 09:58:16 -07001617
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001618static const struct drm_plane_funcs snb_sprite_funcs = {
1619 .update_plane = drm_atomic_helper_update_plane,
1620 .disable_plane = drm_atomic_helper_disable_plane,
1621 .destroy = intel_plane_destroy,
1622 .atomic_get_property = intel_plane_atomic_get_property,
1623 .atomic_set_property = intel_plane_atomic_set_property,
1624 .atomic_duplicate_state = intel_plane_duplicate_state,
1625 .atomic_destroy_state = intel_plane_destroy_state,
1626 .format_mod_supported = snb_sprite_format_mod_supported,
1627};
Ben Widawsky714244e2017-08-01 09:58:16 -07001628
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001629static const struct drm_plane_funcs vlv_sprite_funcs = {
1630 .update_plane = drm_atomic_helper_update_plane,
1631 .disable_plane = drm_atomic_helper_disable_plane,
1632 .destroy = intel_plane_destroy,
1633 .atomic_get_property = intel_plane_atomic_get_property,
1634 .atomic_set_property = intel_plane_atomic_set_property,
1635 .atomic_duplicate_state = intel_plane_duplicate_state,
1636 .atomic_destroy_state = intel_plane_destroy_state,
1637 .format_mod_supported = vlv_sprite_format_mod_supported,
1638};
Ben Widawsky714244e2017-08-01 09:58:16 -07001639
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001640static const struct drm_plane_funcs skl_plane_funcs = {
1641 .update_plane = drm_atomic_helper_update_plane,
1642 .disable_plane = drm_atomic_helper_disable_plane,
1643 .destroy = intel_plane_destroy,
1644 .atomic_get_property = intel_plane_atomic_get_property,
1645 .atomic_set_property = intel_plane_atomic_set_property,
1646 .atomic_duplicate_state = intel_plane_duplicate_state,
1647 .atomic_destroy_state = intel_plane_destroy_state,
1648 .format_mod_supported = skl_plane_format_mod_supported,
Ben Widawsky714244e2017-08-01 09:58:16 -07001649};
1650
Ville Syrjälä77064e22017-12-22 21:22:28 +02001651bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1652 enum pipe pipe, enum plane_id plane_id)
1653{
1654 if (plane_id == PLANE_CURSOR)
1655 return false;
1656
1657 if (INTEL_GEN(dev_priv) >= 10)
1658 return true;
1659
1660 if (IS_GEMINILAKE(dev_priv))
1661 return pipe != PIPE_C;
1662
1663 return pipe != PIPE_C &&
1664 (plane_id == PLANE_PRIMARY ||
1665 plane_id == PLANE_SPRITE0);
1666}
1667
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001668struct intel_plane *
Ville Syrjälä580503c2016-10-31 22:37:00 +02001669intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1670 enum pipe pipe, int plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001671{
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001672 struct intel_plane *intel_plane = NULL;
1673 struct intel_plane_state *state = NULL;
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001674 const struct drm_plane_funcs *plane_funcs;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001675 unsigned long possible_crtcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001676 const uint32_t *plane_formats;
Ben Widawsky714244e2017-08-01 09:58:16 -07001677 const uint64_t *modifiers;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001678 unsigned int supported_rotations;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001679 int num_plane_formats;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001680 int ret;
1681
Daniel Vetterb14c5672013-09-19 12:18:32 +02001682 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001683 if (!intel_plane) {
1684 ret = -ENOMEM;
1685 goto fail;
1686 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001687
Matt Roper8e7d6882015-01-21 16:35:41 -08001688 state = intel_create_plane_state(&intel_plane->base);
1689 if (!state) {
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001690 ret = -ENOMEM;
1691 goto fail;
Matt Roperea2c67b2014-12-23 10:41:52 -08001692 }
Matt Roper8e7d6882015-01-21 16:35:41 -08001693 intel_plane->base.state = &state->base;
Matt Roperea2c67b2014-12-23 10:41:52 -08001694
Ville Syrjälä77064e22017-12-22 21:22:28 +02001695 if (INTEL_GEN(dev_priv) >= 9) {
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001696 state->scaler_id = -1;
1697
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001698 intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
1699 PLANE_SPRITE0 + plane);
1700
Ville Syrjäläddd57132018-09-07 18:24:02 +03001701 intel_plane->max_stride = skl_plane_max_stride;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001702 intel_plane->update_plane = skl_update_plane;
1703 intel_plane->disable_plane = skl_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001704 intel_plane->get_hw_state = skl_plane_get_hw_state;
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001705 intel_plane->check_plane = skl_plane_check;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001706
Chandra Konduru429204f2018-05-12 03:03:17 +05301707 if (skl_plane_has_planar(dev_priv, pipe,
1708 PLANE_SPRITE0 + plane)) {
1709 plane_formats = skl_planar_formats;
1710 num_plane_formats = ARRAY_SIZE(skl_planar_formats);
1711 } else {
1712 plane_formats = skl_plane_formats;
1713 num_plane_formats = ARRAY_SIZE(skl_plane_formats);
1714 }
Ben Widawsky714244e2017-08-01 09:58:16 -07001715
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001716 if (intel_plane->has_ccs)
Ville Syrjälä77064e22017-12-22 21:22:28 +02001717 modifiers = skl_plane_format_modifiers_ccs;
1718 else
1719 modifiers = skl_plane_format_modifiers_noccs;
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001720
1721 plane_funcs = &skl_plane_funcs;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001722 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
Ville Syrjäläddd57132018-09-07 18:24:02 +03001723 intel_plane->max_stride = i9xx_plane_max_stride;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001724 intel_plane->update_plane = vlv_update_plane;
1725 intel_plane->disable_plane = vlv_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001726 intel_plane->get_hw_state = vlv_plane_get_hw_state;
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001727 intel_plane->check_plane = vlv_sprite_check;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001728
1729 plane_formats = vlv_plane_formats;
1730 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
Ben Widawsky714244e2017-08-01 09:58:16 -07001731 modifiers = i9xx_plane_format_modifiers;
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001732
1733 plane_funcs = &vlv_sprite_funcs;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001734 } else if (INTEL_GEN(dev_priv) >= 7) {
Ville Syrjäläddd57132018-09-07 18:24:02 +03001735 intel_plane->max_stride = g4x_sprite_max_stride;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001736 intel_plane->update_plane = ivb_update_plane;
1737 intel_plane->disable_plane = ivb_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001738 intel_plane->get_hw_state = ivb_plane_get_hw_state;
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001739 intel_plane->check_plane = g4x_sprite_check;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001740
1741 plane_formats = snb_plane_formats;
1742 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
Ben Widawsky714244e2017-08-01 09:58:16 -07001743 modifiers = i9xx_plane_format_modifiers;
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001744
1745 plane_funcs = &snb_sprite_funcs;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001746 } else {
Ville Syrjäläddd57132018-09-07 18:24:02 +03001747 intel_plane->max_stride = g4x_sprite_max_stride;
Ville Syrjäläab330812017-04-21 21:14:32 +03001748 intel_plane->update_plane = g4x_update_plane;
1749 intel_plane->disable_plane = g4x_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001750 intel_plane->get_hw_state = g4x_plane_get_hw_state;
Ville Syrjälä4e0b83a2018-09-07 18:24:09 +03001751 intel_plane->check_plane = g4x_sprite_check;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001752
Ben Widawsky714244e2017-08-01 09:58:16 -07001753 modifiers = i9xx_plane_format_modifiers;
Tvrtko Ursulin5db94012016-10-13 11:03:10 +01001754 if (IS_GEN6(dev_priv)) {
Chris Wilsond1686ae2012-04-10 11:41:49 +01001755 plane_formats = snb_plane_formats;
1756 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001757
1758 plane_funcs = &snb_sprite_funcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001759 } else {
Ville Syrjäläab330812017-04-21 21:14:32 +03001760 plane_formats = g4x_plane_formats;
1761 num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001762
1763 plane_funcs = &g4x_sprite_funcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001764 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001765 }
1766
Dave Airlie5481e272016-10-25 16:36:13 +10001767 if (INTEL_GEN(dev_priv) >= 9) {
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001768 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001769 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
1770 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
Ville Syrjälä4ea7be22016-11-14 18:54:00 +02001771 } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1772 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001773 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1774 DRM_MODE_REFLECT_X;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001775 } else {
1776 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001777 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001778 }
1779
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001780 intel_plane->pipe = pipe;
Ville Syrjäläed150302017-11-17 21:19:10 +02001781 intel_plane->i9xx_plane = plane;
Ville Syrjäläb14e5842016-11-22 18:01:56 +02001782 intel_plane->id = PLANE_SPRITE0 + plane;
Ville Syrjäläc19e1122018-01-23 20:33:43 +02001783 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001784
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001785 possible_crtcs = (1 << pipe);
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001786
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001787 if (INTEL_GEN(dev_priv) >= 9)
Ville Syrjälä580503c2016-10-31 22:37:00 +02001788 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001789 possible_crtcs, plane_funcs,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001790 plane_formats, num_plane_formats,
Ben Widawsky714244e2017-08-01 09:58:16 -07001791 modifiers,
1792 DRM_PLANE_TYPE_OVERLAY,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001793 "plane %d%c", plane + 2, pipe_name(pipe));
1794 else
Ville Syrjälä580503c2016-10-31 22:37:00 +02001795 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
Ville Syrjäläa38189c2018-05-18 19:21:59 +03001796 possible_crtcs, plane_funcs,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001797 plane_formats, num_plane_formats,
Ben Widawsky714244e2017-08-01 09:58:16 -07001798 modifiers,
1799 DRM_PLANE_TYPE_OVERLAY,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001800 "sprite %c", sprite_name(pipe, plane));
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001801 if (ret)
1802 goto fail;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001803
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001804 drm_plane_create_rotation_property(&intel_plane->base,
Robert Fossc2c446a2017-05-19 16:50:17 -04001805 DRM_MODE_ROTATE_0,
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001806 supported_rotations);
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301807
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +02001808 drm_plane_create_color_properties(&intel_plane->base,
1809 BIT(DRM_COLOR_YCBCR_BT601) |
1810 BIT(DRM_COLOR_YCBCR_BT709),
Ville Syrjäläc8624ed2018-02-14 21:23:27 +02001811 BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1812 BIT(DRM_COLOR_YCBCR_FULL_RANGE),
Ville Syrjälä23b28082018-02-14 21:23:26 +02001813 DRM_COLOR_YCBCR_BT709,
Ville Syrjäläb0f5c0b2018-02-14 21:23:25 +02001814 DRM_COLOR_YCBCR_LIMITED_RANGE);
1815
Matt Roperea2c67b2014-12-23 10:41:52 -08001816 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1817
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001818 return intel_plane;
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001819
1820fail:
1821 kfree(state);
1822 kfree(intel_plane);
1823
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001824 return ERR_PTR(ret);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001825}