Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2011 Intel Corporation
3 : : *
4 : : * Permission is hereby granted, free of charge, to any person obtaining a
5 : : * copy of this software and associated documentation files (the "Software"),
6 : : * to deal in the Software without restriction, including without limitation
7 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : : * and/or sell copies of the Software, and to permit persons to whom the
9 : : * Software is furnished to do so, subject to the following conditions:
10 : : *
11 : : * The above copyright notice and this permission notice (including the next
12 : : * paragraph) shall be included in all copies or substantial portions of the
13 : : * Software.
14 : : *
15 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 : : * SOFTWARE.
22 : : *
23 : : * Authors:
24 : : * Jesse Barnes <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 : : */
32 : :
33 : : #include <drm/drm_atomic.h>
34 : : #include <drm/drm_atomic_helper.h>
35 : : #include <drm/drm_color_mgmt.h>
36 : : #include <drm/drm_crtc.h>
37 : : #include <drm/drm_fourcc.h>
38 : : #include <drm/drm_plane_helper.h>
39 : : #include <drm/drm_rect.h>
40 : : #include <drm/i915_drm.h>
41 : :
42 : : #include "i915_drv.h"
43 : : #include "i915_trace.h"
44 : : #include "intel_atomic_plane.h"
45 : : #include "intel_display_types.h"
46 : : #include "intel_frontbuffer.h"
47 : : #include "intel_pm.h"
48 : : #include "intel_psr.h"
49 : : #include "intel_sprite.h"
50 : :
51 : 0 : int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
52 : : int usecs)
53 : : {
54 : : /* paranoia */
55 [ # # ]: 0 : if (!adjusted_mode->crtc_htotal)
56 : : return 1;
57 : :
58 : 0 : return DIV_ROUND_UP(usecs * adjusted_mode->crtc_clock,
59 : : 1000 * adjusted_mode->crtc_htotal);
60 : : }
61 : :
62 : : /* FIXME: We should instead only take spinlocks once for the entire update
63 : : * instead of once per mmio. */
64 : : #if IS_ENABLED(CONFIG_PROVE_LOCKING)
65 : : #define VBLANK_EVASION_TIME_US 250
66 : : #else
67 : : #define VBLANK_EVASION_TIME_US 100
68 : : #endif
69 : :
70 : : /**
71 : : * intel_pipe_update_start() - start update of a set of display registers
72 : : * @new_crtc_state: the new crtc state
73 : : *
74 : : * Mark the start of an update to pipe registers that should be updated
75 : : * atomically regarding vblank. If the next vblank will happens within
76 : : * the next 100 us, this function waits until the vblank passes.
77 : : *
78 : : * After a successful call to this function, interrupts will be disabled
79 : : * until a subsequent call to intel_pipe_update_end(). That is done to
80 : : * avoid random delays.
81 : : */
82 : 0 : void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state)
83 : : {
84 : 0 : struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
85 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
86 : 0 : const struct drm_display_mode *adjusted_mode = &new_crtc_state->hw.adjusted_mode;
87 : 0 : long timeout = msecs_to_jiffies_timeout(1);
88 : 0 : int scanline, min, max, vblank_start;
89 : 0 : wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base);
90 [ # # # # : 0 : bool need_vlv_dsi_wa = (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
# # ]
91 [ # # ]: 0 : intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI);
92 [ # # ]: 0 : DEFINE_WAIT(wait);
93 : 0 : u32 psr_status;
94 : :
95 : 0 : vblank_start = adjusted_mode->crtc_vblank_start;
96 [ # # ]: 0 : if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
97 : 0 : vblank_start = DIV_ROUND_UP(vblank_start, 2);
98 : :
99 : : /* FIXME needs to be calibrated sensibly */
100 [ # # ]: 0 : min = vblank_start - intel_usecs_to_scanlines(adjusted_mode,
101 : : VBLANK_EVASION_TIME_US);
102 : 0 : max = vblank_start - 1;
103 : :
104 [ # # ]: 0 : if (min <= 0 || max <= 0)
105 : 0 : goto irq_disable;
106 : :
107 [ # # # # ]: 0 : if (WARN_ON(drm_crtc_vblank_get(&crtc->base)))
108 : 0 : goto irq_disable;
109 : :
110 : : /*
111 : : * Wait for psr to idle out after enabling the VBL interrupts
112 : : * VBL interrupts will start the PSR exit and prevent a PSR
113 : : * re-entry as well.
114 : : */
115 [ # # ]: 0 : if (intel_psr_wait_for_idle(new_crtc_state, &psr_status))
116 : 0 : DRM_ERROR("PSR idle timed out 0x%x, atomic update may fail\n",
117 : : psr_status);
118 : :
119 : 0 : local_irq_disable();
120 : :
121 : 0 : crtc->debug.min_vbl = min;
122 : 0 : crtc->debug.max_vbl = max;
123 : 0 : trace_intel_pipe_update_start(crtc);
124 : :
125 : 0 : for (;;) {
126 : : /*
127 : : * prepare_to_wait() has a memory barrier, which guarantees
128 : : * other CPUs can see the task state update by the time we
129 : : * read the scanline.
130 : : */
131 : 0 : prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
132 : :
133 : 0 : scanline = intel_get_crtc_scanline(crtc);
134 [ # # ]: 0 : if (scanline < min || scanline > max)
135 : : break;
136 : :
137 [ # # ]: 0 : if (!timeout) {
138 : 0 : DRM_ERROR("Potential atomic update failure on pipe %c\n",
139 : : pipe_name(crtc->pipe));
140 : 0 : break;
141 : : }
142 : :
143 : 0 : local_irq_enable();
144 : :
145 : 0 : timeout = schedule_timeout(timeout);
146 : :
147 : 0 : local_irq_disable();
148 : : }
149 : :
150 : 0 : finish_wait(wq, &wait);
151 : :
152 : 0 : drm_crtc_vblank_put(&crtc->base);
153 : :
154 : : /*
155 : : * On VLV/CHV DSI the scanline counter would appear to
156 : : * increment approx. 1/3 of a scanline before start of vblank.
157 : : * The registers still get latched at start of vblank however.
158 : : * This means we must not write any registers on the first
159 : : * line of vblank (since not the whole line is actually in
160 : : * vblank). And unfortunately we can't use the interrupt to
161 : : * wait here since it will fire too soon. We could use the
162 : : * frame start interrupt instead since it will fire after the
163 : : * critical scanline, but that would require more changes
164 : : * in the interrupt code. So for now we'll just do the nasty
165 : : * thing and poll for the bad scanline to pass us by.
166 : : *
167 : : * FIXME figure out if BXT+ DSI suffers from this as well
168 : : */
169 [ # # ]: 0 : while (need_vlv_dsi_wa && scanline == vblank_start)
170 : 0 : scanline = intel_get_crtc_scanline(crtc);
171 : :
172 : 0 : crtc->debug.scanline_start = scanline;
173 : 0 : crtc->debug.start_vbl_time = ktime_get();
174 : 0 : crtc->debug.start_vbl_count = intel_crtc_get_vblank_counter(crtc);
175 : :
176 : 0 : trace_intel_pipe_update_vblank_evaded(crtc);
177 : 0 : return;
178 : :
179 : 0 : irq_disable:
180 : 0 : local_irq_disable();
181 : : }
182 : :
183 : : /**
184 : : * intel_pipe_update_end() - end update of a set of display registers
185 : : * @new_crtc_state: the new crtc state
186 : : *
187 : : * Mark the end of an update started with intel_pipe_update_start(). This
188 : : * re-enables interrupts and verifies the update was actually completed
189 : : * before a vblank.
190 : : */
191 : 0 : void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state)
192 : : {
193 : 0 : struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
194 : 0 : enum pipe pipe = crtc->pipe;
195 : 0 : int scanline_end = intel_get_crtc_scanline(crtc);
196 : 0 : u32 end_vbl_count = intel_crtc_get_vblank_counter(crtc);
197 : 0 : ktime_t end_vbl_time = ktime_get();
198 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
199 : :
200 : 0 : trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end);
201 : :
202 : : /* We're still in the vblank-evade critical section, this can't race.
203 : : * Would be slightly nice to just grab the vblank count and arm the
204 : : * event outside of the critical section - the spinlock might spin for a
205 : : * while ... */
206 [ # # ]: 0 : if (new_crtc_state->uapi.event) {
207 [ # # ]: 0 : WARN_ON(drm_crtc_vblank_get(&crtc->base) != 0);
208 : :
209 : 0 : spin_lock(&crtc->base.dev->event_lock);
210 : 0 : drm_crtc_arm_vblank_event(&crtc->base,
211 : : new_crtc_state->uapi.event);
212 : 0 : spin_unlock(&crtc->base.dev->event_lock);
213 : :
214 : 0 : new_crtc_state->uapi.event = NULL;
215 : : }
216 : :
217 : 0 : local_irq_enable();
218 : :
219 [ # # ]: 0 : if (intel_vgpu_active(dev_priv))
220 : : return;
221 : :
222 [ # # # # ]: 0 : if (crtc->debug.start_vbl_count &&
223 : : crtc->debug.start_vbl_count != end_vbl_count) {
224 : 0 : 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",
225 : : pipe_name(pipe), crtc->debug.start_vbl_count,
226 : : end_vbl_count,
227 : : ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
228 : : crtc->debug.min_vbl, crtc->debug.max_vbl,
229 : : crtc->debug.scanline_start, scanline_end);
230 : : }
231 : : #ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
232 : : else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
233 : : VBLANK_EVASION_TIME_US)
234 : : DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
235 : : pipe_name(pipe),
236 : : ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
237 : : VBLANK_EVASION_TIME_US);
238 : : #endif
239 : : }
240 : :
241 : 0 : int intel_plane_check_stride(const struct intel_plane_state *plane_state)
242 : : {
243 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
244 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
245 : 0 : unsigned int rotation = plane_state->hw.rotation;
246 : 0 : u32 stride, max_stride;
247 : :
248 : : /*
249 : : * We ignore stride for all invisible planes that
250 : : * can be remapped. Otherwise we could end up
251 : : * with a false positive when the remapping didn't
252 : : * kick in due the plane being invisible.
253 : : */
254 [ # # ]: 0 : if (intel_plane_can_remap(plane_state) &&
255 [ # # ]: 0 : !plane_state->uapi.visible)
256 : : return 0;
257 : :
258 : : /* FIXME other color planes? */
259 : 0 : stride = plane_state->color_plane[0].stride;
260 : 0 : max_stride = plane->max_stride(plane, fb->format->format,
261 : : fb->modifier, rotation);
262 : :
263 [ # # ]: 0 : if (stride > max_stride) {
264 : 0 : DRM_DEBUG_KMS("[FB:%d] stride (%d) exceeds [PLANE:%d:%s] max stride (%d)\n",
265 : : fb->base.id, stride,
266 : : plane->base.base.id, plane->base.name, max_stride);
267 : 0 : return -EINVAL;
268 : : }
269 : :
270 : : return 0;
271 : : }
272 : :
273 : 0 : int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state)
274 : : {
275 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
276 : 0 : struct drm_rect *src = &plane_state->uapi.src;
277 : 0 : u32 src_x, src_y, src_w, src_h, hsub, vsub;
278 [ # # ]: 0 : bool rotated = drm_rotation_90_or_270(plane_state->hw.rotation);
279 : :
280 : : /*
281 : : * Hardware doesn't handle subpixel coordinates.
282 : : * Adjust to (macro)pixel boundary, but be careful not to
283 : : * increase the source viewport size, because that could
284 : : * push the downscaling factor out of bounds.
285 : : */
286 : 0 : src_x = src->x1 >> 16;
287 [ # # ]: 0 : src_w = drm_rect_width(src) >> 16;
288 : 0 : src_y = src->y1 >> 16;
289 [ # # ]: 0 : src_h = drm_rect_height(src) >> 16;
290 : :
291 : 0 : drm_rect_init(src, src_x << 16, src_y << 16,
292 [ # # ]: 0 : src_w << 16, src_h << 16);
293 : :
294 [ # # ]: 0 : if (!fb->format->is_yuv)
295 : : return 0;
296 : :
297 : : /* YUV specific checks */
298 [ # # ]: 0 : if (!rotated) {
299 : 0 : hsub = fb->format->hsub;
300 : 0 : vsub = fb->format->vsub;
301 : : } else {
302 : 0 : hsub = vsub = max(fb->format->hsub, fb->format->vsub);
303 : : }
304 : :
305 [ # # # # ]: 0 : if (src_x % hsub || src_w % hsub) {
306 [ # # ]: 0 : DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of %u for %sYUV planes\n",
307 : : src_x, src_w, hsub, rotated ? "rotated " : "");
308 : 0 : return -EINVAL;
309 : : }
310 : :
311 [ # # # # ]: 0 : if (src_y % vsub || src_h % vsub) {
312 [ # # ]: 0 : DRM_DEBUG_KMS("src y/h (%u, %u) must be a multiple of %u for %sYUV planes\n",
313 : : src_y, src_h, vsub, rotated ? "rotated " : "");
314 : 0 : return -EINVAL;
315 : : }
316 : :
317 : : return 0;
318 : : }
319 : :
320 : 0 : bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
321 : : {
322 [ # # # # ]: 0 : return INTEL_GEN(dev_priv) >= 11 &&
323 : : icl_hdr_plane_mask() & BIT(plane_id);
324 : : }
325 : :
326 : : static void
327 : 0 : skl_plane_ratio(const struct intel_crtc_state *crtc_state,
328 : : const struct intel_plane_state *plane_state,
329 : : unsigned int *num, unsigned int *den)
330 : : {
331 : 0 : struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
332 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
333 : :
334 : 0 : if (fb->format->cpp[0] == 8) {
335 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) {
336 : : *num = 10;
337 : : *den = 8;
338 : : } else {
339 : 0 : *num = 9;
340 : 0 : *den = 8;
341 : : }
342 : : } else {
343 : : *num = 1;
344 : : *den = 1;
345 : : }
346 : : }
347 : :
348 : 0 : static int skl_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
349 : : const struct intel_plane_state *plane_state)
350 : : {
351 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev);
352 : 0 : unsigned int pixel_rate = crtc_state->pixel_rate;
353 : 0 : unsigned int src_w, src_h, dst_w, dst_h;
354 : 0 : unsigned int num, den;
355 : :
356 [ # # ]: 0 : skl_plane_ratio(crtc_state, plane_state, &num, &den);
357 : :
358 : : /* two pixels per clock on glk+ */
359 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
360 : 0 : den *= 2;
361 : :
362 : 0 : src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
363 : 0 : src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
364 : 0 : dst_w = drm_rect_width(&plane_state->uapi.dst);
365 : 0 : dst_h = drm_rect_height(&plane_state->uapi.dst);
366 : :
367 : : /* Downscaling limits the maximum pixel rate */
368 : 0 : dst_w = min(src_w, dst_w);
369 : 0 : dst_h = min(src_h, dst_h);
370 : :
371 : 0 : return DIV64_U64_ROUND_UP(mul_u32_u32(pixel_rate * num, src_w * src_h),
372 : : mul_u32_u32(den, dst_w * dst_h));
373 : : }
374 : :
375 : : static unsigned int
376 : 0 : skl_plane_max_stride(struct intel_plane *plane,
377 : : u32 pixel_format, u64 modifier,
378 : : unsigned int rotation)
379 : : {
380 : 0 : const struct drm_format_info *info = drm_format_info(pixel_format);
381 : 0 : int cpp = info->cpp[0];
382 : :
383 : : /*
384 : : * "The stride in bytes must not exceed the
385 : : * of the size of 8K pixels and 32K bytes."
386 : : */
387 [ # # ]: 0 : if (drm_rotation_90_or_270(rotation))
388 : 0 : return min(8192, 32768 / cpp);
389 : : else
390 : 0 : return min(8192 * cpp, 32768);
391 : : }
392 : :
393 : : static void
394 : 0 : skl_program_scaler(struct intel_plane *plane,
395 : : const struct intel_crtc_state *crtc_state,
396 : : const struct intel_plane_state *plane_state)
397 : : {
398 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
399 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
400 : 0 : enum pipe pipe = plane->pipe;
401 : 0 : int scaler_id = plane_state->scaler_id;
402 : 0 : const struct intel_scaler *scaler =
403 : : &crtc_state->scaler_state.scalers[scaler_id];
404 : 0 : int crtc_x = plane_state->uapi.dst.x1;
405 : 0 : int crtc_y = plane_state->uapi.dst.y1;
406 : 0 : u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
407 : 0 : u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
408 : 0 : u16 y_hphase, uv_rgb_hphase;
409 : 0 : u16 y_vphase, uv_rgb_vphase;
410 : 0 : int hscale, vscale;
411 : :
412 : 0 : hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
413 : : &plane_state->uapi.dst,
414 : : 0, INT_MAX);
415 : 0 : vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
416 : : &plane_state->uapi.dst,
417 : : 0, INT_MAX);
418 : :
419 : : /* TODO: handle sub-pixel coordinates */
420 [ # # # # ]: 0 : if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
421 [ # # ]: 0 : !icl_is_hdr_plane(dev_priv, plane->id)) {
422 : 0 : y_hphase = skl_scaler_calc_phase(1, hscale, false);
423 : 0 : y_vphase = skl_scaler_calc_phase(1, vscale, false);
424 : :
425 : : /* MPEG2 chroma siting convention */
426 : 0 : uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
427 : 0 : uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
428 : : } else {
429 : : /* not used */
430 : 0 : y_hphase = 0;
431 : 0 : y_vphase = 0;
432 : :
433 : 0 : uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
434 : 0 : uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
435 : : }
436 : :
437 : 0 : I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
438 : : PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
439 : 0 : I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
440 : : PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
441 : 0 : I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
442 : : PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
443 : 0 : I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
444 : 0 : I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
445 : 0 : }
446 : :
447 : : /* Preoffset values for YUV to RGB Conversion */
448 : : #define PREOFF_YUV_TO_RGB_HI 0x1800
449 : : #define PREOFF_YUV_TO_RGB_ME 0x1F00
450 : : #define PREOFF_YUV_TO_RGB_LO 0x1800
451 : :
452 : : #define ROFF(x) (((x) & 0xffff) << 16)
453 : : #define GOFF(x) (((x) & 0xffff) << 0)
454 : : #define BOFF(x) (((x) & 0xffff) << 16)
455 : :
456 : : static void
457 : : icl_program_input_csc(struct intel_plane *plane,
458 : : const struct intel_crtc_state *crtc_state,
459 : : const struct intel_plane_state *plane_state)
460 : : {
461 : : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
462 : : enum pipe pipe = plane->pipe;
463 : : enum plane_id plane_id = plane->id;
464 : :
465 : : static const u16 input_csc_matrix[][9] = {
466 : : /*
467 : : * BT.601 full range YCbCr -> full range RGB
468 : : * The matrix required is :
469 : : * [1.000, 0.000, 1.371,
470 : : * 1.000, -0.336, -0.698,
471 : : * 1.000, 1.732, 0.0000]
472 : : */
473 : : [DRM_COLOR_YCBCR_BT601] = {
474 : : 0x7AF8, 0x7800, 0x0,
475 : : 0x8B28, 0x7800, 0x9AC0,
476 : : 0x0, 0x7800, 0x7DD8,
477 : : },
478 : : /*
479 : : * BT.709 full range YCbCr -> full range RGB
480 : : * The matrix required is :
481 : : * [1.000, 0.000, 1.574,
482 : : * 1.000, -0.187, -0.468,
483 : : * 1.000, 1.855, 0.0000]
484 : : */
485 : : [DRM_COLOR_YCBCR_BT709] = {
486 : : 0x7C98, 0x7800, 0x0,
487 : : 0x9EF8, 0x7800, 0xAC00,
488 : : 0x0, 0x7800, 0x7ED8,
489 : : },
490 : : /*
491 : : * BT.2020 full range YCbCr -> full range RGB
492 : : * The matrix required is :
493 : : * [1.000, 0.000, 1.474,
494 : : * 1.000, -0.1645, -0.5713,
495 : : * 1.000, 1.8814, 0.0000]
496 : : */
497 : : [DRM_COLOR_YCBCR_BT2020] = {
498 : : 0x7BC8, 0x7800, 0x0,
499 : : 0x8928, 0x7800, 0xAA88,
500 : : 0x0, 0x7800, 0x7F10,
501 : : },
502 : : };
503 : :
504 : : /* Matrix for Limited Range to Full Range Conversion */
505 : : static const u16 input_csc_matrix_lr[][9] = {
506 : : /*
507 : : * BT.601 Limted range YCbCr -> full range RGB
508 : : * The matrix required is :
509 : : * [1.164384, 0.000, 1.596027,
510 : : * 1.164384, -0.39175, -0.812813,
511 : : * 1.164384, 2.017232, 0.0000]
512 : : */
513 : : [DRM_COLOR_YCBCR_BT601] = {
514 : : 0x7CC8, 0x7950, 0x0,
515 : : 0x8D00, 0x7950, 0x9C88,
516 : : 0x0, 0x7950, 0x6810,
517 : : },
518 : : /*
519 : : * BT.709 Limited range YCbCr -> full range RGB
520 : : * The matrix required is :
521 : : * [1.164384, 0.000, 1.792741,
522 : : * 1.164384, -0.213249, -0.532909,
523 : : * 1.164384, 2.112402, 0.0000]
524 : : */
525 : : [DRM_COLOR_YCBCR_BT709] = {
526 : : 0x7E58, 0x7950, 0x0,
527 : : 0x8888, 0x7950, 0xADA8,
528 : : 0x0, 0x7950, 0x6870,
529 : : },
530 : : /*
531 : : * BT.2020 Limited range YCbCr -> full range RGB
532 : : * The matrix required is :
533 : : * [1.164, 0.000, 1.678,
534 : : * 1.164, -0.1873, -0.6504,
535 : : * 1.164, 2.1417, 0.0000]
536 : : */
537 : : [DRM_COLOR_YCBCR_BT2020] = {
538 : : 0x7D70, 0x7950, 0x0,
539 : : 0x8A68, 0x7950, 0xAC00,
540 : : 0x0, 0x7950, 0x6890,
541 : : },
542 : : };
543 : : const u16 *csc;
544 : :
545 : : if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
546 : : csc = input_csc_matrix[plane_state->hw.color_encoding];
547 : : else
548 : : csc = input_csc_matrix_lr[plane_state->hw.color_encoding];
549 : :
550 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 0), ROFF(csc[0]) |
551 : : GOFF(csc[1]));
552 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 1), BOFF(csc[2]));
553 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 2), ROFF(csc[3]) |
554 : : GOFF(csc[4]));
555 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 3), BOFF(csc[5]));
556 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 4), ROFF(csc[6]) |
557 : : GOFF(csc[7]));
558 : : I915_WRITE_FW(PLANE_INPUT_CSC_COEFF(pipe, plane_id, 5), BOFF(csc[8]));
559 : :
560 : : I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 0),
561 : : PREOFF_YUV_TO_RGB_HI);
562 : : if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
563 : : I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1), 0);
564 : : else
565 : : I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 1),
566 : : PREOFF_YUV_TO_RGB_ME);
567 : : I915_WRITE_FW(PLANE_INPUT_CSC_PREOFF(pipe, plane_id, 2),
568 : : PREOFF_YUV_TO_RGB_LO);
569 : : I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 0), 0x0);
570 : : I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 1), 0x0);
571 : : I915_WRITE_FW(PLANE_INPUT_CSC_POSTOFF(pipe, plane_id, 2), 0x0);
572 : : }
573 : :
574 : : static void
575 : 0 : skl_program_plane(struct intel_plane *plane,
576 : : const struct intel_crtc_state *crtc_state,
577 : : const struct intel_plane_state *plane_state,
578 : : int color_plane)
579 : : {
580 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
581 : 0 : enum plane_id plane_id = plane->id;
582 : 0 : enum pipe pipe = plane->pipe;
583 : 0 : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
584 : 0 : u32 surf_addr = plane_state->color_plane[color_plane].offset;
585 : 0 : u32 stride = skl_plane_stride(plane_state, color_plane);
586 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
587 : 0 : int aux_plane = intel_main_to_aux_plane(fb, color_plane);
588 : 0 : u32 aux_dist = plane_state->color_plane[aux_plane].offset - surf_addr;
589 : 0 : u32 aux_stride = skl_plane_stride(plane_state, aux_plane);
590 : 0 : int crtc_x = plane_state->uapi.dst.x1;
591 : 0 : int crtc_y = plane_state->uapi.dst.y1;
592 : 0 : u32 x = plane_state->color_plane[color_plane].x;
593 : 0 : u32 y = plane_state->color_plane[color_plane].y;
594 : 0 : u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
595 : 0 : u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
596 : 0 : u8 alpha = plane_state->hw.alpha >> 8;
597 : 0 : u32 plane_color_ctl = 0;
598 : 0 : unsigned long irqflags;
599 : 0 : u32 keymsk, keymax;
600 : 0 : u32 plane_ctl = plane_state->ctl;
601 : :
602 : 0 : plane_ctl |= skl_plane_ctl_crtc(crtc_state);
603 : :
604 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
605 : 0 : plane_color_ctl = plane_state->color_ctl |
606 : 0 : glk_plane_color_ctl_crtc(crtc_state);
607 : :
608 : : /* Sizes are 0 based */
609 : 0 : src_w--;
610 : 0 : src_h--;
611 : :
612 : 0 : keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
613 : :
614 : 0 : keymsk = key->channel_mask & 0x7ffffff;
615 [ # # ]: 0 : if (alpha < 0xff)
616 : 0 : keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
617 : :
618 : : /* The scaler will handle the output position */
619 [ # # ]: 0 : if (plane_state->scaler_id >= 0) {
620 : 0 : crtc_x = 0;
621 : 0 : crtc_y = 0;
622 : : }
623 : :
624 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
625 : :
626 : 0 : I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride);
627 : 0 : I915_WRITE_FW(PLANE_POS(pipe, plane_id), (crtc_y << 16) | crtc_x);
628 : 0 : I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w);
629 : :
630 [ # # ]: 0 : if (INTEL_GEN(dev_priv) < 12)
631 : 0 : aux_dist |= aux_stride;
632 : 0 : I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), aux_dist);
633 : :
634 [ # # # # ]: 0 : if (icl_is_hdr_plane(dev_priv, plane_id))
635 : 0 : I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), plane_state->cus_ctl);
636 : :
637 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
638 : 0 : I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl);
639 : :
640 [ # # # # ]: 0 : if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id))
641 : 0 : icl_program_input_csc(plane, crtc_state, plane_state);
642 : :
643 : 0 : skl_write_plane_wm(plane, crtc_state);
644 : :
645 : 0 : I915_WRITE_FW(PLANE_KEYVAL(pipe, plane_id), key->min_value);
646 : 0 : I915_WRITE_FW(PLANE_KEYMSK(pipe, plane_id), keymsk);
647 : 0 : I915_WRITE_FW(PLANE_KEYMAX(pipe, plane_id), keymax);
648 : :
649 : 0 : I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (y << 16) | x);
650 : :
651 [ # # ]: 0 : if (INTEL_GEN(dev_priv) < 11)
652 : 0 : I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id),
653 : : (plane_state->color_plane[1].y << 16) |
654 : : plane_state->color_plane[1].x);
655 : :
656 : : /*
657 : : * The control register self-arms if the plane was previously
658 : : * disabled. Try to make the plane enable atomic by writing
659 : : * the control register just before the surface register.
660 : : */
661 : 0 : I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl);
662 : 0 : I915_WRITE_FW(PLANE_SURF(pipe, plane_id),
663 : : intel_plane_ggtt_offset(plane_state) + surf_addr);
664 : :
665 [ # # ]: 0 : if (plane_state->scaler_id >= 0)
666 : 0 : skl_program_scaler(plane, crtc_state, plane_state);
667 : :
668 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
669 : 0 : }
670 : :
671 : : static void
672 : 0 : skl_update_plane(struct intel_plane *plane,
673 : : const struct intel_crtc_state *crtc_state,
674 : : const struct intel_plane_state *plane_state)
675 : : {
676 : 0 : int color_plane = 0;
677 : :
678 [ # # # # ]: 0 : if (plane_state->planar_linked_plane && !plane_state->planar_slave)
679 : : /* Program the UV plane on planar master */
680 : 0 : color_plane = 1;
681 : :
682 : 0 : skl_program_plane(plane, crtc_state, plane_state, color_plane);
683 : 0 : }
684 : : static void
685 : 0 : skl_disable_plane(struct intel_plane *plane,
686 : : const struct intel_crtc_state *crtc_state)
687 : : {
688 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
689 : 0 : enum plane_id plane_id = plane->id;
690 : 0 : enum pipe pipe = plane->pipe;
691 : 0 : unsigned long irqflags;
692 : :
693 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
694 : :
695 [ # # # # ]: 0 : if (icl_is_hdr_plane(dev_priv, plane_id))
696 : 0 : I915_WRITE_FW(PLANE_CUS_CTL(pipe, plane_id), 0);
697 : :
698 : 0 : skl_write_plane_wm(plane, crtc_state);
699 : :
700 : 0 : I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0);
701 : 0 : I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0);
702 : :
703 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
704 : 0 : }
705 : :
706 : : static bool
707 : 0 : skl_plane_get_hw_state(struct intel_plane *plane,
708 : : enum pipe *pipe)
709 : : {
710 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
711 : 0 : enum intel_display_power_domain power_domain;
712 : 0 : enum plane_id plane_id = plane->id;
713 : 0 : intel_wakeref_t wakeref;
714 : 0 : bool ret;
715 : :
716 : 0 : power_domain = POWER_DOMAIN_PIPE(plane->pipe);
717 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
718 [ # # ]: 0 : if (!wakeref)
719 : : return false;
720 : :
721 : 0 : ret = I915_READ(PLANE_CTL(plane->pipe, plane_id)) & PLANE_CTL_ENABLE;
722 : :
723 : 0 : *pipe = plane->pipe;
724 : :
725 : 0 : intel_display_power_put(dev_priv, power_domain, wakeref);
726 : :
727 : 0 : return ret;
728 : : }
729 : :
730 : : static void i9xx_plane_linear_gamma(u16 gamma[8])
731 : : {
732 : : /* The points are not evenly spaced. */
733 : : static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
734 : : int i;
735 : :
736 : : for (i = 0; i < 8; i++)
737 : : gamma[i] = (in[i] << 8) / 32;
738 : : }
739 : :
740 : : static void
741 : 0 : chv_update_csc(const struct intel_plane_state *plane_state)
742 : : {
743 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
744 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
745 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
746 : 0 : enum plane_id plane_id = plane->id;
747 : : /*
748 : : * |r| | c0 c1 c2 | |cr|
749 : : * |g| = | c3 c4 c5 | x |y |
750 : : * |b| | c6 c7 c8 | |cb|
751 : : *
752 : : * Coefficients are s3.12.
753 : : *
754 : : * Cb and Cr apparently come in as signed already, and
755 : : * we always get full range data in on account of CLRC0/1.
756 : : */
757 : 0 : static const s16 csc_matrix[][9] = {
758 : : /* BT.601 full range YCbCr -> full range RGB */
759 : : [DRM_COLOR_YCBCR_BT601] = {
760 : : 5743, 4096, 0,
761 : : -2925, 4096, -1410,
762 : : 0, 4096, 7258,
763 : : },
764 : : /* BT.709 full range YCbCr -> full range RGB */
765 : : [DRM_COLOR_YCBCR_BT709] = {
766 : : 6450, 4096, 0,
767 : : -1917, 4096, -767,
768 : : 0, 4096, 7601,
769 : : },
770 : : };
771 : 0 : const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
772 : :
773 : : /* Seems RGB data bypasses the CSC always */
774 [ # # ]: 0 : if (!fb->format->is_yuv)
775 : : return;
776 : :
777 : 0 : I915_WRITE_FW(SPCSCYGOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
778 : 0 : I915_WRITE_FW(SPCSCCBOFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
779 : 0 : I915_WRITE_FW(SPCSCCROFF(plane_id), SPCSC_OOFF(0) | SPCSC_IOFF(0));
780 : :
781 : 0 : I915_WRITE_FW(SPCSCC01(plane_id), SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
782 : 0 : I915_WRITE_FW(SPCSCC23(plane_id), SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
783 : 0 : I915_WRITE_FW(SPCSCC45(plane_id), SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
784 : 0 : I915_WRITE_FW(SPCSCC67(plane_id), SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
785 : 0 : I915_WRITE_FW(SPCSCC8(plane_id), SPCSC_C0(csc[8]));
786 : :
787 : 0 : I915_WRITE_FW(SPCSCYGICLAMP(plane_id), SPCSC_IMAX(1023) | SPCSC_IMIN(0));
788 : 0 : I915_WRITE_FW(SPCSCCBICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
789 : 0 : I915_WRITE_FW(SPCSCCRICLAMP(plane_id), SPCSC_IMAX(512) | SPCSC_IMIN(-512));
790 : :
791 : 0 : I915_WRITE_FW(SPCSCYGOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
792 : 0 : I915_WRITE_FW(SPCSCCBOCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
793 : 0 : I915_WRITE_FW(SPCSCCROCLAMP(plane_id), SPCSC_OMAX(1023) | SPCSC_OMIN(0));
794 : : }
795 : :
796 : : #define SIN_0 0
797 : : #define COS_0 1
798 : :
799 : : static void
800 : 0 : vlv_update_clrc(const struct intel_plane_state *plane_state)
801 : : {
802 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
803 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
804 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
805 : 0 : enum pipe pipe = plane->pipe;
806 : 0 : enum plane_id plane_id = plane->id;
807 : 0 : int contrast, brightness, sh_scale, sh_sin, sh_cos;
808 : :
809 [ # # ]: 0 : if (fb->format->is_yuv &&
810 [ # # ]: 0 : plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
811 : : /*
812 : : * Expand limited range to full range:
813 : : * Contrast is applied first and is used to expand Y range.
814 : : * Brightness is applied second and is used to remove the
815 : : * offset from Y. Saturation/hue is used to expand CbCr range.
816 : : */
817 : : contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
818 : : brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
819 : : sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
820 : : sh_sin = SIN_0 * sh_scale;
821 : : sh_cos = COS_0 * sh_scale;
822 : : } else {
823 : : /* Pass-through everything. */
824 : 0 : contrast = 1 << 6;
825 : 0 : brightness = 0;
826 : 0 : sh_scale = 1 << 7;
827 : 0 : sh_sin = SIN_0 * sh_scale;
828 : 0 : sh_cos = COS_0 * sh_scale;
829 : : }
830 : :
831 : : /* FIXME these register are single buffered :( */
832 : 0 : I915_WRITE_FW(SPCLRC0(pipe, plane_id),
833 : : SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
834 : 0 : I915_WRITE_FW(SPCLRC1(pipe, plane_id),
835 : : SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
836 : 0 : }
837 : :
838 : : static void
839 : : vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
840 : : const struct intel_plane_state *plane_state,
841 : : unsigned int *num, unsigned int *den)
842 : : {
843 : : u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
844 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
845 : : unsigned int cpp = fb->format->cpp[0];
846 : :
847 : : /*
848 : : * VLV bspec only considers cases where all three planes are
849 : : * enabled, and cases where the primary and one sprite is enabled.
850 : : * Let's assume the case with just two sprites enabled also
851 : : * maps to the latter case.
852 : : */
853 : : if (hweight8(active_planes) == 3) {
854 : : switch (cpp) {
855 : : case 8:
856 : : *num = 11;
857 : : *den = 8;
858 : : break;
859 : : case 4:
860 : : *num = 18;
861 : : *den = 16;
862 : : break;
863 : : default:
864 : : *num = 1;
865 : : *den = 1;
866 : : break;
867 : : }
868 : : } else if (hweight8(active_planes) == 2) {
869 : : switch (cpp) {
870 : : case 8:
871 : : *num = 10;
872 : : *den = 8;
873 : : break;
874 : : case 4:
875 : : *num = 17;
876 : : *den = 16;
877 : : break;
878 : : default:
879 : : *num = 1;
880 : : *den = 1;
881 : : break;
882 : : }
883 : : } else {
884 : : switch (cpp) {
885 : : case 8:
886 : : *num = 10;
887 : : *den = 8;
888 : : break;
889 : : default:
890 : : *num = 1;
891 : : *den = 1;
892 : : break;
893 : : }
894 : : }
895 : : }
896 : :
897 : 0 : int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
898 : : const struct intel_plane_state *plane_state)
899 : : {
900 : 0 : unsigned int pixel_rate;
901 : 0 : unsigned int num, den;
902 : :
903 : : /*
904 : : * Note that crtc_state->pixel_rate accounts for both
905 : : * horizontal and vertical panel fitter downscaling factors.
906 : : * Pre-HSW bspec tells us to only consider the horizontal
907 : : * downscaling factor here. We ignore that and just consider
908 : : * both for simplicity.
909 : : */
910 : 0 : pixel_rate = crtc_state->pixel_rate;
911 : :
912 : 0 : vlv_plane_ratio(crtc_state, plane_state, &num, &den);
913 : :
914 : 0 : return DIV_ROUND_UP(pixel_rate * num, den);
915 : : }
916 : :
917 : 0 : static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
918 : : {
919 : 0 : u32 sprctl = 0;
920 : :
921 : 0 : if (crtc_state->gamma_enable)
922 : 0 : sprctl |= SP_GAMMA_ENABLE;
923 : :
924 : 0 : return sprctl;
925 : : }
926 : :
927 : : static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
928 : : const struct intel_plane_state *plane_state)
929 : : {
930 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
931 : : unsigned int rotation = plane_state->hw.rotation;
932 : : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
933 : : u32 sprctl;
934 : :
935 : : sprctl = SP_ENABLE;
936 : :
937 : : switch (fb->format->format) {
938 : : case DRM_FORMAT_YUYV:
939 : : sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
940 : : break;
941 : : case DRM_FORMAT_YVYU:
942 : : sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
943 : : break;
944 : : case DRM_FORMAT_UYVY:
945 : : sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
946 : : break;
947 : : case DRM_FORMAT_VYUY:
948 : : sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
949 : : break;
950 : : case DRM_FORMAT_C8:
951 : : sprctl |= SP_FORMAT_8BPP;
952 : : break;
953 : : case DRM_FORMAT_RGB565:
954 : : sprctl |= SP_FORMAT_BGR565;
955 : : break;
956 : : case DRM_FORMAT_XRGB8888:
957 : : sprctl |= SP_FORMAT_BGRX8888;
958 : : break;
959 : : case DRM_FORMAT_ARGB8888:
960 : : sprctl |= SP_FORMAT_BGRA8888;
961 : : break;
962 : : case DRM_FORMAT_XBGR2101010:
963 : : sprctl |= SP_FORMAT_RGBX1010102;
964 : : break;
965 : : case DRM_FORMAT_ABGR2101010:
966 : : sprctl |= SP_FORMAT_RGBA1010102;
967 : : break;
968 : : case DRM_FORMAT_XRGB2101010:
969 : : sprctl |= SP_FORMAT_BGRX1010102;
970 : : break;
971 : : case DRM_FORMAT_ARGB2101010:
972 : : sprctl |= SP_FORMAT_BGRA1010102;
973 : : break;
974 : : case DRM_FORMAT_XBGR8888:
975 : : sprctl |= SP_FORMAT_RGBX8888;
976 : : break;
977 : : case DRM_FORMAT_ABGR8888:
978 : : sprctl |= SP_FORMAT_RGBA8888;
979 : : break;
980 : : default:
981 : : MISSING_CASE(fb->format->format);
982 : : return 0;
983 : : }
984 : :
985 : : if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
986 : : sprctl |= SP_YUV_FORMAT_BT709;
987 : :
988 : : if (fb->modifier == I915_FORMAT_MOD_X_TILED)
989 : : sprctl |= SP_TILED;
990 : :
991 : : if (rotation & DRM_MODE_ROTATE_180)
992 : : sprctl |= SP_ROTATE_180;
993 : :
994 : : if (rotation & DRM_MODE_REFLECT_X)
995 : : sprctl |= SP_MIRROR;
996 : :
997 : : if (key->flags & I915_SET_COLORKEY_SOURCE)
998 : : sprctl |= SP_SOURCE_KEY;
999 : :
1000 : : return sprctl;
1001 : : }
1002 : :
1003 : : static void vlv_update_gamma(const struct intel_plane_state *plane_state)
1004 : : {
1005 : : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1006 : : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1007 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1008 : : enum pipe pipe = plane->pipe;
1009 : : enum plane_id plane_id = plane->id;
1010 : : u16 gamma[8];
1011 : : int i;
1012 : :
1013 : : /* Seems RGB data bypasses the gamma always */
1014 : : if (!fb->format->is_yuv)
1015 : : return;
1016 : :
1017 : : i9xx_plane_linear_gamma(gamma);
1018 : :
1019 : : /* FIXME these register are single buffered :( */
1020 : : /* The two end points are implicit (0.0 and 1.0) */
1021 : : for (i = 1; i < 8 - 1; i++)
1022 : : I915_WRITE_FW(SPGAMC(pipe, plane_id, i - 1),
1023 : : gamma[i] << 16 |
1024 : : gamma[i] << 8 |
1025 : : gamma[i]);
1026 : : }
1027 : :
1028 : : static void
1029 : 0 : vlv_update_plane(struct intel_plane *plane,
1030 : : const struct intel_crtc_state *crtc_state,
1031 : : const struct intel_plane_state *plane_state)
1032 : : {
1033 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1034 : 0 : enum pipe pipe = plane->pipe;
1035 : 0 : enum plane_id plane_id = plane->id;
1036 : 0 : u32 sprsurf_offset = plane_state->color_plane[0].offset;
1037 : 0 : u32 linear_offset;
1038 : 0 : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1039 : 0 : int crtc_x = plane_state->uapi.dst.x1;
1040 : 0 : int crtc_y = plane_state->uapi.dst.y1;
1041 [ # # ]: 0 : u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1042 [ # # ]: 0 : u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1043 : 0 : u32 x = plane_state->color_plane[0].x;
1044 : 0 : u32 y = plane_state->color_plane[0].y;
1045 : 0 : unsigned long irqflags;
1046 : 0 : u32 sprctl;
1047 : :
1048 [ # # ]: 0 : sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
1049 : :
1050 : : /* Sizes are 0 based */
1051 : 0 : crtc_w--;
1052 : 0 : crtc_h--;
1053 : :
1054 : 0 : linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1055 : :
1056 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1057 : :
1058 : 0 : I915_WRITE_FW(SPSTRIDE(pipe, plane_id),
1059 : : plane_state->color_plane[0].stride);
1060 : 0 : I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x);
1061 : 0 : I915_WRITE_FW(SPSIZE(pipe, plane_id), (crtc_h << 16) | crtc_w);
1062 : 0 : I915_WRITE_FW(SPCONSTALPHA(pipe, plane_id), 0);
1063 : :
1064 [ # # # # ]: 0 : if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
1065 : 0 : chv_update_csc(plane_state);
1066 : :
1067 [ # # ]: 0 : if (key->flags) {
1068 : 0 : I915_WRITE_FW(SPKEYMINVAL(pipe, plane_id), key->min_value);
1069 : 0 : I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask);
1070 : 0 : I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value);
1071 : : }
1072 : :
1073 : 0 : I915_WRITE_FW(SPLINOFF(pipe, plane_id), linear_offset);
1074 : 0 : I915_WRITE_FW(SPTILEOFF(pipe, plane_id), (y << 16) | x);
1075 : :
1076 : : /*
1077 : : * The control register self-arms if the plane was previously
1078 : : * disabled. Try to make the plane enable atomic by writing
1079 : : * the control register just before the surface register.
1080 : : */
1081 : 0 : I915_WRITE_FW(SPCNTR(pipe, plane_id), sprctl);
1082 : 0 : I915_WRITE_FW(SPSURF(pipe, plane_id),
1083 : : intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1084 : :
1085 : 0 : vlv_update_clrc(plane_state);
1086 : 0 : vlv_update_gamma(plane_state);
1087 : :
1088 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1089 : 0 : }
1090 : :
1091 : : static void
1092 : 0 : vlv_disable_plane(struct intel_plane *plane,
1093 : : const struct intel_crtc_state *crtc_state)
1094 : : {
1095 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1096 : 0 : enum pipe pipe = plane->pipe;
1097 : 0 : enum plane_id plane_id = plane->id;
1098 : 0 : unsigned long irqflags;
1099 : :
1100 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1101 : :
1102 : 0 : I915_WRITE_FW(SPCNTR(pipe, plane_id), 0);
1103 : 0 : I915_WRITE_FW(SPSURF(pipe, plane_id), 0);
1104 : :
1105 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1106 : 0 : }
1107 : :
1108 : : static bool
1109 : 0 : vlv_plane_get_hw_state(struct intel_plane *plane,
1110 : : enum pipe *pipe)
1111 : : {
1112 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1113 : 0 : enum intel_display_power_domain power_domain;
1114 : 0 : enum plane_id plane_id = plane->id;
1115 : 0 : intel_wakeref_t wakeref;
1116 : 0 : bool ret;
1117 : :
1118 : 0 : power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1119 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1120 [ # # ]: 0 : if (!wakeref)
1121 : : return false;
1122 : :
1123 : 0 : ret = I915_READ(SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
1124 : :
1125 : 0 : *pipe = plane->pipe;
1126 : :
1127 : 0 : intel_display_power_put(dev_priv, power_domain, wakeref);
1128 : :
1129 : 0 : return ret;
1130 : : }
1131 : :
1132 : : static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
1133 : : const struct intel_plane_state *plane_state,
1134 : : unsigned int *num, unsigned int *den)
1135 : : {
1136 : : u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1137 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1138 : : unsigned int cpp = fb->format->cpp[0];
1139 : :
1140 : : if (hweight8(active_planes) == 2) {
1141 : : switch (cpp) {
1142 : : case 8:
1143 : : *num = 10;
1144 : : *den = 8;
1145 : : break;
1146 : : case 4:
1147 : : *num = 17;
1148 : : *den = 16;
1149 : : break;
1150 : : default:
1151 : : *num = 1;
1152 : : *den = 1;
1153 : : break;
1154 : : }
1155 : : } else {
1156 : : switch (cpp) {
1157 : : case 8:
1158 : : *num = 9;
1159 : : *den = 8;
1160 : : break;
1161 : : default:
1162 : : *num = 1;
1163 : : *den = 1;
1164 : : break;
1165 : : }
1166 : : }
1167 : : }
1168 : :
1169 : 0 : static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
1170 : : const struct intel_plane_state *plane_state,
1171 : : unsigned int *num, unsigned int *den)
1172 : : {
1173 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
1174 : 0 : unsigned int cpp = fb->format->cpp[0];
1175 : :
1176 : 0 : switch (cpp) {
1177 : 0 : case 8:
1178 : 0 : *num = 12;
1179 : 0 : *den = 8;
1180 : 0 : break;
1181 : 0 : case 4:
1182 : 0 : *num = 19;
1183 : 0 : *den = 16;
1184 : 0 : break;
1185 : 0 : case 2:
1186 : 0 : *num = 33;
1187 : 0 : *den = 32;
1188 : 0 : break;
1189 : 0 : default:
1190 : 0 : *num = 1;
1191 : 0 : *den = 1;
1192 : 0 : break;
1193 : : }
1194 : : }
1195 : :
1196 : 0 : int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1197 : : const struct intel_plane_state *plane_state)
1198 : : {
1199 : 0 : unsigned int pixel_rate;
1200 : 0 : unsigned int num, den;
1201 : :
1202 : : /*
1203 : : * Note that crtc_state->pixel_rate accounts for both
1204 : : * horizontal and vertical panel fitter downscaling factors.
1205 : : * Pre-HSW bspec tells us to only consider the horizontal
1206 : : * downscaling factor here. We ignore that and just consider
1207 : : * both for simplicity.
1208 : : */
1209 : 0 : pixel_rate = crtc_state->pixel_rate;
1210 : :
1211 : 0 : ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1212 : :
1213 : 0 : return DIV_ROUND_UP(pixel_rate * num, den);
1214 : : }
1215 : :
1216 : 0 : static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1217 : : const struct intel_plane_state *plane_state)
1218 : : {
1219 : 0 : unsigned int src_w, dst_w, pixel_rate;
1220 : 0 : unsigned int num, den;
1221 : :
1222 : : /*
1223 : : * Note that crtc_state->pixel_rate accounts for both
1224 : : * horizontal and vertical panel fitter downscaling factors.
1225 : : * Pre-HSW bspec tells us to only consider the horizontal
1226 : : * downscaling factor here. We ignore that and just consider
1227 : : * both for simplicity.
1228 : : */
1229 : 0 : pixel_rate = crtc_state->pixel_rate;
1230 : :
1231 [ # # ]: 0 : src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1232 : 0 : dst_w = drm_rect_width(&plane_state->uapi.dst);
1233 : :
1234 [ # # ]: 0 : if (src_w != dst_w)
1235 [ # # # # ]: 0 : ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
1236 : : else
1237 : 0 : ivb_plane_ratio(crtc_state, plane_state, &num, &den);
1238 : :
1239 : : /* Horizontal downscaling limits the maximum pixel rate */
1240 : 0 : dst_w = min(src_w, dst_w);
1241 : :
1242 : 0 : return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
1243 : : den * dst_w);
1244 : : }
1245 : :
1246 : : static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
1247 : : const struct intel_plane_state *plane_state,
1248 : : unsigned int *num, unsigned int *den)
1249 : : {
1250 : : u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
1251 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1252 : : unsigned int cpp = fb->format->cpp[0];
1253 : :
1254 : : if (hweight8(active_planes) == 2) {
1255 : : switch (cpp) {
1256 : : case 8:
1257 : : *num = 10;
1258 : : *den = 8;
1259 : : break;
1260 : : default:
1261 : : *num = 1;
1262 : : *den = 1;
1263 : : break;
1264 : : }
1265 : : } else {
1266 : : switch (cpp) {
1267 : : case 8:
1268 : : *num = 9;
1269 : : *den = 8;
1270 : : break;
1271 : : default:
1272 : : *num = 1;
1273 : : *den = 1;
1274 : : break;
1275 : : }
1276 : : }
1277 : : }
1278 : :
1279 : 0 : int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
1280 : : const struct intel_plane_state *plane_state)
1281 : : {
1282 : 0 : unsigned int pixel_rate = crtc_state->pixel_rate;
1283 : 0 : unsigned int num, den;
1284 : :
1285 : 0 : hsw_plane_ratio(crtc_state, plane_state, &num, &den);
1286 : :
1287 : 0 : return DIV_ROUND_UP(pixel_rate * num, den);
1288 : : }
1289 : :
1290 : 0 : static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1291 : : {
1292 : 0 : u32 sprctl = 0;
1293 : :
1294 : 0 : if (crtc_state->gamma_enable)
1295 : 0 : sprctl |= SPRITE_GAMMA_ENABLE;
1296 : :
1297 [ # # ]: 0 : if (crtc_state->csc_enable)
1298 : 0 : sprctl |= SPRITE_PIPE_CSC_ENABLE;
1299 : :
1300 : 0 : return sprctl;
1301 : : }
1302 : :
1303 : 0 : static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
1304 : : {
1305 : 0 : struct drm_i915_private *dev_priv =
1306 : : to_i915(plane_state->uapi.plane->dev);
1307 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
1308 : :
1309 [ # # ]: 0 : return fb->format->cpp[0] == 8 &&
1310 [ # # ]: 0 : (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
1311 : : }
1312 : :
1313 : : static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
1314 : : const struct intel_plane_state *plane_state)
1315 : : {
1316 : : struct drm_i915_private *dev_priv =
1317 : : to_i915(plane_state->uapi.plane->dev);
1318 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1319 : : unsigned int rotation = plane_state->hw.rotation;
1320 : : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1321 : : u32 sprctl;
1322 : :
1323 : : sprctl = SPRITE_ENABLE;
1324 : :
1325 : : if (IS_IVYBRIDGE(dev_priv))
1326 : : sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
1327 : :
1328 : : switch (fb->format->format) {
1329 : : case DRM_FORMAT_XBGR8888:
1330 : : sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
1331 : : break;
1332 : : case DRM_FORMAT_XRGB8888:
1333 : : sprctl |= SPRITE_FORMAT_RGBX888;
1334 : : break;
1335 : : case DRM_FORMAT_XBGR2101010:
1336 : : sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
1337 : : break;
1338 : : case DRM_FORMAT_XRGB2101010:
1339 : : sprctl |= SPRITE_FORMAT_RGBX101010;
1340 : : break;
1341 : : case DRM_FORMAT_XBGR16161616F:
1342 : : sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
1343 : : break;
1344 : : case DRM_FORMAT_XRGB16161616F:
1345 : : sprctl |= SPRITE_FORMAT_RGBX161616;
1346 : : break;
1347 : : case DRM_FORMAT_YUYV:
1348 : : sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
1349 : : break;
1350 : : case DRM_FORMAT_YVYU:
1351 : : sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
1352 : : break;
1353 : : case DRM_FORMAT_UYVY:
1354 : : sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
1355 : : break;
1356 : : case DRM_FORMAT_VYUY:
1357 : : sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
1358 : : break;
1359 : : default:
1360 : : MISSING_CASE(fb->format->format);
1361 : : return 0;
1362 : : }
1363 : :
1364 : : if (!ivb_need_sprite_gamma(plane_state))
1365 : : sprctl |= SPRITE_INT_GAMMA_DISABLE;
1366 : :
1367 : : if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1368 : : sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
1369 : :
1370 : : if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1371 : : sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
1372 : :
1373 : : if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1374 : : sprctl |= SPRITE_TILED;
1375 : :
1376 : : if (rotation & DRM_MODE_ROTATE_180)
1377 : : sprctl |= SPRITE_ROTATE_180;
1378 : :
1379 : : if (key->flags & I915_SET_COLORKEY_DESTINATION)
1380 : : sprctl |= SPRITE_DEST_KEY;
1381 : : else if (key->flags & I915_SET_COLORKEY_SOURCE)
1382 : : sprctl |= SPRITE_SOURCE_KEY;
1383 : :
1384 : : return sprctl;
1385 : : }
1386 : :
1387 : : static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
1388 : : u16 gamma[18])
1389 : : {
1390 : : int scale, i;
1391 : :
1392 : : /*
1393 : : * WaFP16GammaEnabling:ivb,hsw
1394 : : * "Workaround : When using the 64-bit format, the sprite output
1395 : : * on each color channel has one quarter amplitude. It can be
1396 : : * brought up to full amplitude by using sprite internal gamma
1397 : : * correction, pipe gamma correction, or pipe color space
1398 : : * conversion to multiply the sprite output by four."
1399 : : */
1400 : : scale = 4;
1401 : :
1402 [ # # ]: 0 : for (i = 0; i < 16; i++)
1403 : 0 : gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
1404 : :
1405 : 0 : gamma[i] = min((scale * i << 10) / 16, 1 << 10);
1406 : 0 : i++;
1407 : :
1408 : 0 : gamma[i] = 3 << 10;
1409 : 0 : i++;
1410 : : }
1411 : :
1412 : 0 : static void ivb_update_gamma(const struct intel_plane_state *plane_state)
1413 : : {
1414 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1415 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1416 : 0 : enum pipe pipe = plane->pipe;
1417 : 0 : u16 gamma[18];
1418 : 0 : int i;
1419 : :
1420 [ # # # # ]: 0 : if (!ivb_need_sprite_gamma(plane_state))
1421 : 0 : return;
1422 : :
1423 : : ivb_sprite_linear_gamma(plane_state, gamma);
1424 : :
1425 : : /* FIXME these register are single buffered :( */
1426 [ # # ]: 0 : for (i = 0; i < 16; i++)
1427 : 0 : I915_WRITE_FW(SPRGAMC(pipe, i),
1428 : : gamma[i] << 20 |
1429 : : gamma[i] << 10 |
1430 : : gamma[i]);
1431 : :
1432 : 0 : I915_WRITE_FW(SPRGAMC16(pipe, 0), gamma[i]);
1433 : 0 : I915_WRITE_FW(SPRGAMC16(pipe, 1), gamma[i]);
1434 : 0 : I915_WRITE_FW(SPRGAMC16(pipe, 2), gamma[i]);
1435 : 0 : i++;
1436 : :
1437 : 0 : I915_WRITE_FW(SPRGAMC17(pipe, 0), gamma[i]);
1438 : 0 : I915_WRITE_FW(SPRGAMC17(pipe, 1), gamma[i]);
1439 : 0 : I915_WRITE_FW(SPRGAMC17(pipe, 2), gamma[i]);
1440 : 0 : i++;
1441 : : }
1442 : :
1443 : : static void
1444 : 0 : ivb_update_plane(struct intel_plane *plane,
1445 : : const struct intel_crtc_state *crtc_state,
1446 : : const struct intel_plane_state *plane_state)
1447 : : {
1448 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1449 : 0 : enum pipe pipe = plane->pipe;
1450 : 0 : u32 sprsurf_offset = plane_state->color_plane[0].offset;
1451 : 0 : u32 linear_offset;
1452 : 0 : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1453 : 0 : int crtc_x = plane_state->uapi.dst.x1;
1454 : 0 : int crtc_y = plane_state->uapi.dst.y1;
1455 [ # # ]: 0 : u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1456 [ # # ]: 0 : u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1457 : 0 : u32 x = plane_state->color_plane[0].x;
1458 : 0 : u32 y = plane_state->color_plane[0].y;
1459 : 0 : u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1460 : 0 : u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1461 : 0 : u32 sprctl, sprscale = 0;
1462 : 0 : unsigned long irqflags;
1463 : :
1464 [ # # ]: 0 : sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
1465 : :
1466 : : /* Sizes are 0 based */
1467 : 0 : src_w--;
1468 : 0 : src_h--;
1469 : 0 : crtc_w--;
1470 : 0 : crtc_h--;
1471 : :
1472 [ # # ]: 0 : if (crtc_w != src_w || crtc_h != src_h)
1473 : 0 : sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
1474 : :
1475 : 0 : linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1476 : :
1477 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1478 : :
1479 : 0 : I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride);
1480 : 0 : I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
1481 : 0 : I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w);
1482 [ # # ]: 0 : if (IS_IVYBRIDGE(dev_priv))
1483 : 0 : I915_WRITE_FW(SPRSCALE(pipe), sprscale);
1484 : :
1485 [ # # ]: 0 : if (key->flags) {
1486 : 0 : I915_WRITE_FW(SPRKEYVAL(pipe), key->min_value);
1487 : 0 : I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask);
1488 : 0 : I915_WRITE_FW(SPRKEYMAX(pipe), key->max_value);
1489 : : }
1490 : :
1491 : : /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
1492 : : * register */
1493 [ # # # # ]: 0 : if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
1494 : 0 : I915_WRITE_FW(SPROFFSET(pipe), (y << 16) | x);
1495 : : } else {
1496 : 0 : I915_WRITE_FW(SPRLINOFF(pipe), linear_offset);
1497 : 0 : I915_WRITE_FW(SPRTILEOFF(pipe), (y << 16) | x);
1498 : : }
1499 : :
1500 : : /*
1501 : : * The control register self-arms if the plane was previously
1502 : : * disabled. Try to make the plane enable atomic by writing
1503 : : * the control register just before the surface register.
1504 : : */
1505 : 0 : I915_WRITE_FW(SPRCTL(pipe), sprctl);
1506 : 0 : I915_WRITE_FW(SPRSURF(pipe),
1507 : : intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
1508 : :
1509 : 0 : ivb_update_gamma(plane_state);
1510 : :
1511 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1512 : 0 : }
1513 : :
1514 : : static void
1515 : 0 : ivb_disable_plane(struct intel_plane *plane,
1516 : : const struct intel_crtc_state *crtc_state)
1517 : : {
1518 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1519 : 0 : enum pipe pipe = plane->pipe;
1520 : 0 : unsigned long irqflags;
1521 : :
1522 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1523 : :
1524 : 0 : I915_WRITE_FW(SPRCTL(pipe), 0);
1525 : : /* Disable the scaler */
1526 [ # # ]: 0 : if (IS_IVYBRIDGE(dev_priv))
1527 : 0 : I915_WRITE_FW(SPRSCALE(pipe), 0);
1528 : 0 : I915_WRITE_FW(SPRSURF(pipe), 0);
1529 : :
1530 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1531 : 0 : }
1532 : :
1533 : : static bool
1534 : 0 : ivb_plane_get_hw_state(struct intel_plane *plane,
1535 : : enum pipe *pipe)
1536 : : {
1537 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1538 : 0 : enum intel_display_power_domain power_domain;
1539 : 0 : intel_wakeref_t wakeref;
1540 : 0 : bool ret;
1541 : :
1542 : 0 : power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1543 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1544 [ # # ]: 0 : if (!wakeref)
1545 : : return false;
1546 : :
1547 : 0 : ret = I915_READ(SPRCTL(plane->pipe)) & SPRITE_ENABLE;
1548 : :
1549 : 0 : *pipe = plane->pipe;
1550 : :
1551 : 0 : intel_display_power_put(dev_priv, power_domain, wakeref);
1552 : :
1553 : 0 : return ret;
1554 : : }
1555 : :
1556 : 0 : static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
1557 : : const struct intel_plane_state *plane_state)
1558 : : {
1559 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
1560 : 0 : unsigned int hscale, pixel_rate;
1561 : 0 : unsigned int limit, decimate;
1562 : :
1563 : : /*
1564 : : * Note that crtc_state->pixel_rate accounts for both
1565 : : * horizontal and vertical panel fitter downscaling factors.
1566 : : * Pre-HSW bspec tells us to only consider the horizontal
1567 : : * downscaling factor here. We ignore that and just consider
1568 : : * both for simplicity.
1569 : : */
1570 : 0 : pixel_rate = crtc_state->pixel_rate;
1571 : :
1572 : : /* Horizontal downscaling limits the maximum pixel rate */
1573 : 0 : hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
1574 : : &plane_state->uapi.dst,
1575 : : 0, INT_MAX);
1576 [ # # ]: 0 : if (hscale < 0x10000)
1577 : 0 : return pixel_rate;
1578 : :
1579 : : /* Decimation steps at 2x,4x,8x,16x */
1580 [ # # # # : 0 : decimate = ilog2(hscale >> 16);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
1581 : 0 : hscale >>= decimate;
1582 : :
1583 : : /* Starting limit is 90% of cdclk */
1584 : 0 : limit = 9;
1585 : :
1586 : : /* -10% per decimation step */
1587 : 0 : limit -= decimate;
1588 : :
1589 : : /* -10% for RGB */
1590 [ # # ]: 0 : if (fb->format->cpp[0] >= 4)
1591 : 0 : limit--; /* -10% for RGB */
1592 : :
1593 : : /*
1594 : : * We should also do -10% if sprite scaling is enabled
1595 : : * on the other pipe, but we can't really check for that,
1596 : : * so we ignore it.
1597 : : */
1598 : :
1599 : 0 : return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
1600 : : limit << 16);
1601 : : }
1602 : :
1603 : : static unsigned int
1604 : 0 : g4x_sprite_max_stride(struct intel_plane *plane,
1605 : : u32 pixel_format, u64 modifier,
1606 : : unsigned int rotation)
1607 : : {
1608 : 0 : return 16384;
1609 : : }
1610 : :
1611 : 0 : static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
1612 : : {
1613 : 0 : u32 dvscntr = 0;
1614 : :
1615 : 0 : if (crtc_state->gamma_enable)
1616 : 0 : dvscntr |= DVS_GAMMA_ENABLE;
1617 : :
1618 [ # # ]: 0 : if (crtc_state->csc_enable)
1619 : 0 : dvscntr |= DVS_PIPE_CSC_ENABLE;
1620 : :
1621 : 0 : return dvscntr;
1622 : : }
1623 : :
1624 : : static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
1625 : : const struct intel_plane_state *plane_state)
1626 : : {
1627 : : struct drm_i915_private *dev_priv =
1628 : : to_i915(plane_state->uapi.plane->dev);
1629 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1630 : : unsigned int rotation = plane_state->hw.rotation;
1631 : : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1632 : : u32 dvscntr;
1633 : :
1634 : : dvscntr = DVS_ENABLE;
1635 : :
1636 : : if (IS_GEN(dev_priv, 6))
1637 : : dvscntr |= DVS_TRICKLE_FEED_DISABLE;
1638 : :
1639 : : switch (fb->format->format) {
1640 : : case DRM_FORMAT_XBGR8888:
1641 : : dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
1642 : : break;
1643 : : case DRM_FORMAT_XRGB8888:
1644 : : dvscntr |= DVS_FORMAT_RGBX888;
1645 : : break;
1646 : : case DRM_FORMAT_XBGR2101010:
1647 : : dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
1648 : : break;
1649 : : case DRM_FORMAT_XRGB2101010:
1650 : : dvscntr |= DVS_FORMAT_RGBX101010;
1651 : : break;
1652 : : case DRM_FORMAT_XBGR16161616F:
1653 : : dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1654 : : break;
1655 : : case DRM_FORMAT_XRGB16161616F:
1656 : : dvscntr |= DVS_FORMAT_RGBX161616;
1657 : : break;
1658 : : case DRM_FORMAT_YUYV:
1659 : : dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1660 : : break;
1661 : : case DRM_FORMAT_YVYU:
1662 : : dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1663 : : break;
1664 : : case DRM_FORMAT_UYVY:
1665 : : dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1666 : : break;
1667 : : case DRM_FORMAT_VYUY:
1668 : : dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1669 : : break;
1670 : : default:
1671 : : MISSING_CASE(fb->format->format);
1672 : : return 0;
1673 : : }
1674 : :
1675 : : if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1676 : : dvscntr |= DVS_YUV_FORMAT_BT709;
1677 : :
1678 : : if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1679 : : dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1680 : :
1681 : : if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1682 : : dvscntr |= DVS_TILED;
1683 : :
1684 : : if (rotation & DRM_MODE_ROTATE_180)
1685 : : dvscntr |= DVS_ROTATE_180;
1686 : :
1687 : : if (key->flags & I915_SET_COLORKEY_DESTINATION)
1688 : : dvscntr |= DVS_DEST_KEY;
1689 : : else if (key->flags & I915_SET_COLORKEY_SOURCE)
1690 : : dvscntr |= DVS_SOURCE_KEY;
1691 : :
1692 : : return dvscntr;
1693 : : }
1694 : :
1695 : : static void g4x_update_gamma(const struct intel_plane_state *plane_state)
1696 : : {
1697 : : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1698 : : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1699 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1700 : : enum pipe pipe = plane->pipe;
1701 : : u16 gamma[8];
1702 : : int i;
1703 : :
1704 : : /* Seems RGB data bypasses the gamma always */
1705 : : if (!fb->format->is_yuv)
1706 : : return;
1707 : :
1708 : : i9xx_plane_linear_gamma(gamma);
1709 : :
1710 : : /* FIXME these register are single buffered :( */
1711 : : /* The two end points are implicit (0.0 and 1.0) */
1712 : : for (i = 1; i < 8 - 1; i++)
1713 : : I915_WRITE_FW(DVSGAMC_G4X(pipe, i - 1),
1714 : : gamma[i] << 16 |
1715 : : gamma[i] << 8 |
1716 : : gamma[i]);
1717 : : }
1718 : :
1719 : : static void ilk_sprite_linear_gamma(u16 gamma[17])
1720 : : {
1721 : : int i;
1722 : :
1723 : : for (i = 0; i < 17; i++)
1724 : : gamma[i] = (i << 10) / 16;
1725 : : }
1726 : :
1727 : : static void ilk_update_gamma(const struct intel_plane_state *plane_state)
1728 : : {
1729 : : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1730 : : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1731 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
1732 : : enum pipe pipe = plane->pipe;
1733 : : u16 gamma[17];
1734 : : int i;
1735 : :
1736 : : /* Seems RGB data bypasses the gamma always */
1737 : : if (!fb->format->is_yuv)
1738 : : return;
1739 : :
1740 : : ilk_sprite_linear_gamma(gamma);
1741 : :
1742 : : /* FIXME these register are single buffered :( */
1743 : : for (i = 0; i < 16; i++)
1744 : : I915_WRITE_FW(DVSGAMC_ILK(pipe, i),
1745 : : gamma[i] << 20 |
1746 : : gamma[i] << 10 |
1747 : : gamma[i]);
1748 : :
1749 : : I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1750 : : I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1751 : : I915_WRITE_FW(DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1752 : : i++;
1753 : : }
1754 : :
1755 : : static void
1756 : 0 : g4x_update_plane(struct intel_plane *plane,
1757 : : const struct intel_crtc_state *crtc_state,
1758 : : const struct intel_plane_state *plane_state)
1759 : : {
1760 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1761 : 0 : enum pipe pipe = plane->pipe;
1762 : 0 : u32 dvssurf_offset = plane_state->color_plane[0].offset;
1763 : 0 : u32 linear_offset;
1764 : 0 : const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1765 : 0 : int crtc_x = plane_state->uapi.dst.x1;
1766 : 0 : int crtc_y = plane_state->uapi.dst.y1;
1767 [ # # ]: 0 : u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1768 [ # # ]: 0 : u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1769 : 0 : u32 x = plane_state->color_plane[0].x;
1770 : 0 : u32 y = plane_state->color_plane[0].y;
1771 : 0 : u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1772 : 0 : u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1773 : 0 : u32 dvscntr, dvsscale = 0;
1774 : 0 : unsigned long irqflags;
1775 : :
1776 [ # # ]: 0 : dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1777 : :
1778 : : /* Sizes are 0 based */
1779 : 0 : src_w--;
1780 : 0 : src_h--;
1781 : 0 : crtc_w--;
1782 : 0 : crtc_h--;
1783 : :
1784 [ # # ]: 0 : if (crtc_w != src_w || crtc_h != src_h)
1785 : 0 : dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
1786 : :
1787 : 0 : linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1788 : :
1789 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1790 : :
1791 : 0 : I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride);
1792 : 0 : I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
1793 : 0 : I915_WRITE_FW(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
1794 : 0 : I915_WRITE_FW(DVSSCALE(pipe), dvsscale);
1795 : :
1796 [ # # ]: 0 : if (key->flags) {
1797 : 0 : I915_WRITE_FW(DVSKEYVAL(pipe), key->min_value);
1798 : 0 : I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask);
1799 : 0 : I915_WRITE_FW(DVSKEYMAX(pipe), key->max_value);
1800 : : }
1801 : :
1802 : 0 : I915_WRITE_FW(DVSLINOFF(pipe), linear_offset);
1803 : 0 : I915_WRITE_FW(DVSTILEOFF(pipe), (y << 16) | x);
1804 : :
1805 : : /*
1806 : : * The control register self-arms if the plane was previously
1807 : : * disabled. Try to make the plane enable atomic by writing
1808 : : * the control register just before the surface register.
1809 : : */
1810 : 0 : I915_WRITE_FW(DVSCNTR(pipe), dvscntr);
1811 : 0 : I915_WRITE_FW(DVSSURF(pipe),
1812 : : intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1813 : :
1814 [ # # # # ]: 0 : if (IS_G4X(dev_priv))
1815 : 0 : g4x_update_gamma(plane_state);
1816 : : else
1817 : 0 : ilk_update_gamma(plane_state);
1818 : :
1819 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1820 : 0 : }
1821 : :
1822 : : static void
1823 : 0 : g4x_disable_plane(struct intel_plane *plane,
1824 : : const struct intel_crtc_state *crtc_state)
1825 : : {
1826 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1827 : 0 : enum pipe pipe = plane->pipe;
1828 : 0 : unsigned long irqflags;
1829 : :
1830 : 0 : spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
1831 : :
1832 : 0 : I915_WRITE_FW(DVSCNTR(pipe), 0);
1833 : : /* Disable the scaler */
1834 : 0 : I915_WRITE_FW(DVSSCALE(pipe), 0);
1835 : 0 : I915_WRITE_FW(DVSSURF(pipe), 0);
1836 : :
1837 : 0 : spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
1838 : 0 : }
1839 : :
1840 : : static bool
1841 : 0 : g4x_plane_get_hw_state(struct intel_plane *plane,
1842 : : enum pipe *pipe)
1843 : : {
1844 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1845 : 0 : enum intel_display_power_domain power_domain;
1846 : 0 : intel_wakeref_t wakeref;
1847 : 0 : bool ret;
1848 : :
1849 : 0 : power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1850 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1851 [ # # ]: 0 : if (!wakeref)
1852 : : return false;
1853 : :
1854 : 0 : ret = I915_READ(DVSCNTR(plane->pipe)) & DVS_ENABLE;
1855 : :
1856 : 0 : *pipe = plane->pipe;
1857 : :
1858 : 0 : intel_display_power_put(dev_priv, power_domain, wakeref);
1859 : :
1860 : 0 : return ret;
1861 : : }
1862 : :
1863 : 0 : static bool intel_fb_scalable(const struct drm_framebuffer *fb)
1864 : : {
1865 [ # # ]: 0 : if (!fb)
1866 : : return false;
1867 : :
1868 [ # # # ]: 0 : switch (fb->format->format) {
1869 : : case DRM_FORMAT_C8:
1870 : : return false;
1871 : 0 : case DRM_FORMAT_XRGB16161616F:
1872 : : case DRM_FORMAT_ARGB16161616F:
1873 : : case DRM_FORMAT_XBGR16161616F:
1874 : : case DRM_FORMAT_ABGR16161616F:
1875 : 0 : return INTEL_GEN(to_i915(fb->dev)) >= 11;
1876 : 0 : default:
1877 : 0 : return true;
1878 : : }
1879 : : }
1880 : :
1881 : : static int
1882 : 0 : g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1883 : : struct intel_plane_state *plane_state)
1884 : : {
1885 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
1886 : 0 : const struct drm_rect *src = &plane_state->uapi.src;
1887 : 0 : const struct drm_rect *dst = &plane_state->uapi.dst;
1888 : 0 : int src_x, src_w, src_h, crtc_w, crtc_h;
1889 : 0 : const struct drm_display_mode *adjusted_mode =
1890 : : &crtc_state->hw.adjusted_mode;
1891 : 0 : unsigned int stride = plane_state->color_plane[0].stride;
1892 : 0 : unsigned int cpp = fb->format->cpp[0];
1893 : 0 : unsigned int width_bytes;
1894 : 0 : int min_width, min_height;
1895 : :
1896 [ # # ]: 0 : crtc_w = drm_rect_width(dst);
1897 [ # # ]: 0 : crtc_h = drm_rect_height(dst);
1898 : :
1899 : 0 : src_x = src->x1 >> 16;
1900 : 0 : src_w = drm_rect_width(src) >> 16;
1901 : 0 : src_h = drm_rect_height(src) >> 16;
1902 : :
1903 [ # # ]: 0 : if (src_w == crtc_w && src_h == crtc_h)
1904 : : return 0;
1905 : :
1906 : 0 : min_width = 3;
1907 : :
1908 [ # # ]: 0 : if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1909 [ # # ]: 0 : if (src_h & 1) {
1910 : 0 : DRM_DEBUG_KMS("Source height must be even with interlaced modes\n");
1911 : 0 : return -EINVAL;
1912 : : }
1913 : : min_height = 6;
1914 : : } else {
1915 : : min_height = 3;
1916 : : }
1917 : :
1918 : 0 : width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1919 : :
1920 [ # # ]: 0 : if (src_w < min_width || src_h < min_height ||
1921 [ # # ]: 0 : src_w > 2048 || src_h > 2048) {
1922 : 0 : DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1923 : : src_w, src_h, min_width, min_height, 2048, 2048);
1924 : 0 : return -EINVAL;
1925 : : }
1926 : :
1927 [ # # ]: 0 : if (width_bytes > 4096) {
1928 : 0 : DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1929 : : width_bytes, 4096);
1930 : 0 : return -EINVAL;
1931 : : }
1932 : :
1933 [ # # ]: 0 : if (stride > 4096) {
1934 : 0 : DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n",
1935 : : stride, 4096);
1936 : 0 : return -EINVAL;
1937 : : }
1938 : :
1939 : : return 0;
1940 : : }
1941 : :
1942 : : static int
1943 : 0 : g4x_sprite_check(struct intel_crtc_state *crtc_state,
1944 : : struct intel_plane_state *plane_state)
1945 : : {
1946 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1947 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1948 : 0 : int min_scale = DRM_PLANE_HELPER_NO_SCALING;
1949 : 0 : int max_scale = DRM_PLANE_HELPER_NO_SCALING;
1950 : 0 : int ret;
1951 : :
1952 [ # # ]: 0 : if (intel_fb_scalable(plane_state->hw.fb)) {
1953 [ # # ]: 0 : if (INTEL_GEN(dev_priv) < 7) {
1954 : : min_scale = 1;
1955 : : max_scale = 16 << 16;
1956 [ # # ]: 0 : } else if (IS_IVYBRIDGE(dev_priv)) {
1957 : 0 : min_scale = 1;
1958 : 0 : max_scale = 2 << 16;
1959 : : }
1960 : : }
1961 : :
1962 : 0 : ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
1963 : 0 : &crtc_state->uapi,
1964 : : min_scale, max_scale,
1965 : : true, true);
1966 [ # # ]: 0 : if (ret)
1967 : : return ret;
1968 : :
1969 : 0 : ret = i9xx_check_plane_surface(plane_state);
1970 [ # # ]: 0 : if (ret)
1971 : : return ret;
1972 : :
1973 [ # # ]: 0 : if (!plane_state->uapi.visible)
1974 : : return 0;
1975 : :
1976 : 0 : ret = intel_plane_check_src_coordinates(plane_state);
1977 [ # # ]: 0 : if (ret)
1978 : : return ret;
1979 : :
1980 : 0 : ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1981 [ # # ]: 0 : if (ret)
1982 : : return ret;
1983 : :
1984 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 7)
1985 : 0 : plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1986 : : else
1987 : 0 : plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1988 : :
1989 : : return 0;
1990 : : }
1991 : :
1992 : 0 : int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1993 : : {
1994 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1995 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1996 : 0 : unsigned int rotation = plane_state->hw.rotation;
1997 : :
1998 : : /* CHV ignores the mirror bit when the rotate bit is set :( */
1999 [ # # ]: 0 : if (IS_CHERRYVIEW(dev_priv) &&
2000 [ # # ]: 0 : rotation & DRM_MODE_ROTATE_180 &&
2001 : : rotation & DRM_MODE_REFLECT_X) {
2002 : 0 : DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
2003 : 0 : return -EINVAL;
2004 : : }
2005 : :
2006 : : return 0;
2007 : : }
2008 : :
2009 : : static int
2010 : 0 : vlv_sprite_check(struct intel_crtc_state *crtc_state,
2011 : : struct intel_plane_state *plane_state)
2012 : : {
2013 : 0 : int ret;
2014 : :
2015 : 0 : ret = chv_plane_check_rotation(plane_state);
2016 [ # # ]: 0 : if (ret)
2017 : : return ret;
2018 : :
2019 : 0 : ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2020 : 0 : &crtc_state->uapi,
2021 : : DRM_PLANE_HELPER_NO_SCALING,
2022 : : DRM_PLANE_HELPER_NO_SCALING,
2023 : : true, true);
2024 [ # # ]: 0 : if (ret)
2025 : : return ret;
2026 : :
2027 : 0 : ret = i9xx_check_plane_surface(plane_state);
2028 [ # # ]: 0 : if (ret)
2029 : : return ret;
2030 : :
2031 [ # # ]: 0 : if (!plane_state->uapi.visible)
2032 : : return 0;
2033 : :
2034 : 0 : ret = intel_plane_check_src_coordinates(plane_state);
2035 [ # # ]: 0 : if (ret)
2036 : : return ret;
2037 : :
2038 : 0 : plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
2039 : :
2040 : 0 : return 0;
2041 : : }
2042 : :
2043 : : static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state,
2044 : : const struct intel_plane_state *plane_state)
2045 : : {
2046 : : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2047 : : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2048 : : const struct drm_framebuffer *fb = plane_state->hw.fb;
2049 : : unsigned int rotation = plane_state->hw.rotation;
2050 : : struct drm_format_name_buf format_name;
2051 : :
2052 : : if (!fb)
2053 : : return 0;
2054 : :
2055 : : if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) &&
2056 : : is_ccs_modifier(fb->modifier)) {
2057 : : DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n",
2058 : : rotation);
2059 : : return -EINVAL;
2060 : : }
2061 : :
2062 : : if (rotation & DRM_MODE_REFLECT_X &&
2063 : : fb->modifier == DRM_FORMAT_MOD_LINEAR) {
2064 : : DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
2065 : : return -EINVAL;
2066 : : }
2067 : :
2068 : : if (drm_rotation_90_or_270(rotation)) {
2069 : : if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
2070 : : fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
2071 : : DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
2072 : : return -EINVAL;
2073 : : }
2074 : :
2075 : : /*
2076 : : * 90/270 is not allowed with RGB64 16:16:16:16 and
2077 : : * Indexed 8-bit. RGB 16-bit 5:6:5 is allowed gen11 onwards.
2078 : : */
2079 : : switch (fb->format->format) {
2080 : : case DRM_FORMAT_RGB565:
2081 : : if (INTEL_GEN(dev_priv) >= 11)
2082 : : break;
2083 : : /* fall through */
2084 : : case DRM_FORMAT_C8:
2085 : : case DRM_FORMAT_XRGB16161616F:
2086 : : case DRM_FORMAT_XBGR16161616F:
2087 : : case DRM_FORMAT_ARGB16161616F:
2088 : : case DRM_FORMAT_ABGR16161616F:
2089 : : case DRM_FORMAT_Y210:
2090 : : case DRM_FORMAT_Y212:
2091 : : case DRM_FORMAT_Y216:
2092 : : case DRM_FORMAT_XVYU12_16161616:
2093 : : case DRM_FORMAT_XVYU16161616:
2094 : : DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
2095 : : drm_get_format_name(fb->format->format,
2096 : : &format_name));
2097 : : return -EINVAL;
2098 : : default:
2099 : : break;
2100 : : }
2101 : : }
2102 : :
2103 : : /* Y-tiling is not supported in IF-ID Interlace mode */
2104 : : if (crtc_state->hw.enable &&
2105 : : crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE &&
2106 : : (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
2107 : : fb->modifier == I915_FORMAT_MOD_Yf_TILED ||
2108 : : fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
2109 : : fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
2110 : : fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
2111 : : fb->modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)) {
2112 : : DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n");
2113 : : return -EINVAL;
2114 : : }
2115 : :
2116 : : return 0;
2117 : : }
2118 : :
2119 : : static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state,
2120 : : const struct intel_plane_state *plane_state)
2121 : : {
2122 : : struct drm_i915_private *dev_priv =
2123 : : to_i915(plane_state->uapi.plane->dev);
2124 : : int crtc_x = plane_state->uapi.dst.x1;
2125 : : int crtc_w = drm_rect_width(&plane_state->uapi.dst);
2126 : : int pipe_src_w = crtc_state->pipe_src_w;
2127 : :
2128 : : /*
2129 : : * Display WA #1175: cnl,glk
2130 : : * Planes other than the cursor may cause FIFO underflow and display
2131 : : * corruption if starting less than 4 pixels from the right edge of
2132 : : * the screen.
2133 : : * Besides the above WA fix the similar problem, where planes other
2134 : : * than the cursor ending less than 4 pixels from the left edge of the
2135 : : * screen may cause FIFO underflow and display corruption.
2136 : : */
2137 : : if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
2138 : : (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) {
2139 : : DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
2140 : : crtc_x + crtc_w < 4 ? "end" : "start",
2141 : : crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x,
2142 : : 4, pipe_src_w - 4);
2143 : : return -ERANGE;
2144 : : }
2145 : :
2146 : : return 0;
2147 : : }
2148 : :
2149 : 0 : static int skl_plane_check_nv12_rotation(const struct intel_plane_state *plane_state)
2150 : : {
2151 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
2152 : 0 : unsigned int rotation = plane_state->hw.rotation;
2153 : 0 : int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
2154 : :
2155 : : /* Display WA #1106 */
2156 [ # # ]: 0 : if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2157 [ # # ]: 0 : src_w & 3 &&
2158 : 0 : (rotation == DRM_MODE_ROTATE_270 ||
2159 [ # # ]: 0 : rotation == (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_90))) {
2160 : 0 : DRM_DEBUG_KMS("src width must be multiple of 4 for rotated planar YUV\n");
2161 : 0 : return -EINVAL;
2162 : : }
2163 : :
2164 : : return 0;
2165 : : }
2166 : :
2167 : : static int skl_plane_max_scale(struct drm_i915_private *dev_priv,
2168 : : const struct drm_framebuffer *fb)
2169 : : {
2170 : : /*
2171 : : * We don't yet know the final source width nor
2172 : : * whether we can use the HQ scaler mode. Assume
2173 : : * the best case.
2174 : : * FIXME need to properly check this later.
2175 : : */
2176 : : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv) ||
2177 : : !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
2178 : : return 0x30000 - 1;
2179 : : else
2180 : : return 0x20000 - 1;
2181 : : }
2182 : :
2183 : 0 : static int skl_plane_check(struct intel_crtc_state *crtc_state,
2184 : : struct intel_plane_state *plane_state)
2185 : : {
2186 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2187 : 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2188 : 0 : const struct drm_framebuffer *fb = plane_state->hw.fb;
2189 : 0 : int min_scale = DRM_PLANE_HELPER_NO_SCALING;
2190 : 0 : int max_scale = DRM_PLANE_HELPER_NO_SCALING;
2191 : 0 : int ret;
2192 : :
2193 : 0 : ret = skl_plane_check_fb(crtc_state, plane_state);
2194 [ # # ]: 0 : if (ret)
2195 : : return ret;
2196 : :
2197 : : /* use scaler when colorkey is not required */
2198 [ # # # # ]: 0 : if (!plane_state->ckey.flags && intel_fb_scalable(fb)) {
2199 : 0 : min_scale = 1;
2200 : 0 : max_scale = skl_plane_max_scale(dev_priv, fb);
2201 : : }
2202 : :
2203 : 0 : ret = drm_atomic_helper_check_plane_state(&plane_state->uapi,
2204 : 0 : &crtc_state->uapi,
2205 : : min_scale, max_scale,
2206 : : true, true);
2207 [ # # ]: 0 : if (ret)
2208 : : return ret;
2209 : :
2210 : 0 : ret = skl_check_plane_surface(plane_state);
2211 [ # # ]: 0 : if (ret)
2212 : : return ret;
2213 : :
2214 [ # # ]: 0 : if (!plane_state->uapi.visible)
2215 : : return 0;
2216 : :
2217 : 0 : ret = skl_plane_check_dst_coordinates(crtc_state, plane_state);
2218 [ # # ]: 0 : if (ret)
2219 : : return ret;
2220 : :
2221 : 0 : ret = intel_plane_check_src_coordinates(plane_state);
2222 [ # # ]: 0 : if (ret)
2223 : : return ret;
2224 : :
2225 : 0 : ret = skl_plane_check_nv12_rotation(plane_state);
2226 [ # # ]: 0 : if (ret)
2227 : : return ret;
2228 : :
2229 : : /* HW only has 8 bits pixel precision, disable plane if invisible */
2230 [ # # ]: 0 : if (!(plane_state->hw.alpha >> 8))
2231 : 0 : plane_state->uapi.visible = false;
2232 : :
2233 : 0 : plane_state->ctl = skl_plane_ctl(crtc_state, plane_state);
2234 : :
2235 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
2236 : 0 : plane_state->color_ctl = glk_plane_color_ctl(crtc_state,
2237 : : plane_state);
2238 : :
2239 [ # # # # ]: 0 : if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
2240 [ # # ]: 0 : icl_is_hdr_plane(dev_priv, plane->id))
2241 : : /* Enable and use MPEG-2 chroma siting */
2242 : 0 : plane_state->cus_ctl = PLANE_CUS_ENABLE |
2243 : : PLANE_CUS_HPHASE_0 |
2244 : : PLANE_CUS_VPHASE_SIGN_NEGATIVE | PLANE_CUS_VPHASE_0_25;
2245 : : else
2246 : 0 : plane_state->cus_ctl = 0;
2247 : :
2248 : : return 0;
2249 : : }
2250 : :
2251 : 0 : static bool has_dst_key_in_primary_plane(struct drm_i915_private *dev_priv)
2252 : : {
2253 : 0 : return INTEL_GEN(dev_priv) >= 9;
2254 : : }
2255 : :
2256 : 0 : static void intel_plane_set_ckey(struct intel_plane_state *plane_state,
2257 : : const struct drm_intel_sprite_colorkey *set)
2258 : : {
2259 : 0 : struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
2260 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
2261 : 0 : struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
2262 : :
2263 : 0 : *key = *set;
2264 : :
2265 : : /*
2266 : : * We want src key enabled on the
2267 : : * sprite and not on the primary.
2268 : : */
2269 [ # # ]: 0 : if (plane->id == PLANE_PRIMARY &&
2270 [ # # ]: 0 : set->flags & I915_SET_COLORKEY_SOURCE)
2271 : 0 : key->flags = 0;
2272 : :
2273 : : /*
2274 : : * On SKL+ we want dst key enabled on
2275 : : * the primary and not on the sprite.
2276 : : */
2277 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 9 && plane->id != PLANE_PRIMARY &&
2278 [ # # ]: 0 : set->flags & I915_SET_COLORKEY_DESTINATION)
2279 : 0 : key->flags = 0;
2280 : 0 : }
2281 : :
2282 : 0 : int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
2283 : : struct drm_file *file_priv)
2284 : : {
2285 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
2286 : 0 : struct drm_intel_sprite_colorkey *set = data;
2287 : 0 : struct drm_plane *plane;
2288 : 0 : struct drm_plane_state *plane_state;
2289 : 0 : struct drm_atomic_state *state;
2290 : 0 : struct drm_modeset_acquire_ctx ctx;
2291 : 0 : int ret = 0;
2292 : :
2293 : : /* ignore the pointless "none" flag */
2294 : 0 : set->flags &= ~I915_SET_COLORKEY_NONE;
2295 : :
2296 [ # # ]: 0 : if (set->flags & ~(I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2297 : : return -EINVAL;
2298 : :
2299 : : /* Make sure we don't try to enable both src & dest simultaneously */
2300 [ # # ]: 0 : if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
2301 : : return -EINVAL;
2302 : :
2303 [ # # # # ]: 0 : if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
2304 [ # # ]: 0 : set->flags & I915_SET_COLORKEY_DESTINATION)
2305 : : return -EINVAL;
2306 : :
2307 : 0 : plane = drm_plane_find(dev, file_priv, set->plane_id);
2308 [ # # # # ]: 0 : if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
2309 : : return -ENOENT;
2310 : :
2311 : : /*
2312 : : * SKL+ only plane 2 can do destination keying against plane 1.
2313 : : * Also multiple planes can't do destination keying on the same
2314 : : * pipe simultaneously.
2315 : : */
2316 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 9 &&
2317 [ # # ]: 0 : to_intel_plane(plane)->id >= PLANE_SPRITE1 &&
2318 [ # # ]: 0 : set->flags & I915_SET_COLORKEY_DESTINATION)
2319 : : return -EINVAL;
2320 : :
2321 : 0 : drm_modeset_acquire_init(&ctx, 0);
2322 : :
2323 : 0 : state = drm_atomic_state_alloc(plane->dev);
2324 [ # # ]: 0 : if (!state) {
2325 : 0 : ret = -ENOMEM;
2326 : 0 : goto out;
2327 : : }
2328 : 0 : state->acquire_ctx = &ctx;
2329 : :
2330 : 0 : while (1) {
2331 : 0 : plane_state = drm_atomic_get_plane_state(state, plane);
2332 [ # # ]: 0 : ret = PTR_ERR_OR_ZERO(plane_state);
2333 [ # # ]: 0 : if (!ret)
2334 : 0 : intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2335 : :
2336 : : /*
2337 : : * On some platforms we have to configure
2338 : : * the dst colorkey on the primary plane.
2339 : : */
2340 [ # # # # ]: 0 : if (!ret && has_dst_key_in_primary_plane(dev_priv)) {
2341 : 0 : struct intel_crtc *crtc =
2342 : 0 : intel_get_crtc_for_pipe(dev_priv,
2343 : 0 : to_intel_plane(plane)->pipe);
2344 : :
2345 : 0 : plane_state = drm_atomic_get_plane_state(state,
2346 : : crtc->base.primary);
2347 [ # # ]: 0 : ret = PTR_ERR_OR_ZERO(plane_state);
2348 [ # # ]: 0 : if (!ret)
2349 : 0 : intel_plane_set_ckey(to_intel_plane_state(plane_state), set);
2350 : : }
2351 : :
2352 [ # # ]: 0 : if (!ret)
2353 : 0 : ret = drm_atomic_commit(state);
2354 : :
2355 [ # # ]: 0 : if (ret != -EDEADLK)
2356 : : break;
2357 : :
2358 : 0 : drm_atomic_state_clear(state);
2359 : 0 : drm_modeset_backoff(&ctx);
2360 : : }
2361 : :
2362 : 0 : drm_atomic_state_put(state);
2363 : 0 : out:
2364 : 0 : drm_modeset_drop_locks(&ctx);
2365 : 0 : drm_modeset_acquire_fini(&ctx);
2366 : 0 : return ret;
2367 : : }
2368 : :
2369 : : static const u32 g4x_plane_formats[] = {
2370 : : DRM_FORMAT_XRGB8888,
2371 : : DRM_FORMAT_YUYV,
2372 : : DRM_FORMAT_YVYU,
2373 : : DRM_FORMAT_UYVY,
2374 : : DRM_FORMAT_VYUY,
2375 : : };
2376 : :
2377 : : static const u64 i9xx_plane_format_modifiers[] = {
2378 : : I915_FORMAT_MOD_X_TILED,
2379 : : DRM_FORMAT_MOD_LINEAR,
2380 : : DRM_FORMAT_MOD_INVALID
2381 : : };
2382 : :
2383 : : static const u32 snb_plane_formats[] = {
2384 : : DRM_FORMAT_XRGB8888,
2385 : : DRM_FORMAT_XBGR8888,
2386 : : DRM_FORMAT_XRGB2101010,
2387 : : DRM_FORMAT_XBGR2101010,
2388 : : DRM_FORMAT_XRGB16161616F,
2389 : : DRM_FORMAT_XBGR16161616F,
2390 : : DRM_FORMAT_YUYV,
2391 : : DRM_FORMAT_YVYU,
2392 : : DRM_FORMAT_UYVY,
2393 : : DRM_FORMAT_VYUY,
2394 : : };
2395 : :
2396 : : static const u32 vlv_plane_formats[] = {
2397 : : DRM_FORMAT_C8,
2398 : : DRM_FORMAT_RGB565,
2399 : : DRM_FORMAT_XRGB8888,
2400 : : DRM_FORMAT_XBGR8888,
2401 : : DRM_FORMAT_ARGB8888,
2402 : : DRM_FORMAT_ABGR8888,
2403 : : DRM_FORMAT_XBGR2101010,
2404 : : DRM_FORMAT_ABGR2101010,
2405 : : DRM_FORMAT_YUYV,
2406 : : DRM_FORMAT_YVYU,
2407 : : DRM_FORMAT_UYVY,
2408 : : DRM_FORMAT_VYUY,
2409 : : };
2410 : :
2411 : : static const u32 chv_pipe_b_sprite_formats[] = {
2412 : : DRM_FORMAT_C8,
2413 : : DRM_FORMAT_RGB565,
2414 : : DRM_FORMAT_XRGB8888,
2415 : : DRM_FORMAT_XBGR8888,
2416 : : DRM_FORMAT_ARGB8888,
2417 : : DRM_FORMAT_ABGR8888,
2418 : : DRM_FORMAT_XRGB2101010,
2419 : : DRM_FORMAT_XBGR2101010,
2420 : : DRM_FORMAT_ARGB2101010,
2421 : : DRM_FORMAT_ABGR2101010,
2422 : : DRM_FORMAT_YUYV,
2423 : : DRM_FORMAT_YVYU,
2424 : : DRM_FORMAT_UYVY,
2425 : : DRM_FORMAT_VYUY,
2426 : : };
2427 : :
2428 : : static const u32 skl_plane_formats[] = {
2429 : : DRM_FORMAT_C8,
2430 : : DRM_FORMAT_RGB565,
2431 : : DRM_FORMAT_XRGB8888,
2432 : : DRM_FORMAT_XBGR8888,
2433 : : DRM_FORMAT_ARGB8888,
2434 : : DRM_FORMAT_ABGR8888,
2435 : : DRM_FORMAT_XRGB2101010,
2436 : : DRM_FORMAT_XBGR2101010,
2437 : : DRM_FORMAT_XRGB16161616F,
2438 : : DRM_FORMAT_XBGR16161616F,
2439 : : DRM_FORMAT_YUYV,
2440 : : DRM_FORMAT_YVYU,
2441 : : DRM_FORMAT_UYVY,
2442 : : DRM_FORMAT_VYUY,
2443 : : };
2444 : :
2445 : : static const u32 skl_planar_formats[] = {
2446 : : DRM_FORMAT_C8,
2447 : : DRM_FORMAT_RGB565,
2448 : : DRM_FORMAT_XRGB8888,
2449 : : DRM_FORMAT_XBGR8888,
2450 : : DRM_FORMAT_ARGB8888,
2451 : : DRM_FORMAT_ABGR8888,
2452 : : DRM_FORMAT_XRGB2101010,
2453 : : DRM_FORMAT_XBGR2101010,
2454 : : DRM_FORMAT_XRGB16161616F,
2455 : : DRM_FORMAT_XBGR16161616F,
2456 : : DRM_FORMAT_YUYV,
2457 : : DRM_FORMAT_YVYU,
2458 : : DRM_FORMAT_UYVY,
2459 : : DRM_FORMAT_VYUY,
2460 : : DRM_FORMAT_NV12,
2461 : : };
2462 : :
2463 : : static const u32 glk_planar_formats[] = {
2464 : : DRM_FORMAT_C8,
2465 : : DRM_FORMAT_RGB565,
2466 : : DRM_FORMAT_XRGB8888,
2467 : : DRM_FORMAT_XBGR8888,
2468 : : DRM_FORMAT_ARGB8888,
2469 : : DRM_FORMAT_ABGR8888,
2470 : : DRM_FORMAT_XRGB2101010,
2471 : : DRM_FORMAT_XBGR2101010,
2472 : : DRM_FORMAT_XRGB16161616F,
2473 : : DRM_FORMAT_XBGR16161616F,
2474 : : DRM_FORMAT_YUYV,
2475 : : DRM_FORMAT_YVYU,
2476 : : DRM_FORMAT_UYVY,
2477 : : DRM_FORMAT_VYUY,
2478 : : DRM_FORMAT_NV12,
2479 : : DRM_FORMAT_P010,
2480 : : DRM_FORMAT_P012,
2481 : : DRM_FORMAT_P016,
2482 : : };
2483 : :
2484 : : static const u32 icl_sdr_y_plane_formats[] = {
2485 : : DRM_FORMAT_C8,
2486 : : DRM_FORMAT_RGB565,
2487 : : DRM_FORMAT_XRGB8888,
2488 : : DRM_FORMAT_XBGR8888,
2489 : : DRM_FORMAT_ARGB8888,
2490 : : DRM_FORMAT_ABGR8888,
2491 : : DRM_FORMAT_XRGB2101010,
2492 : : DRM_FORMAT_XBGR2101010,
2493 : : DRM_FORMAT_ARGB2101010,
2494 : : DRM_FORMAT_ABGR2101010,
2495 : : DRM_FORMAT_YUYV,
2496 : : DRM_FORMAT_YVYU,
2497 : : DRM_FORMAT_UYVY,
2498 : : DRM_FORMAT_VYUY,
2499 : : DRM_FORMAT_Y210,
2500 : : DRM_FORMAT_Y212,
2501 : : DRM_FORMAT_Y216,
2502 : : DRM_FORMAT_XVYU2101010,
2503 : : DRM_FORMAT_XVYU12_16161616,
2504 : : DRM_FORMAT_XVYU16161616,
2505 : : };
2506 : :
2507 : : static const u32 icl_sdr_uv_plane_formats[] = {
2508 : : DRM_FORMAT_C8,
2509 : : DRM_FORMAT_RGB565,
2510 : : DRM_FORMAT_XRGB8888,
2511 : : DRM_FORMAT_XBGR8888,
2512 : : DRM_FORMAT_ARGB8888,
2513 : : DRM_FORMAT_ABGR8888,
2514 : : DRM_FORMAT_XRGB2101010,
2515 : : DRM_FORMAT_XBGR2101010,
2516 : : DRM_FORMAT_ARGB2101010,
2517 : : DRM_FORMAT_ABGR2101010,
2518 : : DRM_FORMAT_YUYV,
2519 : : DRM_FORMAT_YVYU,
2520 : : DRM_FORMAT_UYVY,
2521 : : DRM_FORMAT_VYUY,
2522 : : DRM_FORMAT_NV12,
2523 : : DRM_FORMAT_P010,
2524 : : DRM_FORMAT_P012,
2525 : : DRM_FORMAT_P016,
2526 : : DRM_FORMAT_Y210,
2527 : : DRM_FORMAT_Y212,
2528 : : DRM_FORMAT_Y216,
2529 : : DRM_FORMAT_XVYU2101010,
2530 : : DRM_FORMAT_XVYU12_16161616,
2531 : : DRM_FORMAT_XVYU16161616,
2532 : : };
2533 : :
2534 : : static const u32 icl_hdr_plane_formats[] = {
2535 : : DRM_FORMAT_C8,
2536 : : DRM_FORMAT_RGB565,
2537 : : DRM_FORMAT_XRGB8888,
2538 : : DRM_FORMAT_XBGR8888,
2539 : : DRM_FORMAT_ARGB8888,
2540 : : DRM_FORMAT_ABGR8888,
2541 : : DRM_FORMAT_XRGB2101010,
2542 : : DRM_FORMAT_XBGR2101010,
2543 : : DRM_FORMAT_ARGB2101010,
2544 : : DRM_FORMAT_ABGR2101010,
2545 : : DRM_FORMAT_XRGB16161616F,
2546 : : DRM_FORMAT_XBGR16161616F,
2547 : : DRM_FORMAT_ARGB16161616F,
2548 : : DRM_FORMAT_ABGR16161616F,
2549 : : DRM_FORMAT_YUYV,
2550 : : DRM_FORMAT_YVYU,
2551 : : DRM_FORMAT_UYVY,
2552 : : DRM_FORMAT_VYUY,
2553 : : DRM_FORMAT_NV12,
2554 : : DRM_FORMAT_P010,
2555 : : DRM_FORMAT_P012,
2556 : : DRM_FORMAT_P016,
2557 : : DRM_FORMAT_Y210,
2558 : : DRM_FORMAT_Y212,
2559 : : DRM_FORMAT_Y216,
2560 : : DRM_FORMAT_XVYU2101010,
2561 : : DRM_FORMAT_XVYU12_16161616,
2562 : : DRM_FORMAT_XVYU16161616,
2563 : : };
2564 : :
2565 : : static const u64 skl_plane_format_modifiers_noccs[] = {
2566 : : I915_FORMAT_MOD_Yf_TILED,
2567 : : I915_FORMAT_MOD_Y_TILED,
2568 : : I915_FORMAT_MOD_X_TILED,
2569 : : DRM_FORMAT_MOD_LINEAR,
2570 : : DRM_FORMAT_MOD_INVALID
2571 : : };
2572 : :
2573 : : static const u64 skl_plane_format_modifiers_ccs[] = {
2574 : : I915_FORMAT_MOD_Yf_TILED_CCS,
2575 : : I915_FORMAT_MOD_Y_TILED_CCS,
2576 : : I915_FORMAT_MOD_Yf_TILED,
2577 : : I915_FORMAT_MOD_Y_TILED,
2578 : : I915_FORMAT_MOD_X_TILED,
2579 : : DRM_FORMAT_MOD_LINEAR,
2580 : : DRM_FORMAT_MOD_INVALID
2581 : : };
2582 : :
2583 : : static const u64 gen12_plane_format_modifiers_mc_ccs[] = {
2584 : : I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS,
2585 : : I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2586 : : I915_FORMAT_MOD_Y_TILED,
2587 : : I915_FORMAT_MOD_X_TILED,
2588 : : DRM_FORMAT_MOD_LINEAR,
2589 : : DRM_FORMAT_MOD_INVALID
2590 : : };
2591 : :
2592 : : static const u64 gen12_plane_format_modifiers_rc_ccs[] = {
2593 : : I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS,
2594 : : I915_FORMAT_MOD_Y_TILED,
2595 : : I915_FORMAT_MOD_X_TILED,
2596 : : DRM_FORMAT_MOD_LINEAR,
2597 : : DRM_FORMAT_MOD_INVALID
2598 : : };
2599 : :
2600 : 0 : static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
2601 : : u32 format, u64 modifier)
2602 : : {
2603 [ # # ]: 0 : switch (modifier) {
2604 : : case DRM_FORMAT_MOD_LINEAR:
2605 : : case I915_FORMAT_MOD_X_TILED:
2606 : 0 : break;
2607 : : default:
2608 : : return false;
2609 : : }
2610 : :
2611 [ # # ]: 0 : switch (format) {
2612 : 0 : case DRM_FORMAT_XRGB8888:
2613 : : case DRM_FORMAT_YUYV:
2614 : : case DRM_FORMAT_YVYU:
2615 : : case DRM_FORMAT_UYVY:
2616 : : case DRM_FORMAT_VYUY:
2617 : 0 : if (modifier == DRM_FORMAT_MOD_LINEAR ||
2618 [ # # ]: 0 : modifier == I915_FORMAT_MOD_X_TILED)
2619 : 0 : return true;
2620 : : /* fall through */
2621 : : default:
2622 : : return false;
2623 : : }
2624 : : }
2625 : :
2626 : 0 : static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
2627 : : u32 format, u64 modifier)
2628 : : {
2629 [ # # ]: 0 : switch (modifier) {
2630 : : case DRM_FORMAT_MOD_LINEAR:
2631 : : case I915_FORMAT_MOD_X_TILED:
2632 : 0 : break;
2633 : : default:
2634 : : return false;
2635 : : }
2636 : :
2637 [ # # ]: 0 : switch (format) {
2638 : 0 : case DRM_FORMAT_XRGB8888:
2639 : : case DRM_FORMAT_XBGR8888:
2640 : : case DRM_FORMAT_XRGB2101010:
2641 : : case DRM_FORMAT_XBGR2101010:
2642 : : case DRM_FORMAT_XRGB16161616F:
2643 : : case DRM_FORMAT_XBGR16161616F:
2644 : : case DRM_FORMAT_YUYV:
2645 : : case DRM_FORMAT_YVYU:
2646 : : case DRM_FORMAT_UYVY:
2647 : : case DRM_FORMAT_VYUY:
2648 : 0 : if (modifier == DRM_FORMAT_MOD_LINEAR ||
2649 [ # # ]: 0 : modifier == I915_FORMAT_MOD_X_TILED)
2650 : 0 : return true;
2651 : : /* fall through */
2652 : : default:
2653 : : return false;
2654 : : }
2655 : : }
2656 : :
2657 : 0 : static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
2658 : : u32 format, u64 modifier)
2659 : : {
2660 [ # # ]: 0 : switch (modifier) {
2661 : : case DRM_FORMAT_MOD_LINEAR:
2662 : : case I915_FORMAT_MOD_X_TILED:
2663 : 0 : break;
2664 : : default:
2665 : : return false;
2666 : : }
2667 : :
2668 [ # # ]: 0 : switch (format) {
2669 : 0 : case DRM_FORMAT_C8:
2670 : : case DRM_FORMAT_RGB565:
2671 : : case DRM_FORMAT_ABGR8888:
2672 : : case DRM_FORMAT_ARGB8888:
2673 : : case DRM_FORMAT_XBGR8888:
2674 : : case DRM_FORMAT_XRGB8888:
2675 : : case DRM_FORMAT_XBGR2101010:
2676 : : case DRM_FORMAT_ABGR2101010:
2677 : : case DRM_FORMAT_XRGB2101010:
2678 : : case DRM_FORMAT_ARGB2101010:
2679 : : case DRM_FORMAT_YUYV:
2680 : : case DRM_FORMAT_YVYU:
2681 : : case DRM_FORMAT_UYVY:
2682 : : case DRM_FORMAT_VYUY:
2683 : 0 : if (modifier == DRM_FORMAT_MOD_LINEAR ||
2684 [ # # ]: 0 : modifier == I915_FORMAT_MOD_X_TILED)
2685 : 0 : return true;
2686 : : /* fall through */
2687 : : default:
2688 : : return false;
2689 : : }
2690 : : }
2691 : :
2692 : 0 : static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
2693 : : u32 format, u64 modifier)
2694 : : {
2695 : 0 : struct intel_plane *plane = to_intel_plane(_plane);
2696 : :
2697 [ # # # ]: 0 : switch (modifier) {
2698 : : case DRM_FORMAT_MOD_LINEAR:
2699 : : case I915_FORMAT_MOD_X_TILED:
2700 : : case I915_FORMAT_MOD_Y_TILED:
2701 : : case I915_FORMAT_MOD_Yf_TILED:
2702 : : break;
2703 : 0 : case I915_FORMAT_MOD_Y_TILED_CCS:
2704 : : case I915_FORMAT_MOD_Yf_TILED_CCS:
2705 [ # # ]: 0 : if (!plane->has_ccs)
2706 : : return false;
2707 : : break;
2708 : : default:
2709 : : return false;
2710 : : }
2711 : :
2712 [ # # # # ]: 0 : switch (format) {
2713 : 0 : case DRM_FORMAT_XRGB8888:
2714 : : case DRM_FORMAT_XBGR8888:
2715 : : case DRM_FORMAT_ARGB8888:
2716 : : case DRM_FORMAT_ABGR8888:
2717 [ # # ]: 0 : if (is_ccs_modifier(modifier))
2718 : : return true;
2719 : : /* fall through */
2720 : : case DRM_FORMAT_RGB565:
2721 : : case DRM_FORMAT_XRGB2101010:
2722 : : case DRM_FORMAT_XBGR2101010:
2723 : : case DRM_FORMAT_ARGB2101010:
2724 : : case DRM_FORMAT_ABGR2101010:
2725 : : case DRM_FORMAT_YUYV:
2726 : : case DRM_FORMAT_YVYU:
2727 : : case DRM_FORMAT_UYVY:
2728 : : case DRM_FORMAT_VYUY:
2729 : : case DRM_FORMAT_NV12:
2730 : : case DRM_FORMAT_P010:
2731 : : case DRM_FORMAT_P012:
2732 : : case DRM_FORMAT_P016:
2733 : : case DRM_FORMAT_XVYU2101010:
2734 [ # # ]: 0 : if (modifier == I915_FORMAT_MOD_Yf_TILED)
2735 : : return true;
2736 : : /* fall through */
2737 : : case DRM_FORMAT_C8:
2738 : : case DRM_FORMAT_XBGR16161616F:
2739 : : case DRM_FORMAT_ABGR16161616F:
2740 : : case DRM_FORMAT_XRGB16161616F:
2741 : : case DRM_FORMAT_ARGB16161616F:
2742 : : case DRM_FORMAT_Y210:
2743 : : case DRM_FORMAT_Y212:
2744 : : case DRM_FORMAT_Y216:
2745 : : case DRM_FORMAT_XVYU12_16161616:
2746 : : case DRM_FORMAT_XVYU16161616:
2747 : 0 : if (modifier == DRM_FORMAT_MOD_LINEAR ||
2748 [ # # # # ]: 0 : modifier == I915_FORMAT_MOD_X_TILED ||
2749 : : modifier == I915_FORMAT_MOD_Y_TILED)
2750 : 0 : return true;
2751 : : /* fall through */
2752 : : default:
2753 : : return false;
2754 : : }
2755 : : }
2756 : :
2757 : 0 : static bool gen12_plane_supports_mc_ccs(enum plane_id plane_id)
2758 : : {
2759 : 0 : return plane_id < PLANE_SPRITE4;
2760 : : }
2761 : :
2762 : 0 : static bool gen12_plane_format_mod_supported(struct drm_plane *_plane,
2763 : : u32 format, u64 modifier)
2764 : : {
2765 : 0 : struct intel_plane *plane = to_intel_plane(_plane);
2766 : :
2767 [ # # # ]: 0 : switch (modifier) {
2768 : 0 : case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
2769 [ # # ]: 0 : if (!gen12_plane_supports_mc_ccs(plane->id))
2770 : : return false;
2771 : : /* fall through */
2772 : : case DRM_FORMAT_MOD_LINEAR:
2773 : : case I915_FORMAT_MOD_X_TILED:
2774 : : case I915_FORMAT_MOD_Y_TILED:
2775 : : case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS:
2776 : 0 : break;
2777 : : default:
2778 : : return false;
2779 : : }
2780 : :
2781 [ # # # # ]: 0 : switch (format) {
2782 : 0 : case DRM_FORMAT_XRGB8888:
2783 : : case DRM_FORMAT_XBGR8888:
2784 : : case DRM_FORMAT_ARGB8888:
2785 : : case DRM_FORMAT_ABGR8888:
2786 [ # # ]: 0 : if (is_ccs_modifier(modifier))
2787 : : return true;
2788 : : /* fall through */
2789 : : case DRM_FORMAT_YUYV:
2790 : : case DRM_FORMAT_YVYU:
2791 : : case DRM_FORMAT_UYVY:
2792 : : case DRM_FORMAT_VYUY:
2793 : : case DRM_FORMAT_NV12:
2794 : : case DRM_FORMAT_P010:
2795 : : case DRM_FORMAT_P012:
2796 : : case DRM_FORMAT_P016:
2797 [ # # ]: 0 : if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS)
2798 : : return true;
2799 : : /* fall through */
2800 : : case DRM_FORMAT_RGB565:
2801 : : case DRM_FORMAT_XRGB2101010:
2802 : : case DRM_FORMAT_XBGR2101010:
2803 : : case DRM_FORMAT_ARGB2101010:
2804 : : case DRM_FORMAT_ABGR2101010:
2805 : : case DRM_FORMAT_XVYU2101010:
2806 : : case DRM_FORMAT_C8:
2807 : : case DRM_FORMAT_XBGR16161616F:
2808 : : case DRM_FORMAT_ABGR16161616F:
2809 : : case DRM_FORMAT_XRGB16161616F:
2810 : : case DRM_FORMAT_ARGB16161616F:
2811 : : case DRM_FORMAT_Y210:
2812 : : case DRM_FORMAT_Y212:
2813 : : case DRM_FORMAT_Y216:
2814 : : case DRM_FORMAT_XVYU12_16161616:
2815 : : case DRM_FORMAT_XVYU16161616:
2816 : 0 : if (modifier == DRM_FORMAT_MOD_LINEAR ||
2817 [ # # # # ]: 0 : modifier == I915_FORMAT_MOD_X_TILED ||
2818 : : modifier == I915_FORMAT_MOD_Y_TILED)
2819 : 0 : return true;
2820 : : /* fall through */
2821 : : default:
2822 : : return false;
2823 : : }
2824 : : }
2825 : :
2826 : : static const struct drm_plane_funcs g4x_sprite_funcs = {
2827 : : .update_plane = drm_atomic_helper_update_plane,
2828 : : .disable_plane = drm_atomic_helper_disable_plane,
2829 : : .destroy = intel_plane_destroy,
2830 : : .atomic_duplicate_state = intel_plane_duplicate_state,
2831 : : .atomic_destroy_state = intel_plane_destroy_state,
2832 : : .format_mod_supported = g4x_sprite_format_mod_supported,
2833 : : };
2834 : :
2835 : : static const struct drm_plane_funcs snb_sprite_funcs = {
2836 : : .update_plane = drm_atomic_helper_update_plane,
2837 : : .disable_plane = drm_atomic_helper_disable_plane,
2838 : : .destroy = intel_plane_destroy,
2839 : : .atomic_duplicate_state = intel_plane_duplicate_state,
2840 : : .atomic_destroy_state = intel_plane_destroy_state,
2841 : : .format_mod_supported = snb_sprite_format_mod_supported,
2842 : : };
2843 : :
2844 : : static const struct drm_plane_funcs vlv_sprite_funcs = {
2845 : : .update_plane = drm_atomic_helper_update_plane,
2846 : : .disable_plane = drm_atomic_helper_disable_plane,
2847 : : .destroy = intel_plane_destroy,
2848 : : .atomic_duplicate_state = intel_plane_duplicate_state,
2849 : : .atomic_destroy_state = intel_plane_destroy_state,
2850 : : .format_mod_supported = vlv_sprite_format_mod_supported,
2851 : : };
2852 : :
2853 : : static const struct drm_plane_funcs skl_plane_funcs = {
2854 : : .update_plane = drm_atomic_helper_update_plane,
2855 : : .disable_plane = drm_atomic_helper_disable_plane,
2856 : : .destroy = intel_plane_destroy,
2857 : : .atomic_duplicate_state = intel_plane_duplicate_state,
2858 : : .atomic_destroy_state = intel_plane_destroy_state,
2859 : : .format_mod_supported = skl_plane_format_mod_supported,
2860 : : };
2861 : :
2862 : : static const struct drm_plane_funcs gen12_plane_funcs = {
2863 : : .update_plane = drm_atomic_helper_update_plane,
2864 : : .disable_plane = drm_atomic_helper_disable_plane,
2865 : : .destroy = intel_plane_destroy,
2866 : : .atomic_duplicate_state = intel_plane_duplicate_state,
2867 : : .atomic_destroy_state = intel_plane_destroy_state,
2868 : : .format_mod_supported = gen12_plane_format_mod_supported,
2869 : : };
2870 : :
2871 : 0 : static bool skl_plane_has_fbc(struct drm_i915_private *dev_priv,
2872 : : enum pipe pipe, enum plane_id plane_id)
2873 : : {
2874 : 0 : if (!HAS_FBC(dev_priv))
2875 : : return false;
2876 : :
2877 : 0 : return pipe == PIPE_A && plane_id == PLANE_PRIMARY;
2878 : : }
2879 : :
2880 : 0 : static bool skl_plane_has_planar(struct drm_i915_private *dev_priv,
2881 : : enum pipe pipe, enum plane_id plane_id)
2882 : : {
2883 : : /* Display WA #0870: skl, bxt */
2884 [ # # # # ]: 0 : if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv))
2885 : : return false;
2886 : :
2887 [ # # # # : 0 : if (IS_GEN(dev_priv, 9) && !IS_GEMINILAKE(dev_priv) && pipe == PIPE_C)
# # # # #
# ]
2888 : : return false;
2889 : :
2890 [ # # # # ]: 0 : if (plane_id != PLANE_PRIMARY && plane_id != PLANE_SPRITE0)
2891 : : return false;
2892 : :
2893 : : return true;
2894 : : }
2895 : :
2896 : 0 : static const u32 *skl_get_plane_formats(struct drm_i915_private *dev_priv,
2897 : : enum pipe pipe, enum plane_id plane_id,
2898 : : int *num_formats)
2899 : : {
2900 : 0 : if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2901 : : *num_formats = ARRAY_SIZE(skl_planar_formats);
2902 : : return skl_planar_formats;
2903 : : } else {
2904 : 0 : *num_formats = ARRAY_SIZE(skl_plane_formats);
2905 : 0 : return skl_plane_formats;
2906 : : }
2907 : : }
2908 : :
2909 : 0 : static const u32 *glk_get_plane_formats(struct drm_i915_private *dev_priv,
2910 : : enum pipe pipe, enum plane_id plane_id,
2911 : : int *num_formats)
2912 : : {
2913 : 0 : if (skl_plane_has_planar(dev_priv, pipe, plane_id)) {
2914 : : *num_formats = ARRAY_SIZE(glk_planar_formats);
2915 : : return glk_planar_formats;
2916 : : } else {
2917 : 0 : *num_formats = ARRAY_SIZE(skl_plane_formats);
2918 : 0 : return skl_plane_formats;
2919 : : }
2920 : : }
2921 : :
2922 : 0 : static const u32 *icl_get_plane_formats(struct drm_i915_private *dev_priv,
2923 : : enum pipe pipe, enum plane_id plane_id,
2924 : : int *num_formats)
2925 : : {
2926 : 0 : if (icl_is_hdr_plane(dev_priv, plane_id)) {
2927 : : *num_formats = ARRAY_SIZE(icl_hdr_plane_formats);
2928 : : return icl_hdr_plane_formats;
2929 [ # # ]: 0 : } else if (icl_is_nv12_y_plane(plane_id)) {
2930 : 0 : *num_formats = ARRAY_SIZE(icl_sdr_y_plane_formats);
2931 : 0 : return icl_sdr_y_plane_formats;
2932 : : } else {
2933 : : *num_formats = ARRAY_SIZE(icl_sdr_uv_plane_formats);
2934 : : return icl_sdr_uv_plane_formats;
2935 : : }
2936 : : }
2937 : :
2938 : 0 : static const u64 *gen12_get_plane_modifiers(enum plane_id plane_id)
2939 : : {
2940 : 0 : if (gen12_plane_supports_mc_ccs(plane_id))
2941 : : return gen12_plane_format_modifiers_mc_ccs;
2942 : : else
2943 : 0 : return gen12_plane_format_modifiers_rc_ccs;
2944 : : }
2945 : :
2946 : 0 : static bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
2947 : : enum pipe pipe, enum plane_id plane_id)
2948 : : {
2949 : 0 : if (plane_id == PLANE_CURSOR)
2950 : : return false;
2951 : :
2952 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10)
2953 : : return true;
2954 : :
2955 [ # # ]: 0 : if (IS_GEMINILAKE(dev_priv))
2956 : 0 : return pipe != PIPE_C;
2957 : :
2958 : 0 : return pipe != PIPE_C &&
2959 : 0 : (plane_id == PLANE_PRIMARY ||
2960 : : plane_id == PLANE_SPRITE0);
2961 : : }
2962 : :
2963 : : struct intel_plane *
2964 : 0 : skl_universal_plane_create(struct drm_i915_private *dev_priv,
2965 : : enum pipe pipe, enum plane_id plane_id)
2966 : : {
2967 : 0 : const struct drm_plane_funcs *plane_funcs;
2968 : 0 : struct intel_plane *plane;
2969 : 0 : enum drm_plane_type plane_type;
2970 : 0 : unsigned int supported_rotations;
2971 : 0 : unsigned int possible_crtcs;
2972 : 0 : const u64 *modifiers;
2973 : 0 : const u32 *formats;
2974 : 0 : int num_formats;
2975 : 0 : int ret;
2976 : :
2977 : 0 : plane = intel_plane_alloc();
2978 [ # # ]: 0 : if (IS_ERR(plane))
2979 : : return plane;
2980 : :
2981 : 0 : plane->pipe = pipe;
2982 : 0 : plane->id = plane_id;
2983 : 0 : plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane_id);
2984 : :
2985 [ # # ]: 0 : plane->has_fbc = skl_plane_has_fbc(dev_priv, pipe, plane_id);
2986 [ # # ]: 0 : if (plane->has_fbc) {
2987 : 0 : struct intel_fbc *fbc = &dev_priv->fbc;
2988 : :
2989 : 0 : fbc->possible_framebuffer_bits |= plane->frontbuffer_bit;
2990 : : }
2991 : :
2992 : 0 : plane->max_stride = skl_plane_max_stride;
2993 : 0 : plane->update_plane = skl_update_plane;
2994 : 0 : plane->disable_plane = skl_disable_plane;
2995 : 0 : plane->get_hw_state = skl_plane_get_hw_state;
2996 : 0 : plane->check_plane = skl_plane_check;
2997 : 0 : plane->min_cdclk = skl_plane_min_cdclk;
2998 : :
2999 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 11)
3000 [ # # ]: 0 : formats = icl_get_plane_formats(dev_priv, pipe,
3001 : : plane_id, &num_formats);
3002 [ # # # # ]: 0 : else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
3003 [ # # ]: 0 : formats = glk_get_plane_formats(dev_priv, pipe,
3004 : : plane_id, &num_formats);
3005 : : else
3006 [ # # ]: 0 : formats = skl_get_plane_formats(dev_priv, pipe,
3007 : : plane_id, &num_formats);
3008 : :
3009 [ # # ]: 0 : plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, plane_id);
3010 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 12) {
3011 [ # # ]: 0 : modifiers = gen12_get_plane_modifiers(plane_id);
3012 : : plane_funcs = &gen12_plane_funcs;
3013 : : } else {
3014 [ # # ]: 0 : if (plane->has_ccs)
3015 : : modifiers = skl_plane_format_modifiers_ccs;
3016 : : else
3017 : 0 : modifiers = skl_plane_format_modifiers_noccs;
3018 : : plane_funcs = &skl_plane_funcs;
3019 : : }
3020 : :
3021 [ # # ]: 0 : if (plane_id == PLANE_PRIMARY)
3022 : : plane_type = DRM_PLANE_TYPE_PRIMARY;
3023 : : else
3024 : 0 : plane_type = DRM_PLANE_TYPE_OVERLAY;
3025 : :
3026 : 0 : possible_crtcs = BIT(pipe);
3027 : :
3028 : 0 : ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3029 : : possible_crtcs, plane_funcs,
3030 : : formats, num_formats, modifiers,
3031 : : plane_type,
3032 : : "plane %d%c", plane_id + 1,
3033 : : pipe_name(pipe));
3034 [ # # ]: 0 : if (ret)
3035 : 0 : goto fail;
3036 : :
3037 : 0 : supported_rotations =
3038 : : DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 |
3039 : : DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270;
3040 : :
3041 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 10)
3042 : 0 : supported_rotations |= DRM_MODE_REFLECT_X;
3043 : :
3044 : 0 : drm_plane_create_rotation_property(&plane->base,
3045 : : DRM_MODE_ROTATE_0,
3046 : : supported_rotations);
3047 : :
3048 : 0 : drm_plane_create_color_properties(&plane->base,
3049 : : BIT(DRM_COLOR_YCBCR_BT601) |
3050 : : BIT(DRM_COLOR_YCBCR_BT709),
3051 : : BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3052 : : BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3053 : : DRM_COLOR_YCBCR_BT709,
3054 : : DRM_COLOR_YCBCR_LIMITED_RANGE);
3055 : :
3056 : 0 : drm_plane_create_alpha_property(&plane->base);
3057 : 0 : drm_plane_create_blend_mode_property(&plane->base,
3058 : : BIT(DRM_MODE_BLEND_PIXEL_NONE) |
3059 : : BIT(DRM_MODE_BLEND_PREMULTI) |
3060 : : BIT(DRM_MODE_BLEND_COVERAGE));
3061 : :
3062 : 0 : drm_plane_create_zpos_immutable_property(&plane->base, plane_id);
3063 : :
3064 : 0 : drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3065 : :
3066 : 0 : return plane;
3067 : :
3068 : : fail:
3069 : 0 : intel_plane_free(plane);
3070 : :
3071 : 0 : return ERR_PTR(ret);
3072 : : }
3073 : :
3074 : : struct intel_plane *
3075 : 0 : intel_sprite_plane_create(struct drm_i915_private *dev_priv,
3076 : : enum pipe pipe, int sprite)
3077 : : {
3078 : 0 : struct intel_plane *plane;
3079 : 0 : const struct drm_plane_funcs *plane_funcs;
3080 : 0 : unsigned long possible_crtcs;
3081 : 0 : unsigned int supported_rotations;
3082 : 0 : const u64 *modifiers;
3083 : 0 : const u32 *formats;
3084 : 0 : int num_formats;
3085 : 0 : int ret, zpos;
3086 : :
3087 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 9)
3088 : 0 : return skl_universal_plane_create(dev_priv, pipe,
3089 : 0 : PLANE_SPRITE0 + sprite);
3090 : :
3091 : 0 : plane = intel_plane_alloc();
3092 [ # # ]: 0 : if (IS_ERR(plane))
3093 : : return plane;
3094 : :
3095 [ # # # # ]: 0 : if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
3096 : 0 : plane->max_stride = i9xx_plane_max_stride;
3097 : 0 : plane->update_plane = vlv_update_plane;
3098 : 0 : plane->disable_plane = vlv_disable_plane;
3099 : 0 : plane->get_hw_state = vlv_plane_get_hw_state;
3100 : 0 : plane->check_plane = vlv_sprite_check;
3101 : 0 : plane->min_cdclk = vlv_plane_min_cdclk;
3102 : :
3103 [ # # # # ]: 0 : if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3104 : : formats = chv_pipe_b_sprite_formats;
3105 : : num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
3106 : : } else {
3107 : 0 : formats = vlv_plane_formats;
3108 : 0 : num_formats = ARRAY_SIZE(vlv_plane_formats);
3109 : : }
3110 : : modifiers = i9xx_plane_format_modifiers;
3111 : :
3112 : : plane_funcs = &vlv_sprite_funcs;
3113 [ # # ]: 0 : } else if (INTEL_GEN(dev_priv) >= 7) {
3114 : 0 : plane->max_stride = g4x_sprite_max_stride;
3115 : 0 : plane->update_plane = ivb_update_plane;
3116 : 0 : plane->disable_plane = ivb_disable_plane;
3117 : 0 : plane->get_hw_state = ivb_plane_get_hw_state;
3118 : 0 : plane->check_plane = g4x_sprite_check;
3119 : :
3120 [ # # # # ]: 0 : if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
3121 : 0 : plane->min_cdclk = hsw_plane_min_cdclk;
3122 : : else
3123 : 0 : plane->min_cdclk = ivb_sprite_min_cdclk;
3124 : :
3125 : : formats = snb_plane_formats;
3126 : : num_formats = ARRAY_SIZE(snb_plane_formats);
3127 : : modifiers = i9xx_plane_format_modifiers;
3128 : :
3129 : : plane_funcs = &snb_sprite_funcs;
3130 : : } else {
3131 : 0 : plane->max_stride = g4x_sprite_max_stride;
3132 : 0 : plane->update_plane = g4x_update_plane;
3133 : 0 : plane->disable_plane = g4x_disable_plane;
3134 : 0 : plane->get_hw_state = g4x_plane_get_hw_state;
3135 : 0 : plane->check_plane = g4x_sprite_check;
3136 : 0 : plane->min_cdclk = g4x_sprite_min_cdclk;
3137 : :
3138 : 0 : modifiers = i9xx_plane_format_modifiers;
3139 [ # # ]: 0 : if (IS_GEN(dev_priv, 6)) {
3140 : : formats = snb_plane_formats;
3141 : : num_formats = ARRAY_SIZE(snb_plane_formats);
3142 : :
3143 : : plane_funcs = &snb_sprite_funcs;
3144 : : } else {
3145 : 0 : formats = g4x_plane_formats;
3146 : 0 : num_formats = ARRAY_SIZE(g4x_plane_formats);
3147 : :
3148 : 0 : plane_funcs = &g4x_sprite_funcs;
3149 : : }
3150 : : }
3151 : :
3152 [ # # # # ]: 0 : if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
3153 : : supported_rotations =
3154 : : DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
3155 : : DRM_MODE_REFLECT_X;
3156 : : } else {
3157 : 0 : supported_rotations =
3158 : : DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
3159 : : }
3160 : :
3161 : 0 : plane->pipe = pipe;
3162 : 0 : plane->id = PLANE_SPRITE0 + sprite;
3163 : 0 : plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
3164 : :
3165 : 0 : possible_crtcs = BIT(pipe);
3166 : :
3167 : 0 : ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
3168 : : possible_crtcs, plane_funcs,
3169 : : formats, num_formats, modifiers,
3170 : : DRM_PLANE_TYPE_OVERLAY,
3171 : 0 : "sprite %c", sprite_name(pipe, sprite));
3172 [ # # ]: 0 : if (ret)
3173 : 0 : goto fail;
3174 : :
3175 : 0 : drm_plane_create_rotation_property(&plane->base,
3176 : : DRM_MODE_ROTATE_0,
3177 : : supported_rotations);
3178 : :
3179 : 0 : drm_plane_create_color_properties(&plane->base,
3180 : : BIT(DRM_COLOR_YCBCR_BT601) |
3181 : : BIT(DRM_COLOR_YCBCR_BT709),
3182 : : BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
3183 : : BIT(DRM_COLOR_YCBCR_FULL_RANGE),
3184 : : DRM_COLOR_YCBCR_BT709,
3185 : : DRM_COLOR_YCBCR_LIMITED_RANGE);
3186 : :
3187 : 0 : zpos = sprite + 1;
3188 : 0 : drm_plane_create_zpos_immutable_property(&plane->base, zpos);
3189 : :
3190 : 0 : drm_plane_helper_add(&plane->base, &intel_plane_helper_funcs);
3191 : :
3192 : 0 : return plane;
3193 : :
3194 : : fail:
3195 : 0 : intel_plane_free(plane);
3196 : :
3197 : 0 : return ERR_PTR(ret);
3198 : : }
|