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