blob: 3025c609d6882d69fa39ce070167b1bd33a17e06 [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ä38f24f22018-02-14 21:23:24 +020044bool intel_format_is_yuv(u32 format)
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +030045{
46 switch (format) {
47 case DRM_FORMAT_YUYV:
48 case DRM_FORMAT_UYVY:
49 case DRM_FORMAT_VYUY:
50 case DRM_FORMAT_YVYU:
51 return true;
52 default:
53 return false;
54 }
55}
56
Ville Syrjälädfd2e9a2016-05-18 11:34:38 +030057int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
58 int usecs)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030059{
60 /* paranoia */
Ville Syrjälä5e7234c2015-09-25 16:37:43 +030061 if (!adjusted_mode->crtc_htotal)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030062 return 1;
63
Ville Syrjälä5e7234c2015-09-25 16:37:43 +030064 return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
65 1000 * adjusted_mode->crtc_htotal);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030066}
67
Daniel Vetter69208c92017-10-10 11:18:16 +020068/* FIXME: We should instead only take spinlocks once for the entire update
69 * instead of once per mmio. */
70#if IS_ENABLED(CONFIG_PROVE_LOCKING)
71#define VBLANK_EVASION_TIME_US 250
72#else
Maarten Lankhorste1edbd42017-02-28 15:28:48 +010073#define VBLANK_EVASION_TIME_US 100
Daniel Vetter69208c92017-10-10 11:18:16 +020074#endif
Maarten Lankhorste1edbd42017-02-28 15:28:48 +010075
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020076/**
77 * intel_pipe_update_start() - start update of a set of display registers
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030078 * @new_crtc_state: the new crtc state
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020079 *
80 * Mark the start of an update to pipe registers that should be updated
81 * atomically regarding vblank. If the next vblank will happens within
82 * the next 100 us, this function waits until the vblank passes.
83 *
84 * After a successful call to this function, interrupts will be disabled
85 * until a subsequent call to intel_pipe_update_end(). That is done to
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030086 * avoid random delays.
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +020087 */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030088void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030089{
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030090 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +020091 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030092 const struct drm_display_mode *adjusted_mode = &new_crtc_state->base.adjusted_mode;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030093 long timeout = msecs_to_jiffies_timeout(1);
94 int scanline, min, max, vblank_start;
Ville Syrjälä210871b62014-05-22 19:00:50 +030095 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +020096 bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +030097 intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +030098 DEFINE_WAIT(wait);
99
Ville Syrjälä124abe02015-09-08 13:40:45 +0300100 vblank_start = adjusted_mode->crtc_vblank_start;
101 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300102 vblank_start = DIV_ROUND_UP(vblank_start, 2);
103
104 /* FIXME needs to be calibrated sensibly */
Maarten Lankhorste1edbd42017-02-28 15:28:48 +0100105 min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
106 VBLANK_EVASION_TIME_US);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300107 max = vblank_start - 1;
108
Maarten Lankhorst8f539a832015-07-13 16:30:32 +0200109 local_irq_disable();
Maarten Lankhorst8f539a832015-07-13 16:30:32 +0200110
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300111 if (min <= 0 || max <= 0)
Maarten Lankhorst8f539a832015-07-13 16:30:32 +0200112 return;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300113
Daniel Vetter1e3feef2015-02-13 21:03:45 +0100114 if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
Maarten Lankhorst8f539a832015-07-13 16:30:32 +0200115 return;
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300116
Jesse Barnesd637ce32015-09-17 08:08:32 -0700117 crtc->debug.min_vbl = min;
118 crtc->debug.max_vbl = max;
119 trace_i915_pipe_update_start(crtc);
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300120
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300121 for (;;) {
122 /*
123 * prepare_to_wait() has a memory barrier, which guarantees
124 * other CPUs can see the task state update by the time we
125 * read the scanline.
126 */
Ville Syrjälä210871b62014-05-22 19:00:50 +0300127 prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300128
129 scanline = intel_get_crtc_scanline(crtc);
130 if (scanline < min || scanline > max)
131 break;
132
133 if (timeout <= 0) {
134 DRM_ERROR("Potential atomic update failure on pipe %c\n",
135 pipe_name(crtc->pipe));
136 break;
137 }
138
139 local_irq_enable();
140
141 timeout = schedule_timeout(timeout);
142
143 local_irq_disable();
144 }
145
Ville Syrjälä210871b62014-05-22 19:00:50 +0300146 finish_wait(wq, &wait);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300147
Daniel Vetter1e3feef2015-02-13 21:03:45 +0100148 drm_crtc_vblank_put(&crtc->base);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300149
Ville Syrjäläec1b4ee2016-12-15 19:47:34 +0200150 /*
151 * On VLV/CHV DSI the scanline counter would appear to
152 * increment approx. 1/3 of a scanline before start of vblank.
153 * The registers still get latched at start of vblank however.
154 * This means we must not write any registers on the first
155 * line of vblank (since not the whole line is actually in
156 * vblank). And unfortunately we can't use the interrupt to
157 * wait here since it will fire too soon. We could use the
158 * frame start interrupt instead since it will fire after the
159 * critical scanline, but that would require more changes
160 * in the interrupt code. So for now we'll just do the nasty
161 * thing and poll for the bad scanline to pass us by.
162 *
163 * FIXME figure out if BXT+ DSI suffers from this as well
164 */
165 while (need_vlv_dsi_wa && scanline == vblank_start)
166 scanline = intel_get_crtc_scanline(crtc);
167
Jesse Barneseb120ef2015-09-15 14:19:32 -0700168 crtc->debug.scanline_start = scanline;
169 crtc->debug.start_vbl_time = ktime_get();
Maarten Lankhorsta2991412016-05-17 15:07:48 +0200170 crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300171
Jesse Barnesd637ce32015-09-17 08:08:32 -0700172 trace_i915_pipe_update_vblank_evaded(crtc);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300173}
174
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200175/**
176 * intel_pipe_update_end() - end update of a set of display registers
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300177 * @new_crtc_state: the new crtc state
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200178 *
179 * Mark the end of an update started with intel_pipe_update_start(). This
180 * re-enables interrupts and verifies the update was actually completed
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300181 * before a vblank.
Ander Conselvan de Oliveira26ff2762014-10-28 15:10:12 +0200182 */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300183void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300184{
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300185 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->base.crtc);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300186 enum pipe pipe = crtc->pipe;
Jesse Barneseb120ef2015-09-15 14:19:32 -0700187 int scanline_end = intel_get_crtc_scanline(crtc);
Maarten Lankhorsta2991412016-05-17 15:07:48 +0200188 u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
Maarten Lankhorst85a62bf2015-09-01 12:15:33 +0200189 ktime_t end_vbl_time = ktime_get();
Bing Niua94f2b92017-03-08 15:14:03 -0500190 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300191
Jesse Barnesd637ce32015-09-17 08:08:32 -0700192 trace_i915_pipe_update_end(crtc, end_vbl_count, scanline_end);
Ville Syrjälä25ef2842014-04-29 13:35:48 +0300193
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200194 /* We're still in the vblank-evade critical section, this can't race.
195 * Would be slightly nice to just grab the vblank count and arm the
196 * event outside of the critical section - the spinlock might spin for a
197 * while ... */
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300198 if (new_crtc_state->base.event) {
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200199 WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
200
201 spin_lock(&crtc->base.dev->event_lock);
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300202 drm_crtc_arm_vblank_event(&crtc->base, new_crtc_state->base.event);
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200203 spin_unlock(&crtc->base.dev->event_lock);
204
Ville Syrjäläd3a8fb32017-08-23 18:22:21 +0300205 new_crtc_state->base.event = NULL;
Daniel Vetter1f7528c2016-06-13 16:13:45 +0200206 }
207
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300208 local_irq_enable();
209
Bing Niua94f2b92017-03-08 15:14:03 -0500210 if (intel_vgpu_active(dev_priv))
211 return;
212
Jesse Barneseb120ef2015-09-15 14:19:32 -0700213 if (crtc->debug.start_vbl_count &&
214 crtc->debug.start_vbl_count != end_vbl_count) {
215 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",
216 pipe_name(pipe), crtc->debug.start_vbl_count,
217 end_vbl_count,
218 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
219 crtc->debug.min_vbl, crtc->debug.max_vbl,
220 crtc->debug.scanline_start, scanline_end);
Ville Syrjälä7b8cd332017-05-07 20:12:52 +0300221 }
222#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
223 else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
224 VBLANK_EVASION_TIME_US)
Maarten Lankhorste1edbd42017-02-28 15:28:48 +0100225 DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
226 pipe_name(pipe),
227 ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
228 VBLANK_EVASION_TIME_US);
Ville Syrjälä7b8cd332017-05-07 20:12:52 +0300229#endif
Ville Syrjälä8d7849d2014-04-29 13:35:46 +0300230}
231
Juha-Pekka Heikkila9a8cc572017-10-17 23:08:09 +0300232void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300233skl_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100234 const struct intel_crtc_state *crtc_state,
235 const struct intel_plane_state *plane_state)
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000236{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300237 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
238 const struct drm_framebuffer *fb = plane_state->base.fb;
239 enum plane_id plane_id = plane->id;
240 enum pipe pipe = plane->pipe;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200241 u32 plane_ctl = plane_state->ctl;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100242 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjäläb63a16f2016-01-28 16:53:54 +0200243 u32 surf_addr = plane_state->main.offset;
Ville Syrjälä8d0deca2016-02-15 22:54:41 +0200244 unsigned int rotation = plane_state->base.rotation;
Ville Syrjäläd2196772016-01-28 18:33:11 +0200245 u32 stride = skl_plane_stride(fb, 0, rotation);
Ville Syrjälä2e2adb02017-08-01 09:58:13 -0700246 u32 aux_stride = skl_plane_stride(fb, 1, rotation);
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300247 int crtc_x = plane_state->base.dst.x1;
248 int crtc_y = plane_state->base.dst.y1;
249 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
250 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
Ville Syrjäläb63a16f2016-01-28 16:53:54 +0200251 uint32_t x = plane_state->main.x;
252 uint32_t y = plane_state->main.y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300253 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
254 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200255 unsigned long irqflags;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000256
Ville Syrjälä6687c902015-09-15 13:16:41 +0300257 /* Sizes are 0 based */
258 src_w--;
259 src_h--;
260 crtc_w--;
261 crtc_h--;
262
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200263 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
264
James Ausmus4036c782017-11-13 10:11:28 -0800265 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200266 I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id),
James Ausmus4036c782017-11-13 10:11:28 -0800267 plane_state->color_ctl);
Ville Syrjälä38f24f22018-02-14 21:23:24 +0200268
Ville Syrjälä78587de2017-03-09 17:44:32 +0200269 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200270 I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
271 I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), key->max_value);
272 I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), key->channel_mask);
Ville Syrjälä78587de2017-03-09 17:44:32 +0200273 }
274
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200275 I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
276 I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
277 I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
Ville Syrjälä2e2adb02017-08-01 09:58:13 -0700278 I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id),
279 (plane_state->aux.offset - surf_addr) | aux_stride);
280 I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
281 (plane_state->aux.y << 16) | plane_state->aux.x);
Chandra Konduruc3318792015-04-15 15:15:02 -0700282
283 /* program plane scaler */
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100284 if (plane_state->scaler_id >= 0) {
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100285 int scaler_id = plane_state->scaler_id;
Imre Deak7494bcd2016-05-12 16:18:49 +0300286 const struct intel_scaler *scaler;
Chandra Konduruc3318792015-04-15 15:15:02 -0700287
Imre Deak7494bcd2016-05-12 16:18:49 +0300288 scaler = &crtc_state->scaler_state.scalers[scaler_id];
289
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200290 I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
291 PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
292 I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
293 I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
294 I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
295 ((crtc_w + 1) << 16)|(crtc_h + 1));
Chandra Konduruc3318792015-04-15 15:15:02 -0700296
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200297 I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
Chandra Konduruc3318792015-04-15 15:15:02 -0700298 } else {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200299 I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
Chandra Konduruc3318792015-04-15 15:15:02 -0700300 }
301
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200302 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
303 I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
304 intel_plane_ggtt_offset(plane_state) + surf_addr);
305 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
306
307 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000308}
309
Juha-Pekka Heikkila779d4d82017-10-17 23:08:10 +0300310void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300311skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000312{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300313 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
314 enum plane_id plane_id = plane->id;
315 enum pipe pipe = plane->pipe;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200316 unsigned long irqflags;
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000317
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200318 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000319
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200320 I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
321
322 I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
323 POSTING_READ_FW(PLANE_SURF(pipe, plane_id));
324
325 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000326}
327
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200328bool
329skl_plane_get_hw_state(struct intel_plane *plane)
330{
331 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
332 enum intel_display_power_domain power_domain;
333 enum plane_id plane_id = plane->id;
334 enum pipe pipe = plane->pipe;
335 bool ret;
336
337 power_domain = POWER_DOMAIN_PIPE(pipe);
338 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
339 return false;
340
341 ret = I915_READ(PLANE_CTL(pipe, plane_id)) & PLANE_CTL_ENABLE;
342
343 intel_display_power_put(dev_priv, power_domain);
344
345 return ret;
346}
347
Damien Lespiaudc2a41b2013-12-04 00:49:41 +0000348static void
Ville Syrjälä5deae912018-02-14 21:23:23 +0200349chv_update_csc(const struct intel_plane_state *plane_state)
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300350{
Ville Syrjälä5deae912018-02-14 21:23:23 +0200351 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300352 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
Ville Syrjälä5deae912018-02-14 21:23:23 +0200353 const struct drm_framebuffer *fb = plane_state->base.fb;
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300354 enum plane_id plane_id = plane->id;
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300355
356 /* Seems RGB data bypasses the CSC always */
Ville Syrjälä38f24f22018-02-14 21:23:24 +0200357 if (!intel_format_is_yuv(fb->format->format))
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300358 return;
359
360 /*
Ville Syrjälä5deae912018-02-14 21:23:23 +0200361 * BT.601 full range YCbCr -> full range RGB
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300362 *
Ville Syrjälä5deae912018-02-14 21:23:23 +0200363 * |r| | 5743 4096 0| |cr|
364 * |g| = |-2925 4096 -1410| x |y |
365 * |b| | 0 4096 7258| |cb|
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300366 *
Ville Syrjälä5deae912018-02-14 21:23:23 +0200367 * Cb and Cr apparently come in as signed already,
368 * and we get full range data in on account of CLRC0/1
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300369 */
Ville Syrjälä5deae912018-02-14 21:23:23 +0200370 I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200371 I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
372 I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300373
Ville Syrjälä5deae912018-02-14 21:23:23 +0200374 I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(4096) | SPCSC_C0(5743));
375 I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(-2925) | SPCSC_C0(0));
376 I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(-1410) | SPCSC_C0(4096));
377 I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(4096) | SPCSC_C0(0));
378 I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(7258));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300379
Ville Syrjälä5deae912018-02-14 21:23:23 +0200380 I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
381 I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
382 I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300383
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200384 I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
385 I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
386 I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
Ville Syrjälä6ca2aeb2014-10-20 19:47:53 +0300387}
388
Ville Syrjälä5deae912018-02-14 21:23:23 +0200389#define SIN_0 0
390#define COS_0 1
391
392static void
393vlv_update_clrc(const struct intel_plane_state *plane_state)
394{
395 struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
396 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
397 const struct drm_framebuffer *fb = plane_state->base.fb;
398 enum pipe pipe = plane->pipe;
399 enum plane_id plane_id = plane->id;
400 int contrast, brightness, sh_scale, sh_sin, sh_cos;
401
Ville Syrjälä38f24f22018-02-14 21:23:24 +0200402 if (intel_format_is_yuv(fb->format->format)) {
Ville Syrjälä5deae912018-02-14 21:23:23 +0200403 /*
404 * Expand limited range to full range:
405 * Contrast is applied first and is used to expand Y range.
406 * Brightness is applied second and is used to remove the
407 * offset from Y. Saturation/hue is used to expand CbCr range.
408 */
409 contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
410 brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
411 sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
412 sh_sin = SIN_0 * sh_scale;
413 sh_cos = COS_0 * sh_scale;
414 } else {
415 /* Pass-through everything. */
416 contrast = 1 << 6;
417 brightness = 0;
418 sh_scale = 1 << 7;
419 sh_sin = SIN_0 * sh_scale;
420 sh_cos = COS_0 * sh_scale;
421 }
422
423 /* FIXME these register are single buffered :( */
424 I915_WRITE_FW(SPCLRC0(pipe, plane_id),
425 SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
426 I915_WRITE_FW(SPCLRC1(pipe, plane_id),
427 SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
428}
429
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200430static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
431 const struct intel_plane_state *plane_state)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700432{
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200433 const struct drm_framebuffer *fb = plane_state->base.fb;
Ville Syrjälä11df4d92016-11-07 22:20:55 +0200434 unsigned int rotation = plane_state->base.rotation;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100435 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200436 u32 sprctl;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700437
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200438 sprctl = SP_ENABLE | SP_GAMMA_ENABLE;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700439
Ville Syrjälä438b74a2016-12-14 23:32:55 +0200440 switch (fb->format->format) {
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700441 case DRM_FORMAT_YUYV:
442 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
443 break;
444 case DRM_FORMAT_YVYU:
445 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
446 break;
447 case DRM_FORMAT_UYVY:
448 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
449 break;
450 case DRM_FORMAT_VYUY:
451 sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
452 break;
453 case DRM_FORMAT_RGB565:
454 sprctl |= SP_FORMAT_BGR565;
455 break;
456 case DRM_FORMAT_XRGB8888:
457 sprctl |= SP_FORMAT_BGRX8888;
458 break;
459 case DRM_FORMAT_ARGB8888:
460 sprctl |= SP_FORMAT_BGRA8888;
461 break;
462 case DRM_FORMAT_XBGR2101010:
463 sprctl |= SP_FORMAT_RGBX1010102;
464 break;
465 case DRM_FORMAT_ABGR2101010:
466 sprctl |= SP_FORMAT_RGBA1010102;
467 break;
468 case DRM_FORMAT_XBGR8888:
469 sprctl |= SP_FORMAT_RGBX8888;
470 break;
471 case DRM_FORMAT_ABGR8888:
472 sprctl |= SP_FORMAT_RGBA8888;
473 break;
474 default:
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200475 MISSING_CASE(fb->format->format);
476 return 0;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700477 }
478
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200479 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700480 sprctl |= SP_TILED;
481
Robert Fossc2c446a2017-05-19 16:50:17 -0400482 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälädf0cd452016-11-14 18:53:59 +0200483 sprctl |= SP_ROTATE_180;
484
Robert Fossc2c446a2017-05-19 16:50:17 -0400485 if (rotation & DRM_MODE_REFLECT_X)
Ville Syrjälä4ea7be22016-11-14 18:54:00 +0200486 sprctl |= SP_MIRROR;
487
Ville Syrjälä78587de2017-03-09 17:44:32 +0200488 if (key->flags & I915_SET_COLORKEY_SOURCE)
489 sprctl |= SP_SOURCE_KEY;
490
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200491 return sprctl;
492}
493
494static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300495vlv_update_plane(struct intel_plane *plane,
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200496 const struct intel_crtc_state *crtc_state,
497 const struct intel_plane_state *plane_state)
498{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300499 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
500 const struct drm_framebuffer *fb = plane_state->base.fb;
501 enum pipe pipe = plane->pipe;
502 enum plane_id plane_id = plane->id;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200503 u32 sprctl = plane_state->ctl;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200504 u32 sprsurf_offset = plane_state->main.offset;
505 u32 linear_offset;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200506 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
507 int crtc_x = plane_state->base.dst.x1;
508 int crtc_y = plane_state->base.dst.y1;
509 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
510 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200511 uint32_t x = plane_state->main.x;
512 uint32_t y = plane_state->main.y;
Ville Syrjälä96ef6852017-03-17 23:17:58 +0200513 unsigned long irqflags;
514
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700515 /* Sizes are 0 based */
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700516 crtc_w--;
517 crtc_h--;
518
Ville Syrjälä29490562016-01-20 18:02:50 +0200519 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300520
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200521 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
522
Ville Syrjälä5deae912018-02-14 21:23:23 +0200523 vlv_update_clrc(plane_state);
524
Ville Syrjälä78587de2017-03-09 17:44:32 +0200525 if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
Ville Syrjälä5deae912018-02-14 21:23:23 +0200526 chv_update_csc(plane_state);
Ville Syrjälä78587de2017-03-09 17:44:32 +0200527
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200528 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200529 I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
530 I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
531 I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200532 }
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200533 I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]);
534 I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200535
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200536 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200537 I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700538 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200539 I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700540
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200541 I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
Ville Syrjäläc14b0482014-10-16 20:52:34 +0300542
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200543 I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
544 I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
545 I915_WRITE_FW(SPSURF(pipe, plane_id),
546 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
547 POSTING_READ_FW(SPSURF(pipe, plane_id));
548
549 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700550}
551
552static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300553vlv_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700554{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300555 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
556 enum pipe pipe = plane->pipe;
557 enum plane_id plane_id = plane->id;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200558 unsigned long irqflags;
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700559
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200560 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
Ville Syrjälä48fe4692015-03-19 17:57:13 +0200561
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200562 I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
563
564 I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
565 POSTING_READ_FW(SPSURF(pipe, plane_id));
566
567 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700568}
569
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200570static bool
571vlv_plane_get_hw_state(struct intel_plane *plane)
572{
573 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
574 enum intel_display_power_domain power_domain;
575 enum plane_id plane_id = plane->id;
576 enum pipe pipe = plane->pipe;
577 bool ret;
578
579 power_domain = POWER_DOMAIN_PIPE(pipe);
580 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
581 return false;
582
583 ret = I915_READ(SPCNTR(pipe, plane_id)) & SP_ENABLE;
584
585 intel_display_power_put(dev_priv, power_domain);
586
587 return ret;
588}
589
Ville Syrjälä45dea7b2017-03-17 23:17:59 +0200590static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
591 const struct intel_plane_state *plane_state)
592{
593 struct drm_i915_private *dev_priv =
594 to_i915(plane_state->base.plane->dev);
595 const struct drm_framebuffer *fb = plane_state->base.fb;
596 unsigned int rotation = plane_state->base.rotation;
597 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
598 u32 sprctl;
599
600 sprctl = SPRITE_ENABLE | SPRITE_GAMMA_ENABLE;
601
602 if (IS_IVYBRIDGE(dev_priv))
603 sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
604
605 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
606 sprctl |= SPRITE_PIPE_CSC_ENABLE;
607
608 switch (fb->format->format) {
609 case DRM_FORMAT_XBGR8888:
610 sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
611 break;
612 case DRM_FORMAT_XRGB8888:
613 sprctl |= SPRITE_FORMAT_RGBX888;
614 break;
615 case DRM_FORMAT_YUYV:
616 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
617 break;
618 case DRM_FORMAT_YVYU:
619 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
620 break;
621 case DRM_FORMAT_UYVY:
622 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
623 break;
624 case DRM_FORMAT_VYUY:
625 sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
626 break;
627 default:
628 MISSING_CASE(fb->format->format);
629 return 0;
630 }
631
632 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
633 sprctl |= SPRITE_TILED;
634
Robert Fossc2c446a2017-05-19 16:50:17 -0400635 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälä45dea7b2017-03-17 23:17:59 +0200636 sprctl |= SPRITE_ROTATE_180;
637
638 if (key->flags & I915_SET_COLORKEY_DESTINATION)
639 sprctl |= SPRITE_DEST_KEY;
640 else if (key->flags & I915_SET_COLORKEY_SOURCE)
641 sprctl |= SPRITE_SOURCE_KEY;
642
643 return sprctl;
644}
645
Jesse Barnes7f1f3852013-04-02 11:22:20 -0700646static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300647ivb_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100648 const struct intel_crtc_state *crtc_state,
649 const struct intel_plane_state *plane_state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800650{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300651 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
652 const struct drm_framebuffer *fb = plane_state->base.fb;
653 enum pipe pipe = plane->pipe;
Ville Syrjäläa0864d52017-03-23 21:27:09 +0200654 u32 sprctl = plane_state->ctl, sprscale = 0;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200655 u32 sprsurf_offset = plane_state->main.offset;
656 u32 linear_offset;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100657 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300658 int crtc_x = plane_state->base.dst.x1;
659 int crtc_y = plane_state->base.dst.y1;
660 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
661 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200662 uint32_t x = plane_state->main.x;
663 uint32_t y = plane_state->main.y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300664 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
665 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200666 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800667
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800668 /* Sizes are 0 based */
669 src_w--;
670 src_h--;
671 crtc_w--;
672 crtc_h--;
673
Ville Syrjälä8553c182013-12-05 15:51:39 +0200674 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800675 sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800676
Ville Syrjälä29490562016-01-20 18:02:50 +0200677 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300678
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200679 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
680
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200681 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200682 I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
683 I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
684 I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200685 }
686
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200687 I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]);
688 I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200689
Damien Lespiau5a35e992012-10-26 18:20:12 +0100690 /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
691 * register */
Tvrtko Ursulin86527442016-10-13 11:03:00 +0100692 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200693 I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200694 else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200695 I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100696 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200697 I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
Damien Lespiauc54173a2012-10-26 18:20:11 +0100698
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200699 I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300700 if (plane->can_scale)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200701 I915_WRITE_FW(SPRSCALE(pipe), sprscale);
702 I915_WRITE_FW(SPRCTL(pipe), sprctl);
703 I915_WRITE_FW(SPRSURF(pipe),
704 intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
705 POSTING_READ_FW(SPRSURF(pipe));
706
707 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800708}
709
710static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300711ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800712{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300713 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
714 enum pipe pipe = plane->pipe;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200715 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800716
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200717 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
718
719 I915_WRITE_FW(SPRCTL(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800720 /* Can't leave the scaler enabled... */
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300721 if (plane->can_scale)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200722 I915_WRITE_FW(SPRSCALE(pipe), 0);
Ville Syrjälä5b633d62014-04-29 13:35:47 +0300723
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200724 I915_WRITE_FW(SPRSURF(pipe), 0);
725 POSTING_READ_FW(SPRSURF(pipe));
726
727 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800728}
729
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200730static bool
731ivb_plane_get_hw_state(struct intel_plane *plane)
732{
733 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
734 enum intel_display_power_domain power_domain;
735 enum pipe pipe = plane->pipe;
736 bool ret;
737
738 power_domain = POWER_DOMAIN_PIPE(pipe);
739 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
740 return false;
741
742 ret = I915_READ(SPRCTL(pipe)) & SPRITE_ENABLE;
743
744 intel_display_power_put(dev_priv, power_domain);
745
746 return ret;
747}
748
Ville Syrjäläab330812017-04-21 21:14:32 +0300749static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
Ville Syrjälä0a375142017-03-17 23:18:00 +0200750 const struct intel_plane_state *plane_state)
751{
752 struct drm_i915_private *dev_priv =
753 to_i915(plane_state->base.plane->dev);
754 const struct drm_framebuffer *fb = plane_state->base.fb;
755 unsigned int rotation = plane_state->base.rotation;
756 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
757 u32 dvscntr;
758
759 dvscntr = DVS_ENABLE | DVS_GAMMA_ENABLE;
760
761 if (IS_GEN6(dev_priv))
762 dvscntr |= DVS_TRICKLE_FEED_DISABLE;
763
764 switch (fb->format->format) {
765 case DRM_FORMAT_XBGR8888:
766 dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
767 break;
768 case DRM_FORMAT_XRGB8888:
769 dvscntr |= DVS_FORMAT_RGBX888;
770 break;
771 case DRM_FORMAT_YUYV:
772 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
773 break;
774 case DRM_FORMAT_YVYU:
775 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
776 break;
777 case DRM_FORMAT_UYVY:
778 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
779 break;
780 case DRM_FORMAT_VYUY:
781 dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
782 break;
783 default:
784 MISSING_CASE(fb->format->format);
785 return 0;
786 }
787
788 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
789 dvscntr |= DVS_TILED;
790
Robert Fossc2c446a2017-05-19 16:50:17 -0400791 if (rotation & DRM_MODE_ROTATE_180)
Ville Syrjälä0a375142017-03-17 23:18:00 +0200792 dvscntr |= DVS_ROTATE_180;
793
794 if (key->flags & I915_SET_COLORKEY_DESTINATION)
795 dvscntr |= DVS_DEST_KEY;
796 else if (key->flags & I915_SET_COLORKEY_SOURCE)
797 dvscntr |= DVS_SOURCE_KEY;
798
799 return dvscntr;
800}
801
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800802static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300803g4x_update_plane(struct intel_plane *plane,
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100804 const struct intel_crtc_state *crtc_state,
805 const struct intel_plane_state *plane_state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800806{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300807 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
808 const struct drm_framebuffer *fb = plane_state->base.fb;
809 enum pipe pipe = plane->pipe;
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200810 u32 dvscntr = plane_state->ctl, dvsscale = 0;
811 u32 dvssurf_offset = plane_state->main.offset;
812 u32 linear_offset;
Maarten Lankhorst2fde1392016-01-07 11:54:06 +0100813 const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300814 int crtc_x = plane_state->base.dst.x1;
815 int crtc_y = plane_state->base.dst.y1;
816 uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
817 uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
Ville Syrjäläf9407ae2017-03-23 21:27:12 +0200818 uint32_t x = plane_state->main.x;
819 uint32_t y = plane_state->main.y;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300820 uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
821 uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200822 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800823
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800824 /* Sizes are 0 based */
825 src_w--;
826 src_h--;
827 crtc_w--;
828 crtc_h--;
829
Ville Syrjälä8368f012013-12-05 15:51:31 +0200830 if (crtc_w != src_w || crtc_h != src_h)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800831 dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
832
Ville Syrjälä29490562016-01-20 18:02:50 +0200833 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
Ville Syrjälä6687c902015-09-15 13:16:41 +0300834
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200835 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
836
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200837 if (key->flags) {
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200838 I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
839 I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
840 I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
Ville Syrjälä47ecbb22015-03-19 21:18:57 +0200841 }
842
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200843 I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]);
844 I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
Ville Syrjäläca6ad022014-01-17 20:09:03 +0200845
Ville Syrjäläbae781b2016-11-16 13:33:16 +0200846 if (fb->modifier == I915_FORMAT_MOD_X_TILED)
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200847 I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100848 else
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200849 I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
Damien Lespiau5a35e992012-10-26 18:20:12 +0100850
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200851 I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
852 I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
853 I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
854 I915_WRITE_FW(DVSSURF(pipe),
855 intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
856 POSTING_READ_FW(DVSSURF(pipe));
857
858 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800859}
860
861static void
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300862g4x_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800863{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300864 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
865 enum pipe pipe = plane->pipe;
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200866 unsigned long irqflags;
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800867
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200868 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
869
870 I915_WRITE_FW(DVSCNTR(pipe), 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800871 /* Disable the scaler */
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200872 I915_WRITE_FW(DVSSCALE(pipe), 0);
Ville Syrjälä48fe4692015-03-19 17:57:13 +0200873
Ville Syrjälädd584fc2017-03-09 17:44:33 +0200874 I915_WRITE_FW(DVSSURF(pipe), 0);
875 POSTING_READ_FW(DVSSURF(pipe));
876
877 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800878}
879
Ville Syrjälä51f5a0962017-11-17 21:19:08 +0200880static bool
881g4x_plane_get_hw_state(struct intel_plane *plane)
882{
883 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
884 enum intel_display_power_domain power_domain;
885 enum pipe pipe = plane->pipe;
886 bool ret;
887
888 power_domain = POWER_DOMAIN_PIPE(pipe);
889 if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
890 return false;
891
892 ret = I915_READ(DVSCNTR(pipe)) & DVS_ENABLE;
893
894 intel_display_power_put(dev_priv, power_domain);
895
896 return ret;
897}
898
Jesse Barnes8ea30862012-01-03 08:05:39 -0800899static int
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300900intel_check_sprite_plane(struct intel_plane *plane,
Maarten Lankhorst061e4b82015-06-15 12:33:46 +0200901 struct intel_crtc_state *crtc_state,
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300902 struct intel_plane_state *state)
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800903{
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300904 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
905 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
Matt Roper2b875c22014-12-01 15:40:13 -0800906 struct drm_framebuffer *fb = state->base.fb;
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300907 int crtc_x, crtc_y;
908 unsigned int crtc_w, crtc_h;
909 uint32_t src_x, src_y, src_w, src_h;
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300910 struct drm_rect *src = &state->base.src;
911 struct drm_rect *dst = &state->base.dst;
Ville Syrjäläa2936e3d2017-11-23 21:04:49 +0200912 struct drm_rect clip = {};
Ville Syrjälä8a97bbc2017-12-22 21:22:29 +0200913 int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
Ville Syrjälä17316932013-04-24 18:52:38 +0300914 int hscale, vscale;
915 int max_scale, min_scale;
Chandra Konduru225c2282015-05-18 16:18:44 -0700916 bool can_scale;
Ville Syrjäläb63a16f2016-01-28 16:53:54 +0200917 int ret;
Matt Ropercf4c7c12014-12-04 10:27:42 -0800918
Rob Clark1638d302016-11-05 11:08:08 -0400919 *src = drm_plane_state_src(&state->base);
920 *dst = drm_plane_state_dest(&state->base);
Ville Syrjäläf8856a42016-07-26 19:07:00 +0300921
Matt Ropercf4c7c12014-12-04 10:27:42 -0800922 if (!fb) {
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300923 state->base.visible = false;
Maarten Lankhorstda20eab2015-06-15 12:33:44 +0200924 return 0;
Matt Ropercf4c7c12014-12-04 10:27:42 -0800925 }
Jesse Barnes5e1bac22013-03-26 09:25:43 -0700926
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800927 /* Don't modify another pipe's plane */
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300928 if (plane->pipe != crtc->pipe) {
Ville Syrjälä17316932013-04-24 18:52:38 +0300929 DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n");
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800930 return -EINVAL;
Ville Syrjälä17316932013-04-24 18:52:38 +0300931 }
932
933 /* FIXME check all gen limits */
Ville Syrjälä8a97bbc2017-12-22 21:22:29 +0200934 if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) {
Ville Syrjälä17316932013-04-24 18:52:38 +0300935 DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n");
936 return -EINVAL;
937 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800938
Chandra Konduru225c2282015-05-18 16:18:44 -0700939 /* setup can_scale, min_scale, max_scale */
Tvrtko Ursulin55b8f2a2016-10-14 09:17:22 +0100940 if (INTEL_GEN(dev_priv) >= 9) {
Chandra Konduru225c2282015-05-18 16:18:44 -0700941 /* use scaler when colorkey is not required */
Ville Syrjälä6ec5bd32018-02-02 22:42:31 +0200942 if (!state->ckey.flags) {
Chandra Konduru225c2282015-05-18 16:18:44 -0700943 can_scale = 1;
944 min_scale = 1;
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300945 max_scale = skl_max_scale(crtc, crtc_state);
Chandra Konduru225c2282015-05-18 16:18:44 -0700946 } else {
947 can_scale = 0;
948 min_scale = DRM_PLANE_HELPER_NO_SCALING;
949 max_scale = DRM_PLANE_HELPER_NO_SCALING;
950 }
951 } else {
Ville Syrjälä282dbf92017-03-27 21:55:33 +0300952 can_scale = plane->can_scale;
953 max_scale = plane->max_downscale << 16;
954 min_scale = plane->can_scale ? 1 : (1 << 16);
Chandra Konduru225c2282015-05-18 16:18:44 -0700955 }
956
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300957 /*
958 * FIXME the following code does a bunch of fuzzy adjustments to the
959 * coordinates and sizes. We probably need some way to decide whether
960 * more strict checking should be done instead.
961 */
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300962 drm_rect_rotate(src, fb->width << 16, fb->height << 16,
Matt Roper8e7d6882015-01-21 16:35:41 -0800963 state->base.rotation);
Ville Syrjälä76eebda2014-08-05 11:26:52 +0530964
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300965 hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300966 BUG_ON(hscale < 0);
Ville Syrjälä17316932013-04-24 18:52:38 +0300967
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300968 vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300969 BUG_ON(vscale < 0);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800970
Ville Syrjäläa2936e3d2017-11-23 21:04:49 +0200971 if (crtc_state->base.enable)
972 drm_mode_get_hv_timing(&crtc_state->base.mode,
973 &clip.x2, &clip.y2);
974
975 state->base.visible = drm_rect_clip_scaled(src, dst, &clip, hscale, vscale);
Jesse Barnesb840d907f2011-12-13 13:19:38 -0800976
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300977 crtc_x = dst->x1;
978 crtc_y = dst->y1;
979 crtc_w = drm_rect_width(dst);
980 crtc_h = drm_rect_height(dst);
Damien Lespiau2d354c32012-10-22 18:19:27 +0100981
Ville Syrjälä936e71e2016-07-26 19:06:59 +0300982 if (state->base.visible) {
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300983 /* check again in case clipping clamped the results */
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300984 hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300985 if (hscale < 0) {
986 DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
Ville Syrjäläc70f5772015-11-16 17:02:36 +0200987 drm_rect_debug_print("src: ", src, true);
988 drm_rect_debug_print("dst: ", dst, false);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300989
990 return hscale;
991 }
992
Gustavo Padovan96d61a72014-09-05 17:04:47 -0300993 vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300994 if (vscale < 0) {
995 DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
Ville Syrjäläc70f5772015-11-16 17:02:36 +0200996 drm_rect_debug_print("src: ", src, true);
997 drm_rect_debug_print("dst: ", dst, false);
Ville Syrjälä3c3686c2013-04-24 18:52:39 +0300998
999 return vscale;
1000 }
1001
Ville Syrjälä17316932013-04-24 18:52:38 +03001002 /* Make the source viewport size an exact multiple of the scaling factors. */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001003 drm_rect_adjust_size(src,
1004 drm_rect_width(dst) * hscale - drm_rect_width(src),
1005 drm_rect_height(dst) * vscale - drm_rect_height(src));
Ville Syrjälä17316932013-04-24 18:52:38 +03001006
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001007 drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
Matt Roper8e7d6882015-01-21 16:35:41 -08001008 state->base.rotation);
Ville Syrjälä76eebda2014-08-05 11:26:52 +05301009
Ville Syrjälä17316932013-04-24 18:52:38 +03001010 /* sanity check to make sure the src viewport wasn't enlarged */
Matt Roperea2c67b2014-12-23 10:41:52 -08001011 WARN_ON(src->x1 < (int) state->base.src_x ||
1012 src->y1 < (int) state->base.src_y ||
1013 src->x2 > (int) state->base.src_x + state->base.src_w ||
1014 src->y2 > (int) state->base.src_y + state->base.src_h);
Ville Syrjälä17316932013-04-24 18:52:38 +03001015
1016 /*
1017 * Hardware doesn't handle subpixel coordinates.
1018 * Adjust to (macro)pixel boundary, but be careful not to
1019 * increase the source viewport size, because that could
1020 * push the downscaling factor out of bounds.
Ville Syrjälä17316932013-04-24 18:52:38 +03001021 */
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001022 src_x = src->x1 >> 16;
1023 src_w = drm_rect_width(src) >> 16;
1024 src_y = src->y1 >> 16;
1025 src_h = drm_rect_height(src) >> 16;
Ville Syrjälä17316932013-04-24 18:52:38 +03001026
Ville Syrjälä38f24f22018-02-14 21:23:24 +02001027 if (intel_format_is_yuv(fb->format->format)) {
Ville Syrjälä17316932013-04-24 18:52:38 +03001028 src_x &= ~1;
1029 src_w &= ~1;
1030
1031 /*
1032 * Must keep src and dst the
1033 * same if we can't scale.
1034 */
Chandra Konduru225c2282015-05-18 16:18:44 -07001035 if (!can_scale)
Ville Syrjälä17316932013-04-24 18:52:38 +03001036 crtc_w &= ~1;
1037
1038 if (crtc_w == 0)
Ville Syrjälä936e71e2016-07-26 19:06:59 +03001039 state->base.visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001040 }
1041 }
1042
1043 /* Check size restrictions when scaling */
Ville Syrjälä936e71e2016-07-26 19:06:59 +03001044 if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
Ville Syrjälä17316932013-04-24 18:52:38 +03001045 unsigned int width_bytes;
Ville Syrjälä353c8592016-12-14 23:30:57 +02001046 int cpp = fb->format->cpp[0];
Ville Syrjälä17316932013-04-24 18:52:38 +03001047
Chandra Konduru225c2282015-05-18 16:18:44 -07001048 WARN_ON(!can_scale);
Ville Syrjälä17316932013-04-24 18:52:38 +03001049
1050 /* FIXME interlacing min height is 6 */
1051
1052 if (crtc_w < 3 || crtc_h < 3)
Ville Syrjälä936e71e2016-07-26 19:06:59 +03001053 state->base.visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001054
1055 if (src_w < 3 || src_h < 3)
Ville Syrjälä936e71e2016-07-26 19:06:59 +03001056 state->base.visible = false;
Ville Syrjälä17316932013-04-24 18:52:38 +03001057
Ville Syrjäläac484962016-01-20 21:05:26 +02001058 width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
Ville Syrjälä17316932013-04-24 18:52:38 +03001059
Tvrtko Ursulin55b8f2a2016-10-14 09:17:22 +01001060 if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
Chandra Konduruc3318792015-04-15 15:15:02 -07001061 width_bytes > 4096 || fb->pitches[0] > 4096)) {
Ville Syrjälä17316932013-04-24 18:52:38 +03001062 DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
1063 return -EINVAL;
1064 }
1065 }
1066
Ville Syrjälä936e71e2016-07-26 19:06:59 +03001067 if (state->base.visible) {
Chandra Konduru0a5ae1b2015-04-09 16:41:54 -07001068 src->x1 = src_x << 16;
1069 src->x2 = (src_x + src_w) << 16;
1070 src->y1 = src_y << 16;
1071 src->y2 = (src_y + src_h) << 16;
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001072 }
1073
1074 dst->x1 = crtc_x;
1075 dst->x2 = crtc_x + crtc_w;
1076 dst->y1 = crtc_y;
1077 dst->y2 = crtc_y + crtc_h;
1078
Tvrtko Ursulin55b8f2a2016-10-14 09:17:22 +01001079 if (INTEL_GEN(dev_priv) >= 9) {
Imre Deakc322c642018-01-16 13:24:14 +02001080 ret = skl_check_plane_surface(crtc_state, state);
Ville Syrjäläb63a16f2016-01-28 16:53:54 +02001081 if (ret)
1082 return ret;
Ville Syrjäläa0864d52017-03-23 21:27:09 +02001083
1084 state->ctl = skl_plane_ctl(crtc_state, state);
1085 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
Ville Syrjäläf9407ae2017-03-23 21:27:12 +02001086 ret = i9xx_check_plane_surface(state);
1087 if (ret)
1088 return ret;
1089
Ville Syrjäläa0864d52017-03-23 21:27:09 +02001090 state->ctl = vlv_sprite_ctl(crtc_state, state);
1091 } else if (INTEL_GEN(dev_priv) >= 7) {
Ville Syrjäläf9407ae2017-03-23 21:27:12 +02001092 ret = i9xx_check_plane_surface(state);
1093 if (ret)
1094 return ret;
1095
Ville Syrjäläa0864d52017-03-23 21:27:09 +02001096 state->ctl = ivb_sprite_ctl(crtc_state, state);
1097 } else {
Ville Syrjäläf9407ae2017-03-23 21:27:12 +02001098 ret = i9xx_check_plane_surface(state);
1099 if (ret)
1100 return ret;
1101
Ville Syrjäläab330812017-04-21 21:14:32 +03001102 state->ctl = g4x_sprite_ctl(crtc_state, state);
Ville Syrjäläb63a16f2016-01-28 16:53:54 +02001103 }
1104
James Ausmus4036c782017-11-13 10:11:28 -08001105 if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
1106 state->color_ctl = glk_plane_color_ctl(crtc_state, state);
1107
Gustavo Padovan96d61a72014-09-05 17:04:47 -03001108 return 0;
1109}
1110
Jesse Barnes8ea30862012-01-03 08:05:39 -08001111int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
1112 struct drm_file *file_priv)
1113{
Tvrtko Ursulin920a14b2016-10-14 10:13:44 +01001114 struct drm_i915_private *dev_priv = to_i915(dev);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001115 struct drm_intel_sprite_colorkey *set = data;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001116 struct drm_plane *plane;
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001117 struct drm_plane_state *plane_state;
1118 struct drm_atomic_state *state;
1119 struct drm_modeset_acquire_ctx ctx;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001120 int ret = 0;
1121
Ville Syrjälä6ec5bd32018-02-02 22:42:31 +02001122 /* ignore the pointless "none" flag */
1123 set->flags &= ~I915_SET_COLORKEY_NONE;
1124
Jesse Barnes8ea30862012-01-03 08:05:39 -08001125 /* Make sure we don't try to enable both src & dest simultaneously */
1126 if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
1127 return -EINVAL;
1128
Tvrtko Ursulin920a14b2016-10-14 10:13:44 +01001129 if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
Ville Syrjälä47ecbb22015-03-19 21:18:57 +02001130 set->flags & I915_SET_COLORKEY_DESTINATION)
1131 return -EINVAL;
1132
Keith Packard418da172017-03-14 23:25:07 -07001133 plane = drm_plane_find(dev, file_priv, set->plane_id);
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001134 if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
1135 return -ENOENT;
1136
1137 drm_modeset_acquire_init(&ctx, 0);
1138
1139 state = drm_atomic_state_alloc(plane->dev);
1140 if (!state) {
1141 ret = -ENOMEM;
1142 goto out;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001143 }
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001144 state->acquire_ctx = &ctx;
Jesse Barnes8ea30862012-01-03 08:05:39 -08001145
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001146 while (1) {
1147 plane_state = drm_atomic_get_plane_state(state, plane);
1148 ret = PTR_ERR_OR_ZERO(plane_state);
1149 if (!ret) {
1150 to_intel_plane_state(plane_state)->ckey = *set;
1151 ret = drm_atomic_commit(state);
Chandra Konduru6156a452015-04-27 13:48:39 -07001152 }
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001153
1154 if (ret != -EDEADLK)
1155 break;
1156
1157 drm_atomic_state_clear(state);
1158 drm_modeset_backoff(&ctx);
Chandra Konduru6156a452015-04-27 13:48:39 -07001159 }
1160
Chris Wilson08536952016-10-14 13:18:18 +01001161 drm_atomic_state_put(state);
Maarten Lankhorst818ed962015-06-15 12:33:54 +02001162out:
1163 drm_modeset_drop_locks(&ctx);
1164 drm_modeset_acquire_fini(&ctx);
Jesse Barnes8ea30862012-01-03 08:05:39 -08001165 return ret;
1166}
1167
Ville Syrjäläab330812017-04-21 21:14:32 +03001168static const uint32_t g4x_plane_formats[] = {
Chris Wilsond1686ae2012-04-10 11:41:49 +01001169 DRM_FORMAT_XRGB8888,
1170 DRM_FORMAT_YUYV,
1171 DRM_FORMAT_YVYU,
1172 DRM_FORMAT_UYVY,
1173 DRM_FORMAT_VYUY,
1174};
1175
Ben Widawsky714244e2017-08-01 09:58:16 -07001176static const uint64_t i9xx_plane_format_modifiers[] = {
1177 I915_FORMAT_MOD_X_TILED,
1178 DRM_FORMAT_MOD_LINEAR,
1179 DRM_FORMAT_MOD_INVALID
1180};
1181
Damien Lespiaudada2d52015-05-12 16:13:22 +01001182static const uint32_t snb_plane_formats[] = {
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001183 DRM_FORMAT_XBGR8888,
1184 DRM_FORMAT_XRGB8888,
1185 DRM_FORMAT_YUYV,
1186 DRM_FORMAT_YVYU,
1187 DRM_FORMAT_UYVY,
1188 DRM_FORMAT_VYUY,
1189};
1190
Damien Lespiaudada2d52015-05-12 16:13:22 +01001191static const uint32_t vlv_plane_formats[] = {
Jesse Barnes7f1f3852013-04-02 11:22:20 -07001192 DRM_FORMAT_RGB565,
1193 DRM_FORMAT_ABGR8888,
1194 DRM_FORMAT_ARGB8888,
1195 DRM_FORMAT_XBGR8888,
1196 DRM_FORMAT_XRGB8888,
1197 DRM_FORMAT_XBGR2101010,
1198 DRM_FORMAT_ABGR2101010,
1199 DRM_FORMAT_YUYV,
1200 DRM_FORMAT_YVYU,
1201 DRM_FORMAT_UYVY,
1202 DRM_FORMAT_VYUY,
1203};
1204
Damien Lespiaudc2a41b2013-12-04 00:49:41 +00001205static uint32_t skl_plane_formats[] = {
1206 DRM_FORMAT_RGB565,
1207 DRM_FORMAT_ABGR8888,
1208 DRM_FORMAT_ARGB8888,
1209 DRM_FORMAT_XBGR8888,
1210 DRM_FORMAT_XRGB8888,
1211 DRM_FORMAT_YUYV,
1212 DRM_FORMAT_YVYU,
1213 DRM_FORMAT_UYVY,
1214 DRM_FORMAT_VYUY,
1215};
1216
Ville Syrjälä77064e22017-12-22 21:22:28 +02001217static const uint64_t skl_plane_format_modifiers_noccs[] = {
1218 I915_FORMAT_MOD_Yf_TILED,
1219 I915_FORMAT_MOD_Y_TILED,
1220 I915_FORMAT_MOD_X_TILED,
1221 DRM_FORMAT_MOD_LINEAR,
1222 DRM_FORMAT_MOD_INVALID
1223};
1224
1225static const uint64_t skl_plane_format_modifiers_ccs[] = {
1226 I915_FORMAT_MOD_Yf_TILED_CCS,
1227 I915_FORMAT_MOD_Y_TILED_CCS,
Ville Syrjälä74ac1602017-12-22 21:22:26 +02001228 I915_FORMAT_MOD_Yf_TILED,
1229 I915_FORMAT_MOD_Y_TILED,
Ben Widawsky714244e2017-08-01 09:58:16 -07001230 I915_FORMAT_MOD_X_TILED,
1231 DRM_FORMAT_MOD_LINEAR,
1232 DRM_FORMAT_MOD_INVALID
1233};
1234
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001235static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001236{
1237 switch (format) {
Ben Widawsky714244e2017-08-01 09:58:16 -07001238 case DRM_FORMAT_XRGB8888:
1239 case DRM_FORMAT_YUYV:
1240 case DRM_FORMAT_YVYU:
1241 case DRM_FORMAT_UYVY:
1242 case DRM_FORMAT_VYUY:
1243 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1244 modifier == I915_FORMAT_MOD_X_TILED)
1245 return true;
1246 /* fall through */
1247 default:
1248 return false;
1249 }
1250}
1251
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001252static bool snb_mod_supported(uint32_t format, uint64_t modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001253{
1254 switch (format) {
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001255 case DRM_FORMAT_XRGB8888:
1256 case DRM_FORMAT_XBGR8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001257 case DRM_FORMAT_YUYV:
1258 case DRM_FORMAT_YVYU:
1259 case DRM_FORMAT_UYVY:
1260 case DRM_FORMAT_VYUY:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001261 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1262 modifier == I915_FORMAT_MOD_X_TILED)
1263 return true;
1264 /* fall through */
1265 default:
1266 return false;
1267 }
1268}
1269
1270static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
1271{
1272 switch (format) {
Ben Widawsky714244e2017-08-01 09:58:16 -07001273 case DRM_FORMAT_RGB565:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001274 case DRM_FORMAT_ABGR8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001275 case DRM_FORMAT_ARGB8888:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001276 case DRM_FORMAT_XBGR8888:
1277 case DRM_FORMAT_XRGB8888:
Ben Widawsky714244e2017-08-01 09:58:16 -07001278 case DRM_FORMAT_XBGR2101010:
1279 case DRM_FORMAT_ABGR2101010:
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001280 case DRM_FORMAT_YUYV:
1281 case DRM_FORMAT_YVYU:
1282 case DRM_FORMAT_UYVY:
1283 case DRM_FORMAT_VYUY:
Ben Widawsky714244e2017-08-01 09:58:16 -07001284 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1285 modifier == I915_FORMAT_MOD_X_TILED)
1286 return true;
1287 /* fall through */
1288 default:
1289 return false;
1290 }
1291}
1292
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001293static bool skl_mod_supported(uint32_t format, uint64_t modifier)
Ben Widawsky714244e2017-08-01 09:58:16 -07001294{
Ben Widawsky714244e2017-08-01 09:58:16 -07001295 switch (format) {
1296 case DRM_FORMAT_XRGB8888:
1297 case DRM_FORMAT_XBGR8888:
1298 case DRM_FORMAT_ARGB8888:
1299 case DRM_FORMAT_ABGR8888:
Ville Syrjälä77064e22017-12-22 21:22:28 +02001300 if (modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
1301 modifier == I915_FORMAT_MOD_Y_TILED_CCS)
1302 return true;
1303 /* fall through */
Ben Widawsky714244e2017-08-01 09:58:16 -07001304 case DRM_FORMAT_RGB565:
1305 case DRM_FORMAT_XRGB2101010:
1306 case DRM_FORMAT_XBGR2101010:
1307 case DRM_FORMAT_YUYV:
1308 case DRM_FORMAT_YVYU:
1309 case DRM_FORMAT_UYVY:
1310 case DRM_FORMAT_VYUY:
1311 if (modifier == I915_FORMAT_MOD_Yf_TILED)
1312 return true;
1313 /* fall through */
1314 case DRM_FORMAT_C8:
1315 if (modifier == DRM_FORMAT_MOD_LINEAR ||
1316 modifier == I915_FORMAT_MOD_X_TILED ||
1317 modifier == I915_FORMAT_MOD_Y_TILED)
1318 return true;
1319 /* fall through */
1320 default:
1321 return false;
1322 }
1323}
1324
1325static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
1326 uint32_t format,
1327 uint64_t modifier)
1328{
1329 struct drm_i915_private *dev_priv = to_i915(plane->dev);
1330
1331 if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
1332 return false;
1333
1334 if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
1335 modifier != DRM_FORMAT_MOD_LINEAR)
1336 return false;
1337
1338 if (INTEL_GEN(dev_priv) >= 9)
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001339 return skl_mod_supported(format, modifier);
Ben Widawsky714244e2017-08-01 09:58:16 -07001340 else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001341 return vlv_mod_supported(format, modifier);
1342 else if (INTEL_GEN(dev_priv) >= 6)
1343 return snb_mod_supported(format, modifier);
Ben Widawsky714244e2017-08-01 09:58:16 -07001344 else
Ville Syrjäläc21f7902017-12-22 21:22:27 +02001345 return g4x_mod_supported(format, modifier);
Ben Widawsky714244e2017-08-01 09:58:16 -07001346}
1347
Colin Ian King2d567582017-08-11 14:49:38 +01001348static const struct drm_plane_funcs intel_sprite_plane_funcs = {
Ben Widawsky714244e2017-08-01 09:58:16 -07001349 .update_plane = drm_atomic_helper_update_plane,
1350 .disable_plane = drm_atomic_helper_disable_plane,
1351 .destroy = intel_plane_destroy,
1352 .atomic_get_property = intel_plane_atomic_get_property,
1353 .atomic_set_property = intel_plane_atomic_set_property,
1354 .atomic_duplicate_state = intel_plane_duplicate_state,
1355 .atomic_destroy_state = intel_plane_destroy_state,
1356 .format_mod_supported = intel_sprite_plane_format_mod_supported,
1357};
1358
Ville Syrjälä77064e22017-12-22 21:22:28 +02001359bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
1360 enum pipe pipe, enum plane_id plane_id)
1361{
1362 if (plane_id == PLANE_CURSOR)
1363 return false;
1364
1365 if (INTEL_GEN(dev_priv) >= 10)
1366 return true;
1367
1368 if (IS_GEMINILAKE(dev_priv))
1369 return pipe != PIPE_C;
1370
1371 return pipe != PIPE_C &&
1372 (plane_id == PLANE_PRIMARY ||
1373 plane_id == PLANE_SPRITE0);
1374}
1375
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001376struct intel_plane *
Ville Syrjälä580503c2016-10-31 22:37:00 +02001377intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1378 enum pipe pipe, int plane)
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001379{
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001380 struct intel_plane *intel_plane = NULL;
1381 struct intel_plane_state *state = NULL;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001382 unsigned long possible_crtcs;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001383 const uint32_t *plane_formats;
Ben Widawsky714244e2017-08-01 09:58:16 -07001384 const uint64_t *modifiers;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001385 unsigned int supported_rotations;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001386 int num_plane_formats;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001387 int ret;
1388
Daniel Vetterb14c5672013-09-19 12:18:32 +02001389 intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001390 if (!intel_plane) {
1391 ret = -ENOMEM;
1392 goto fail;
1393 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001394
Matt Roper8e7d6882015-01-21 16:35:41 -08001395 state = intel_create_plane_state(&intel_plane->base);
1396 if (!state) {
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001397 ret = -ENOMEM;
1398 goto fail;
Matt Roperea2c67b2014-12-23 10:41:52 -08001399 }
Matt Roper8e7d6882015-01-21 16:35:41 -08001400 intel_plane->base.state = &state->base;
Matt Roperea2c67b2014-12-23 10:41:52 -08001401
Ville Syrjälä77064e22017-12-22 21:22:28 +02001402 if (INTEL_GEN(dev_priv) >= 9) {
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001403 intel_plane->can_scale = true;
1404 state->scaler_id = -1;
1405
1406 intel_plane->update_plane = skl_update_plane;
1407 intel_plane->disable_plane = skl_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001408 intel_plane->get_hw_state = skl_plane_get_hw_state;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001409
1410 plane_formats = skl_plane_formats;
1411 num_plane_formats = ARRAY_SIZE(skl_plane_formats);
Ben Widawsky714244e2017-08-01 09:58:16 -07001412
Ville Syrjälä77064e22017-12-22 21:22:28 +02001413 if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane))
1414 modifiers = skl_plane_format_modifiers_ccs;
1415 else
1416 modifiers = skl_plane_format_modifiers_noccs;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001417 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1418 intel_plane->can_scale = false;
1419 intel_plane->max_downscale = 1;
1420
1421 intel_plane->update_plane = vlv_update_plane;
1422 intel_plane->disable_plane = vlv_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001423 intel_plane->get_hw_state = vlv_plane_get_hw_state;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001424
1425 plane_formats = vlv_plane_formats;
1426 num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
Ben Widawsky714244e2017-08-01 09:58:16 -07001427 modifiers = i9xx_plane_format_modifiers;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001428 } else if (INTEL_GEN(dev_priv) >= 7) {
1429 if (IS_IVYBRIDGE(dev_priv)) {
1430 intel_plane->can_scale = true;
1431 intel_plane->max_downscale = 2;
1432 } else {
1433 intel_plane->can_scale = false;
1434 intel_plane->max_downscale = 1;
1435 }
1436
1437 intel_plane->update_plane = ivb_update_plane;
1438 intel_plane->disable_plane = ivb_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001439 intel_plane->get_hw_state = ivb_plane_get_hw_state;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001440
1441 plane_formats = snb_plane_formats;
1442 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
Ben Widawsky714244e2017-08-01 09:58:16 -07001443 modifiers = i9xx_plane_format_modifiers;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001444 } else {
Damien Lespiau2d354c32012-10-22 18:19:27 +01001445 intel_plane->can_scale = true;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001446 intel_plane->max_downscale = 16;
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001447
Ville Syrjäläab330812017-04-21 21:14:32 +03001448 intel_plane->update_plane = g4x_update_plane;
1449 intel_plane->disable_plane = g4x_disable_plane;
Ville Syrjälä51f5a0962017-11-17 21:19:08 +02001450 intel_plane->get_hw_state = g4x_plane_get_hw_state;
Chris Wilsond1686ae2012-04-10 11:41:49 +01001451
Ben Widawsky714244e2017-08-01 09:58:16 -07001452 modifiers = i9xx_plane_format_modifiers;
Tvrtko Ursulin5db94012016-10-13 11:03:10 +01001453 if (IS_GEN6(dev_priv)) {
Chris Wilsond1686ae2012-04-10 11:41:49 +01001454 plane_formats = snb_plane_formats;
1455 num_plane_formats = ARRAY_SIZE(snb_plane_formats);
1456 } else {
Ville Syrjäläab330812017-04-21 21:14:32 +03001457 plane_formats = g4x_plane_formats;
1458 num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
Chris Wilsond1686ae2012-04-10 11:41:49 +01001459 }
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001460 }
1461
Dave Airlie5481e272016-10-25 16:36:13 +10001462 if (INTEL_GEN(dev_priv) >= 9) {
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001463 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001464 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
1465 DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
Ville Syrjälä4ea7be22016-11-14 18:54:00 +02001466 } else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1467 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001468 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1469 DRM_MODE_REFLECT_X;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001470 } else {
1471 supported_rotations =
Robert Fossc2c446a2017-05-19 16:50:17 -04001472 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001473 }
1474
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001475 intel_plane->pipe = pipe;
Ville Syrjäläed150302017-11-17 21:19:10 +02001476 intel_plane->i9xx_plane = plane;
Ville Syrjäläb14e5842016-11-22 18:01:56 +02001477 intel_plane->id = PLANE_SPRITE0 + plane;
Ville Syrjäläc19e1122018-01-23 20:33:43 +02001478 intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id);
Matt Roperc59cb172014-12-01 15:40:16 -08001479 intel_plane->check_plane = intel_check_sprite_plane;
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001480
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001481 possible_crtcs = (1 << pipe);
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001482
Ville Syrjälä1890ae62016-10-25 18:58:03 +03001483 if (INTEL_GEN(dev_priv) >= 9)
Ville Syrjälä580503c2016-10-31 22:37:00 +02001484 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
Ben Widawsky714244e2017-08-01 09:58:16 -07001485 possible_crtcs, &intel_sprite_plane_funcs,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001486 plane_formats, num_plane_formats,
Ben Widawsky714244e2017-08-01 09:58:16 -07001487 modifiers,
1488 DRM_PLANE_TYPE_OVERLAY,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001489 "plane %d%c", plane + 2, pipe_name(pipe));
1490 else
Ville Syrjälä580503c2016-10-31 22:37:00 +02001491 ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
Ben Widawsky714244e2017-08-01 09:58:16 -07001492 possible_crtcs, &intel_sprite_plane_funcs,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001493 plane_formats, num_plane_formats,
Ben Widawsky714244e2017-08-01 09:58:16 -07001494 modifiers,
1495 DRM_PLANE_TYPE_OVERLAY,
Ville Syrjälä38573dc2016-05-27 20:59:23 +03001496 "sprite %c", sprite_name(pipe, plane));
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001497 if (ret)
1498 goto fail;
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001499
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001500 drm_plane_create_rotation_property(&intel_plane->base,
Robert Fossc2c446a2017-05-19 16:50:17 -04001501 DRM_MODE_ROTATE_0,
Ville Syrjälä93ca7e02016-09-26 19:30:56 +03001502 supported_rotations);
Ville Syrjälä7ed6eee2014-08-05 11:26:55 +05301503
Matt Roperea2c67b2014-12-23 10:41:52 -08001504 drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
1505
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001506 return intel_plane;
Ville Syrjäläfca0ce22016-03-21 14:43:22 +00001507
1508fail:
1509 kfree(state);
1510 kfree(intel_plane);
1511
Ville Syrjäläb079bd172016-10-25 18:58:02 +03001512 return ERR_PTR(ret);
Jesse Barnesb840d907f2011-12-13 13:19:38 -08001513}