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 <linux/string_helpers.h>
34
35#include <drm/drm_atomic_helper.h>
36#include <drm/drm_blend.h>
37#include <drm/drm_color_mgmt.h>
38#include <drm/drm_fourcc.h>
39#include <drm/drm_rect.h>
40
41#include "i915_drv.h"
42#include "i915_reg.h"
43#include "i9xx_plane.h"
44#include "intel_atomic_plane.h"
45#include "intel_de.h"
46#include "intel_display_types.h"
47#include "intel_fb.h"
48#include "intel_sprite.h"
49
50static void i9xx_plane_linear_gamma(u16 gamma[8])
51{
52	/* The points are not evenly spaced. */
53	static const u8 in[8] = { 0, 1, 2, 4, 8, 16, 24, 32 };
54	int i;
55
56	for (i = 0; i < 8; i++)
57		gamma[i] = (in[i] << 8) / 32;
58}
59
60static void
61chv_sprite_update_csc(const struct intel_plane_state *plane_state)
62{
63	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
64	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
65	const struct drm_framebuffer *fb = plane_state->hw.fb;
66	enum plane_id plane_id = plane->id;
67	/*
68	 * |r|   | c0 c1 c2 |   |cr|
69	 * |g| = | c3 c4 c5 | x |y |
70	 * |b|   | c6 c7 c8 |   |cb|
71	 *
72	 * Coefficients are s3.12.
73	 *
74	 * Cb and Cr apparently come in as signed already, and
75	 * we always get full range data in on account of CLRC0/1.
76	 */
77	static const s16 csc_matrix[][9] = {
78		/* BT.601 full range YCbCr -> full range RGB */
79		[DRM_COLOR_YCBCR_BT601] = {
80			 5743, 4096,     0,
81			-2925, 4096, -1410,
82			    0, 4096,  7258,
83		},
84		/* BT.709 full range YCbCr -> full range RGB */
85		[DRM_COLOR_YCBCR_BT709] = {
86			 6450, 4096,     0,
87			-1917, 4096,  -767,
88			    0, 4096,  7601,
89		},
90	};
91	const s16 *csc = csc_matrix[plane_state->hw.color_encoding];
92
93	/* Seems RGB data bypasses the CSC always */
94	if (!fb->format->is_yuv)
95		return;
96
97	intel_de_write_fw(dev_priv, SPCSCYGOFF(plane_id),
98			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
99	intel_de_write_fw(dev_priv, SPCSCCBOFF(plane_id),
100			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
101	intel_de_write_fw(dev_priv, SPCSCCROFF(plane_id),
102			  SPCSC_OOFF(0) | SPCSC_IOFF(0));
103
104	intel_de_write_fw(dev_priv, SPCSCC01(plane_id),
105			  SPCSC_C1(csc[1]) | SPCSC_C0(csc[0]));
106	intel_de_write_fw(dev_priv, SPCSCC23(plane_id),
107			  SPCSC_C1(csc[3]) | SPCSC_C0(csc[2]));
108	intel_de_write_fw(dev_priv, SPCSCC45(plane_id),
109			  SPCSC_C1(csc[5]) | SPCSC_C0(csc[4]));
110	intel_de_write_fw(dev_priv, SPCSCC67(plane_id),
111			  SPCSC_C1(csc[7]) | SPCSC_C0(csc[6]));
112	intel_de_write_fw(dev_priv, SPCSCC8(plane_id), SPCSC_C0(csc[8]));
113
114	intel_de_write_fw(dev_priv, SPCSCYGICLAMP(plane_id),
115			  SPCSC_IMAX(1023) | SPCSC_IMIN(0));
116	intel_de_write_fw(dev_priv, SPCSCCBICLAMP(plane_id),
117			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
118	intel_de_write_fw(dev_priv, SPCSCCRICLAMP(plane_id),
119			  SPCSC_IMAX(512) | SPCSC_IMIN(-512));
120
121	intel_de_write_fw(dev_priv, SPCSCYGOCLAMP(plane_id),
122			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
123	intel_de_write_fw(dev_priv, SPCSCCBOCLAMP(plane_id),
124			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
125	intel_de_write_fw(dev_priv, SPCSCCROCLAMP(plane_id),
126			  SPCSC_OMAX(1023) | SPCSC_OMIN(0));
127}
128
129#define SIN_0 0
130#define COS_0 1
131
132static void
133vlv_sprite_update_clrc(const struct intel_plane_state *plane_state)
134{
135	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
136	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
137	const struct drm_framebuffer *fb = plane_state->hw.fb;
138	enum pipe pipe = plane->pipe;
139	enum plane_id plane_id = plane->id;
140	int contrast, brightness, sh_scale, sh_sin, sh_cos;
141
142	if (fb->format->is_yuv &&
143	    plane_state->hw.color_range == DRM_COLOR_YCBCR_LIMITED_RANGE) {
144		/*
145		 * Expand limited range to full range:
146		 * Contrast is applied first and is used to expand Y range.
147		 * Brightness is applied second and is used to remove the
148		 * offset from Y. Saturation/hue is used to expand CbCr range.
149		 */
150		contrast = DIV_ROUND_CLOSEST(255 << 6, 235 - 16);
151		brightness = -DIV_ROUND_CLOSEST(16 * 255, 235 - 16);
152		sh_scale = DIV_ROUND_CLOSEST(128 << 7, 240 - 128);
153		sh_sin = SIN_0 * sh_scale;
154		sh_cos = COS_0 * sh_scale;
155	} else {
156		/* Pass-through everything. */
157		contrast = 1 << 6;
158		brightness = 0;
159		sh_scale = 1 << 7;
160		sh_sin = SIN_0 * sh_scale;
161		sh_cos = COS_0 * sh_scale;
162	}
163
164	/* FIXME these register are single buffered :( */
165	intel_de_write_fw(dev_priv, SPCLRC0(pipe, plane_id),
166			  SP_CONTRAST(contrast) | SP_BRIGHTNESS(brightness));
167	intel_de_write_fw(dev_priv, SPCLRC1(pipe, plane_id),
168			  SP_SH_SIN(sh_sin) | SP_SH_COS(sh_cos));
169}
170
171static void
172vlv_plane_ratio(const struct intel_crtc_state *crtc_state,
173		const struct intel_plane_state *plane_state,
174		unsigned int *num, unsigned int *den)
175{
176	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
177	const struct drm_framebuffer *fb = plane_state->hw.fb;
178	unsigned int cpp = fb->format->cpp[0];
179
180	/*
181	 * VLV bspec only considers cases where all three planes are
182	 * enabled, and cases where the primary and one sprite is enabled.
183	 * Let's assume the case with just two sprites enabled also
184	 * maps to the latter case.
185	 */
186	if (hweight8(active_planes) == 3) {
187		switch (cpp) {
188		case 8:
189			*num = 11;
190			*den = 8;
191			break;
192		case 4:
193			*num = 18;
194			*den = 16;
195			break;
196		default:
197			*num = 1;
198			*den = 1;
199			break;
200		}
201	} else if (hweight8(active_planes) == 2) {
202		switch (cpp) {
203		case 8:
204			*num = 10;
205			*den = 8;
206			break;
207		case 4:
208			*num = 17;
209			*den = 16;
210			break;
211		default:
212			*num = 1;
213			*den = 1;
214			break;
215		}
216	} else {
217		switch (cpp) {
218		case 8:
219			*num = 10;
220			*den = 8;
221			break;
222		default:
223			*num = 1;
224			*den = 1;
225			break;
226		}
227	}
228}
229
230int vlv_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
231			const struct intel_plane_state *plane_state)
232{
233	unsigned int pixel_rate;
234	unsigned int num, den;
235
236	/*
237	 * Note that crtc_state->pixel_rate accounts for both
238	 * horizontal and vertical panel fitter downscaling factors.
239	 * Pre-HSW bspec tells us to only consider the horizontal
240	 * downscaling factor here. We ignore that and just consider
241	 * both for simplicity.
242	 */
243	pixel_rate = crtc_state->pixel_rate;
244
245	vlv_plane_ratio(crtc_state, plane_state, &num, &den);
246
247	return DIV_ROUND_UP(pixel_rate * num, den);
248}
249
250static u32 vlv_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
251{
252	u32 sprctl = 0;
253
254	if (crtc_state->gamma_enable)
255		sprctl |= SP_PIPE_GAMMA_ENABLE;
256
257	return sprctl;
258}
259
260static u32 vlv_sprite_ctl(const struct intel_crtc_state *crtc_state,
261			  const struct intel_plane_state *plane_state)
262{
263	const struct drm_framebuffer *fb = plane_state->hw.fb;
264	unsigned int rotation = plane_state->hw.rotation;
265	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
266	u32 sprctl;
267
268	sprctl = SP_ENABLE;
269
270	switch (fb->format->format) {
271	case DRM_FORMAT_YUYV:
272		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YUYV;
273		break;
274	case DRM_FORMAT_YVYU:
275		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_YVYU;
276		break;
277	case DRM_FORMAT_UYVY:
278		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_UYVY;
279		break;
280	case DRM_FORMAT_VYUY:
281		sprctl |= SP_FORMAT_YUV422 | SP_YUV_ORDER_VYUY;
282		break;
283	case DRM_FORMAT_C8:
284		sprctl |= SP_FORMAT_8BPP;
285		break;
286	case DRM_FORMAT_RGB565:
287		sprctl |= SP_FORMAT_BGR565;
288		break;
289	case DRM_FORMAT_XRGB8888:
290		sprctl |= SP_FORMAT_BGRX8888;
291		break;
292	case DRM_FORMAT_ARGB8888:
293		sprctl |= SP_FORMAT_BGRA8888;
294		break;
295	case DRM_FORMAT_XBGR2101010:
296		sprctl |= SP_FORMAT_RGBX1010102;
297		break;
298	case DRM_FORMAT_ABGR2101010:
299		sprctl |= SP_FORMAT_RGBA1010102;
300		break;
301	case DRM_FORMAT_XRGB2101010:
302		sprctl |= SP_FORMAT_BGRX1010102;
303		break;
304	case DRM_FORMAT_ARGB2101010:
305		sprctl |= SP_FORMAT_BGRA1010102;
306		break;
307	case DRM_FORMAT_XBGR8888:
308		sprctl |= SP_FORMAT_RGBX8888;
309		break;
310	case DRM_FORMAT_ABGR8888:
311		sprctl |= SP_FORMAT_RGBA8888;
312		break;
313	default:
314		MISSING_CASE(fb->format->format);
315		return 0;
316	}
317
318	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
319		sprctl |= SP_YUV_FORMAT_BT709;
320
321	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
322		sprctl |= SP_TILED;
323
324	if (rotation & DRM_MODE_ROTATE_180)
325		sprctl |= SP_ROTATE_180;
326
327	if (rotation & DRM_MODE_REFLECT_X)
328		sprctl |= SP_MIRROR;
329
330	if (key->flags & I915_SET_COLORKEY_SOURCE)
331		sprctl |= SP_SOURCE_KEY;
332
333	return sprctl;
334}
335
336static void vlv_sprite_update_gamma(const struct intel_plane_state *plane_state)
337{
338	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
339	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
340	const struct drm_framebuffer *fb = plane_state->hw.fb;
341	enum pipe pipe = plane->pipe;
342	enum plane_id plane_id = plane->id;
343	u16 gamma[8];
344	int i;
345
346	/* Seems RGB data bypasses the gamma always */
347	if (!fb->format->is_yuv)
348		return;
349
350	i9xx_plane_linear_gamma(gamma);
351
352	/* FIXME these register are single buffered :( */
353	/* The two end points are implicit (0.0 and 1.0) */
354	for (i = 1; i < 8 - 1; i++)
355		intel_de_write_fw(dev_priv, SPGAMC(pipe, plane_id, i - 1),
356				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
357}
358
359static void
360vlv_sprite_update_noarm(struct intel_plane *plane,
361			const struct intel_crtc_state *crtc_state,
362			const struct intel_plane_state *plane_state)
363{
364	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
365	enum pipe pipe = plane->pipe;
366	enum plane_id plane_id = plane->id;
367	int crtc_x = plane_state->uapi.dst.x1;
368	int crtc_y = plane_state->uapi.dst.y1;
369	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
370	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
371
372	intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id),
373			  plane_state->view.color_plane[0].mapping_stride);
374	intel_de_write_fw(dev_priv, SPPOS(pipe, plane_id),
375			  SP_POS_Y(crtc_y) | SP_POS_X(crtc_x));
376	intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id),
377			  SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1));
378}
379
380static void
381vlv_sprite_update_arm(struct intel_plane *plane,
382		      const struct intel_crtc_state *crtc_state,
383		      const struct intel_plane_state *plane_state)
384{
385	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
386	enum pipe pipe = plane->pipe;
387	enum plane_id plane_id = plane->id;
388	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
389	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
390	u32 x = plane_state->view.color_plane[0].x;
391	u32 y = plane_state->view.color_plane[0].y;
392	u32 sprctl, linear_offset;
393
394	sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state);
395
396	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
397
398	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
399		chv_sprite_update_csc(plane_state);
400
401	if (key->flags) {
402		intel_de_write_fw(dev_priv, SPKEYMINVAL(pipe, plane_id),
403				  key->min_value);
404		intel_de_write_fw(dev_priv, SPKEYMSK(pipe, plane_id),
405				  key->channel_mask);
406		intel_de_write_fw(dev_priv, SPKEYMAXVAL(pipe, plane_id),
407				  key->max_value);
408	}
409
410	intel_de_write_fw(dev_priv, SPCONSTALPHA(pipe, plane_id), 0);
411
412	intel_de_write_fw(dev_priv, SPLINOFF(pipe, plane_id), linear_offset);
413	intel_de_write_fw(dev_priv, SPTILEOFF(pipe, plane_id),
414			  SP_OFFSET_Y(y) | SP_OFFSET_X(x));
415
416	/*
417	 * The control register self-arms if the plane was previously
418	 * disabled. Try to make the plane enable atomic by writing
419	 * the control register just before the surface register.
420	 */
421	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), sprctl);
422	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id),
423			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
424
425	vlv_sprite_update_clrc(plane_state);
426	vlv_sprite_update_gamma(plane_state);
427}
428
429static void
430vlv_sprite_disable_arm(struct intel_plane *plane,
431		       const struct intel_crtc_state *crtc_state)
432{
433	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
434	enum pipe pipe = plane->pipe;
435	enum plane_id plane_id = plane->id;
436
437	intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0);
438	intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0);
439}
440
441static bool
442vlv_sprite_get_hw_state(struct intel_plane *plane,
443			enum pipe *pipe)
444{
445	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
446	enum intel_display_power_domain power_domain;
447	enum plane_id plane_id = plane->id;
448	intel_wakeref_t wakeref;
449	bool ret;
450
451	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
452	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
453	if (!wakeref)
454		return false;
455
456	ret = intel_de_read(dev_priv, SPCNTR(plane->pipe, plane_id)) & SP_ENABLE;
457
458	*pipe = plane->pipe;
459
460	intel_display_power_put(dev_priv, power_domain, wakeref);
461
462	return ret;
463}
464
465static void ivb_plane_ratio(const struct intel_crtc_state *crtc_state,
466			    const struct intel_plane_state *plane_state,
467			    unsigned int *num, unsigned int *den)
468{
469	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
470	const struct drm_framebuffer *fb = plane_state->hw.fb;
471	unsigned int cpp = fb->format->cpp[0];
472
473	if (hweight8(active_planes) == 2) {
474		switch (cpp) {
475		case 8:
476			*num = 10;
477			*den = 8;
478			break;
479		case 4:
480			*num = 17;
481			*den = 16;
482			break;
483		default:
484			*num = 1;
485			*den = 1;
486			break;
487		}
488	} else {
489		switch (cpp) {
490		case 8:
491			*num = 9;
492			*den = 8;
493			break;
494		default:
495			*num = 1;
496			*den = 1;
497			break;
498		}
499	}
500}
501
502static void ivb_plane_ratio_scaling(const struct intel_crtc_state *crtc_state,
503				    const struct intel_plane_state *plane_state,
504				    unsigned int *num, unsigned int *den)
505{
506	const struct drm_framebuffer *fb = plane_state->hw.fb;
507	unsigned int cpp = fb->format->cpp[0];
508
509	switch (cpp) {
510	case 8:
511		*num = 12;
512		*den = 8;
513		break;
514	case 4:
515		*num = 19;
516		*den = 16;
517		break;
518	case 2:
519		*num = 33;
520		*den = 32;
521		break;
522	default:
523		*num = 1;
524		*den = 1;
525		break;
526	}
527}
528
529int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
530			const struct intel_plane_state *plane_state)
531{
532	unsigned int pixel_rate;
533	unsigned int num, den;
534
535	/*
536	 * Note that crtc_state->pixel_rate accounts for both
537	 * horizontal and vertical panel fitter downscaling factors.
538	 * Pre-HSW bspec tells us to only consider the horizontal
539	 * downscaling factor here. We ignore that and just consider
540	 * both for simplicity.
541	 */
542	pixel_rate = crtc_state->pixel_rate;
543
544	ivb_plane_ratio(crtc_state, plane_state, &num, &den);
545
546	return DIV_ROUND_UP(pixel_rate * num, den);
547}
548
549static int ivb_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
550				const struct intel_plane_state *plane_state)
551{
552	unsigned int src_w, dst_w, pixel_rate;
553	unsigned int num, den;
554
555	/*
556	 * Note that crtc_state->pixel_rate accounts for both
557	 * horizontal and vertical panel fitter downscaling factors.
558	 * Pre-HSW bspec tells us to only consider the horizontal
559	 * downscaling factor here. We ignore that and just consider
560	 * both for simplicity.
561	 */
562	pixel_rate = crtc_state->pixel_rate;
563
564	src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
565	dst_w = drm_rect_width(&plane_state->uapi.dst);
566
567	if (src_w != dst_w)
568		ivb_plane_ratio_scaling(crtc_state, plane_state, &num, &den);
569	else
570		ivb_plane_ratio(crtc_state, plane_state, &num, &den);
571
572	/* Horizontal downscaling limits the maximum pixel rate */
573	dst_w = min(src_w, dst_w);
574
575	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, num * src_w),
576				den * dst_w);
577}
578
579static void hsw_plane_ratio(const struct intel_crtc_state *crtc_state,
580			    const struct intel_plane_state *plane_state,
581			    unsigned int *num, unsigned int *den)
582{
583	u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
584	const struct drm_framebuffer *fb = plane_state->hw.fb;
585	unsigned int cpp = fb->format->cpp[0];
586
587	if (hweight8(active_planes) == 2) {
588		switch (cpp) {
589		case 8:
590			*num = 10;
591			*den = 8;
592			break;
593		default:
594			*num = 1;
595			*den = 1;
596			break;
597		}
598	} else {
599		switch (cpp) {
600		case 8:
601			*num = 9;
602			*den = 8;
603			break;
604		default:
605			*num = 1;
606			*den = 1;
607			break;
608		}
609	}
610}
611
612int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
613			const struct intel_plane_state *plane_state)
614{
615	unsigned int pixel_rate = crtc_state->pixel_rate;
616	unsigned int num, den;
617
618	hsw_plane_ratio(crtc_state, plane_state, &num, &den);
619
620	return DIV_ROUND_UP(pixel_rate * num, den);
621}
622
623static u32 ivb_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
624{
625	u32 sprctl = 0;
626
627	if (crtc_state->gamma_enable)
628		sprctl |= SPRITE_PIPE_GAMMA_ENABLE;
629
630	if (crtc_state->csc_enable)
631		sprctl |= SPRITE_PIPE_CSC_ENABLE;
632
633	return sprctl;
634}
635
636static bool ivb_need_sprite_gamma(const struct intel_plane_state *plane_state)
637{
638	struct drm_i915_private *dev_priv =
639		to_i915(plane_state->uapi.plane->dev);
640	const struct drm_framebuffer *fb = plane_state->hw.fb;
641
642	return fb->format->cpp[0] == 8 &&
643		(IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv));
644}
645
646static u32 ivb_sprite_ctl(const struct intel_crtc_state *crtc_state,
647			  const struct intel_plane_state *plane_state)
648{
649	struct drm_i915_private *dev_priv =
650		to_i915(plane_state->uapi.plane->dev);
651	const struct drm_framebuffer *fb = plane_state->hw.fb;
652	unsigned int rotation = plane_state->hw.rotation;
653	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
654	u32 sprctl;
655
656	sprctl = SPRITE_ENABLE;
657
658	if (IS_IVYBRIDGE(dev_priv))
659		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
660
661	switch (fb->format->format) {
662	case DRM_FORMAT_XBGR8888:
663		sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
664		break;
665	case DRM_FORMAT_XRGB8888:
666		sprctl |= SPRITE_FORMAT_RGBX888;
667		break;
668	case DRM_FORMAT_XBGR2101010:
669		sprctl |= SPRITE_FORMAT_RGBX101010 | SPRITE_RGB_ORDER_RGBX;
670		break;
671	case DRM_FORMAT_XRGB2101010:
672		sprctl |= SPRITE_FORMAT_RGBX101010;
673		break;
674	case DRM_FORMAT_XBGR16161616F:
675		sprctl |= SPRITE_FORMAT_RGBX161616 | SPRITE_RGB_ORDER_RGBX;
676		break;
677	case DRM_FORMAT_XRGB16161616F:
678		sprctl |= SPRITE_FORMAT_RGBX161616;
679		break;
680	case DRM_FORMAT_YUYV:
681		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YUYV;
682		break;
683	case DRM_FORMAT_YVYU:
684		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_YVYU;
685		break;
686	case DRM_FORMAT_UYVY:
687		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_UYVY;
688		break;
689	case DRM_FORMAT_VYUY:
690		sprctl |= SPRITE_FORMAT_YUV422 | SPRITE_YUV_ORDER_VYUY;
691		break;
692	default:
693		MISSING_CASE(fb->format->format);
694		return 0;
695	}
696
697	if (!ivb_need_sprite_gamma(plane_state))
698		sprctl |= SPRITE_PLANE_GAMMA_DISABLE;
699
700	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
701		sprctl |= SPRITE_YUV_TO_RGB_CSC_FORMAT_BT709;
702
703	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
704		sprctl |= SPRITE_YUV_RANGE_CORRECTION_DISABLE;
705
706	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
707		sprctl |= SPRITE_TILED;
708
709	if (rotation & DRM_MODE_ROTATE_180)
710		sprctl |= SPRITE_ROTATE_180;
711
712	if (key->flags & I915_SET_COLORKEY_DESTINATION)
713		sprctl |= SPRITE_DEST_KEY;
714	else if (key->flags & I915_SET_COLORKEY_SOURCE)
715		sprctl |= SPRITE_SOURCE_KEY;
716
717	return sprctl;
718}
719
720static void ivb_sprite_linear_gamma(const struct intel_plane_state *plane_state,
721				    u16 gamma[18])
722{
723	int scale, i;
724
725	/*
726	 * WaFP16GammaEnabling:ivb,hsw
727	 * "Workaround : When using the 64-bit format, the sprite output
728	 *  on each color channel has one quarter amplitude. It can be
729	 *  brought up to full amplitude by using sprite internal gamma
730	 *  correction, pipe gamma correction, or pipe color space
731	 *  conversion to multiply the sprite output by four."
732	 */
733	scale = 4;
734
735	for (i = 0; i < 16; i++)
736		gamma[i] = min((scale * i << 10) / 16, (1 << 10) - 1);
737
738	gamma[i] = min((scale * i << 10) / 16, 1 << 10);
739	i++;
740
741	gamma[i] = 3 << 10;
742	i++;
743}
744
745static void ivb_sprite_update_gamma(const struct intel_plane_state *plane_state)
746{
747	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
748	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
749	enum pipe pipe = plane->pipe;
750	u16 gamma[18];
751	int i;
752
753	if (!ivb_need_sprite_gamma(plane_state))
754		return;
755
756	ivb_sprite_linear_gamma(plane_state, gamma);
757
758	/* FIXME these register are single buffered :( */
759	for (i = 0; i < 16; i++)
760		intel_de_write_fw(dev_priv, SPRGAMC(pipe, i),
761				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
762
763	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 0), gamma[i]);
764	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 1), gamma[i]);
765	intel_de_write_fw(dev_priv, SPRGAMC16(pipe, 2), gamma[i]);
766	i++;
767
768	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 0), gamma[i]);
769	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 1), gamma[i]);
770	intel_de_write_fw(dev_priv, SPRGAMC17(pipe, 2), gamma[i]);
771	i++;
772}
773
774static void
775ivb_sprite_update_noarm(struct intel_plane *plane,
776			const struct intel_crtc_state *crtc_state,
777			const struct intel_plane_state *plane_state)
778{
779	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
780	enum pipe pipe = plane->pipe;
781	int crtc_x = plane_state->uapi.dst.x1;
782	int crtc_y = plane_state->uapi.dst.y1;
783	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
784	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
785	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
786	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
787	u32 sprscale = 0;
788
789	if (crtc_w != src_w || crtc_h != src_h)
790		sprscale = SPRITE_SCALE_ENABLE |
791			SPRITE_SRC_WIDTH(src_w - 1) |
792			SPRITE_SRC_HEIGHT(src_h - 1);
793
794	intel_de_write_fw(dev_priv, SPRSTRIDE(pipe),
795			  plane_state->view.color_plane[0].mapping_stride);
796	intel_de_write_fw(dev_priv, SPRPOS(pipe),
797			  SPRITE_POS_Y(crtc_y) | SPRITE_POS_X(crtc_x));
798	intel_de_write_fw(dev_priv, SPRSIZE(pipe),
799			  SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1));
800	if (IS_IVYBRIDGE(dev_priv))
801		intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale);
802}
803
804static void
805ivb_sprite_update_arm(struct intel_plane *plane,
806		      const struct intel_crtc_state *crtc_state,
807		      const struct intel_plane_state *plane_state)
808{
809	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
810	enum pipe pipe = plane->pipe;
811	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
812	u32 sprsurf_offset = plane_state->view.color_plane[0].offset;
813	u32 x = plane_state->view.color_plane[0].x;
814	u32 y = plane_state->view.color_plane[0].y;
815	u32 sprctl, linear_offset;
816
817	sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state);
818
819	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
820
821	if (key->flags) {
822		intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value);
823		intel_de_write_fw(dev_priv, SPRKEYMSK(pipe),
824				  key->channel_mask);
825		intel_de_write_fw(dev_priv, SPRKEYMAX(pipe), key->max_value);
826	}
827
828	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
829	 * register */
830	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
831		intel_de_write_fw(dev_priv, SPROFFSET(pipe),
832				  SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
833	} else {
834		intel_de_write_fw(dev_priv, SPRLINOFF(pipe), linear_offset);
835		intel_de_write_fw(dev_priv, SPRTILEOFF(pipe),
836				  SPRITE_OFFSET_Y(y) | SPRITE_OFFSET_X(x));
837	}
838
839	/*
840	 * The control register self-arms if the plane was previously
841	 * disabled. Try to make the plane enable atomic by writing
842	 * the control register just before the surface register.
843	 */
844	intel_de_write_fw(dev_priv, SPRCTL(pipe), sprctl);
845	intel_de_write_fw(dev_priv, SPRSURF(pipe),
846			  intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
847
848	ivb_sprite_update_gamma(plane_state);
849}
850
851static void
852ivb_sprite_disable_arm(struct intel_plane *plane,
853		       const struct intel_crtc_state *crtc_state)
854{
855	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
856	enum pipe pipe = plane->pipe;
857
858	intel_de_write_fw(dev_priv, SPRCTL(pipe), 0);
859	/* Disable the scaler */
860	if (IS_IVYBRIDGE(dev_priv))
861		intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0);
862	intel_de_write_fw(dev_priv, SPRSURF(pipe), 0);
863}
864
865static bool
866ivb_sprite_get_hw_state(struct intel_plane *plane,
867			enum pipe *pipe)
868{
869	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
870	enum intel_display_power_domain power_domain;
871	intel_wakeref_t wakeref;
872	bool ret;
873
874	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
875	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
876	if (!wakeref)
877		return false;
878
879	ret =  intel_de_read(dev_priv, SPRCTL(plane->pipe)) & SPRITE_ENABLE;
880
881	*pipe = plane->pipe;
882
883	intel_display_power_put(dev_priv, power_domain, wakeref);
884
885	return ret;
886}
887
888static int g4x_sprite_min_cdclk(const struct intel_crtc_state *crtc_state,
889				const struct intel_plane_state *plane_state)
890{
891	const struct drm_framebuffer *fb = plane_state->hw.fb;
892	unsigned int hscale, pixel_rate;
893	unsigned int limit, decimate;
894
895	/*
896	 * Note that crtc_state->pixel_rate accounts for both
897	 * horizontal and vertical panel fitter downscaling factors.
898	 * Pre-HSW bspec tells us to only consider the horizontal
899	 * downscaling factor here. We ignore that and just consider
900	 * both for simplicity.
901	 */
902	pixel_rate = crtc_state->pixel_rate;
903
904	/* Horizontal downscaling limits the maximum pixel rate */
905	hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
906				      &plane_state->uapi.dst,
907				      0, INT_MAX);
908	hscale = max(hscale, 0x10000u);
909
910	/* Decimation steps at 2x,4x,8x,16x */
911	decimate = ilog2(hscale >> 16);
912	hscale >>= decimate;
913
914	/* Starting limit is 90% of cdclk */
915	limit = 9;
916
917	/* -10% per decimation step */
918	limit -= decimate;
919
920	/* -10% for RGB */
921	if (!fb->format->is_yuv)
922		limit--;
923
924	/*
925	 * We should also do -10% if sprite scaling is enabled
926	 * on the other pipe, but we can't really check for that,
927	 * so we ignore it.
928	 */
929
930	return DIV_ROUND_UP_ULL(mul_u32_u32(pixel_rate, 10 * hscale),
931				limit << 16);
932}
933
934static unsigned int
935g4x_sprite_max_stride(struct intel_plane *plane,
936		      u32 pixel_format, u64 modifier,
937		      unsigned int rotation)
938{
939	const struct drm_format_info *info = drm_format_info(pixel_format);
940	int cpp = info->cpp[0];
941
942	/* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
943	if (modifier == I915_FORMAT_MOD_X_TILED)
944		return min(4096 * cpp, 16 * 1024);
945	else
946		return 16 * 1024;
947}
948
949static unsigned int
950hsw_sprite_max_stride(struct intel_plane *plane,
951		      u32 pixel_format, u64 modifier,
952		      unsigned int rotation)
953{
954	const struct drm_format_info *info = drm_format_info(pixel_format);
955	int cpp = info->cpp[0];
956
957	/* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
958	return min(8192 * cpp, 16 * 1024);
959}
960
961static u32 g4x_sprite_ctl_crtc(const struct intel_crtc_state *crtc_state)
962{
963	u32 dvscntr = 0;
964
965	if (crtc_state->gamma_enable)
966		dvscntr |= DVS_PIPE_GAMMA_ENABLE;
967
968	if (crtc_state->csc_enable)
969		dvscntr |= DVS_PIPE_CSC_ENABLE;
970
971	return dvscntr;
972}
973
974static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state,
975			  const struct intel_plane_state *plane_state)
976{
977	struct drm_i915_private *dev_priv =
978		to_i915(plane_state->uapi.plane->dev);
979	const struct drm_framebuffer *fb = plane_state->hw.fb;
980	unsigned int rotation = plane_state->hw.rotation;
981	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
982	u32 dvscntr;
983
984	dvscntr = DVS_ENABLE;
985
986	if (IS_SANDYBRIDGE(dev_priv))
987		dvscntr |= DVS_TRICKLE_FEED_DISABLE;
988
989	switch (fb->format->format) {
990	case DRM_FORMAT_XBGR8888:
991		dvscntr |= DVS_FORMAT_RGBX888 | DVS_RGB_ORDER_XBGR;
992		break;
993	case DRM_FORMAT_XRGB8888:
994		dvscntr |= DVS_FORMAT_RGBX888;
995		break;
996	case DRM_FORMAT_XBGR2101010:
997		dvscntr |= DVS_FORMAT_RGBX101010 | DVS_RGB_ORDER_XBGR;
998		break;
999	case DRM_FORMAT_XRGB2101010:
1000		dvscntr |= DVS_FORMAT_RGBX101010;
1001		break;
1002	case DRM_FORMAT_XBGR16161616F:
1003		dvscntr |= DVS_FORMAT_RGBX161616 | DVS_RGB_ORDER_XBGR;
1004		break;
1005	case DRM_FORMAT_XRGB16161616F:
1006		dvscntr |= DVS_FORMAT_RGBX161616;
1007		break;
1008	case DRM_FORMAT_YUYV:
1009		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YUYV;
1010		break;
1011	case DRM_FORMAT_YVYU:
1012		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_YVYU;
1013		break;
1014	case DRM_FORMAT_UYVY:
1015		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_UYVY;
1016		break;
1017	case DRM_FORMAT_VYUY:
1018		dvscntr |= DVS_FORMAT_YUV422 | DVS_YUV_ORDER_VYUY;
1019		break;
1020	default:
1021		MISSING_CASE(fb->format->format);
1022		return 0;
1023	}
1024
1025	if (plane_state->hw.color_encoding == DRM_COLOR_YCBCR_BT709)
1026		dvscntr |= DVS_YUV_FORMAT_BT709;
1027
1028	if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
1029		dvscntr |= DVS_YUV_RANGE_CORRECTION_DISABLE;
1030
1031	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
1032		dvscntr |= DVS_TILED;
1033
1034	if (rotation & DRM_MODE_ROTATE_180)
1035		dvscntr |= DVS_ROTATE_180;
1036
1037	if (key->flags & I915_SET_COLORKEY_DESTINATION)
1038		dvscntr |= DVS_DEST_KEY;
1039	else if (key->flags & I915_SET_COLORKEY_SOURCE)
1040		dvscntr |= DVS_SOURCE_KEY;
1041
1042	return dvscntr;
1043}
1044
1045static void g4x_sprite_update_gamma(const struct intel_plane_state *plane_state)
1046{
1047	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1048	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1049	const struct drm_framebuffer *fb = plane_state->hw.fb;
1050	enum pipe pipe = plane->pipe;
1051	u16 gamma[8];
1052	int i;
1053
1054	/* Seems RGB data bypasses the gamma always */
1055	if (!fb->format->is_yuv)
1056		return;
1057
1058	i9xx_plane_linear_gamma(gamma);
1059
1060	/* FIXME these register are single buffered :( */
1061	/* The two end points are implicit (0.0 and 1.0) */
1062	for (i = 1; i < 8 - 1; i++)
1063		intel_de_write_fw(dev_priv, DVSGAMC_G4X(pipe, i - 1),
1064				  gamma[i] << 16 | gamma[i] << 8 | gamma[i]);
1065}
1066
1067static void ilk_sprite_linear_gamma(u16 gamma[17])
1068{
1069	int i;
1070
1071	for (i = 0; i < 17; i++)
1072		gamma[i] = (i << 10) / 16;
1073}
1074
1075static void ilk_sprite_update_gamma(const struct intel_plane_state *plane_state)
1076{
1077	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1078	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1079	const struct drm_framebuffer *fb = plane_state->hw.fb;
1080	enum pipe pipe = plane->pipe;
1081	u16 gamma[17];
1082	int i;
1083
1084	/* Seems RGB data bypasses the gamma always */
1085	if (!fb->format->is_yuv)
1086		return;
1087
1088	ilk_sprite_linear_gamma(gamma);
1089
1090	/* FIXME these register are single buffered :( */
1091	for (i = 0; i < 16; i++)
1092		intel_de_write_fw(dev_priv, DVSGAMC_ILK(pipe, i),
1093				  gamma[i] << 20 | gamma[i] << 10 | gamma[i]);
1094
1095	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 0), gamma[i]);
1096	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 1), gamma[i]);
1097	intel_de_write_fw(dev_priv, DVSGAMCMAX_ILK(pipe, 2), gamma[i]);
1098	i++;
1099}
1100
1101static void
1102g4x_sprite_update_noarm(struct intel_plane *plane,
1103			const struct intel_crtc_state *crtc_state,
1104			const struct intel_plane_state *plane_state)
1105{
1106	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1107	enum pipe pipe = plane->pipe;
1108	int crtc_x = plane_state->uapi.dst.x1;
1109	int crtc_y = plane_state->uapi.dst.y1;
1110	u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
1111	u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
1112	u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
1113	u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
1114	u32 dvsscale = 0;
1115
1116	if (crtc_w != src_w || crtc_h != src_h)
1117		dvsscale = DVS_SCALE_ENABLE |
1118			DVS_SRC_WIDTH(src_w - 1) |
1119			DVS_SRC_HEIGHT(src_h - 1);
1120
1121	intel_de_write_fw(dev_priv, DVSSTRIDE(pipe),
1122			  plane_state->view.color_plane[0].mapping_stride);
1123	intel_de_write_fw(dev_priv, DVSPOS(pipe),
1124			  DVS_POS_Y(crtc_y) | DVS_POS_X(crtc_x));
1125	intel_de_write_fw(dev_priv, DVSSIZE(pipe),
1126			  DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1));
1127	intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale);
1128}
1129
1130static void
1131g4x_sprite_update_arm(struct intel_plane *plane,
1132		      const struct intel_crtc_state *crtc_state,
1133		      const struct intel_plane_state *plane_state)
1134{
1135	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1136	enum pipe pipe = plane->pipe;
1137	const struct drm_intel_sprite_colorkey *key = &plane_state->ckey;
1138	u32 dvssurf_offset = plane_state->view.color_plane[0].offset;
1139	u32 x = plane_state->view.color_plane[0].x;
1140	u32 y = plane_state->view.color_plane[0].y;
1141	u32 dvscntr, linear_offset;
1142
1143	dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state);
1144
1145	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
1146
1147	if (key->flags) {
1148		intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value);
1149		intel_de_write_fw(dev_priv, DVSKEYMSK(pipe),
1150				  key->channel_mask);
1151		intel_de_write_fw(dev_priv, DVSKEYMAX(pipe), key->max_value);
1152	}
1153
1154	intel_de_write_fw(dev_priv, DVSLINOFF(pipe), linear_offset);
1155	intel_de_write_fw(dev_priv, DVSTILEOFF(pipe),
1156			  DVS_OFFSET_Y(y) | DVS_OFFSET_X(x));
1157
1158	/*
1159	 * The control register self-arms if the plane was previously
1160	 * disabled. Try to make the plane enable atomic by writing
1161	 * the control register just before the surface register.
1162	 */
1163	intel_de_write_fw(dev_priv, DVSCNTR(pipe), dvscntr);
1164	intel_de_write_fw(dev_priv, DVSSURF(pipe),
1165			  intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
1166
1167	if (IS_G4X(dev_priv))
1168		g4x_sprite_update_gamma(plane_state);
1169	else
1170		ilk_sprite_update_gamma(plane_state);
1171}
1172
1173static void
1174g4x_sprite_disable_arm(struct intel_plane *plane,
1175		       const struct intel_crtc_state *crtc_state)
1176{
1177	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1178	enum pipe pipe = plane->pipe;
1179
1180	intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0);
1181	/* Disable the scaler */
1182	intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0);
1183	intel_de_write_fw(dev_priv, DVSSURF(pipe), 0);
1184}
1185
1186static bool
1187g4x_sprite_get_hw_state(struct intel_plane *plane,
1188			enum pipe *pipe)
1189{
1190	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1191	enum intel_display_power_domain power_domain;
1192	intel_wakeref_t wakeref;
1193	bool ret;
1194
1195	power_domain = POWER_DOMAIN_PIPE(plane->pipe);
1196	wakeref = intel_display_power_get_if_enabled(dev_priv, power_domain);
1197	if (!wakeref)
1198		return false;
1199
1200	ret = intel_de_read(dev_priv, DVSCNTR(plane->pipe)) & DVS_ENABLE;
1201
1202	*pipe = plane->pipe;
1203
1204	intel_display_power_put(dev_priv, power_domain, wakeref);
1205
1206	return ret;
1207}
1208
1209static bool g4x_fb_scalable(const struct drm_framebuffer *fb)
1210{
1211	if (!fb)
1212		return false;
1213
1214	switch (fb->format->format) {
1215	case DRM_FORMAT_C8:
1216	case DRM_FORMAT_XRGB16161616F:
1217	case DRM_FORMAT_ARGB16161616F:
1218	case DRM_FORMAT_XBGR16161616F:
1219	case DRM_FORMAT_ABGR16161616F:
1220		return false;
1221	default:
1222		return true;
1223	}
1224}
1225
1226static int
1227g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state,
1228			 struct intel_plane_state *plane_state)
1229{
1230	struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
1231	const struct drm_framebuffer *fb = plane_state->hw.fb;
1232	const struct drm_rect *src = &plane_state->uapi.src;
1233	const struct drm_rect *dst = &plane_state->uapi.dst;
1234	int src_x, src_w, src_h, crtc_w, crtc_h;
1235	const struct drm_display_mode *adjusted_mode =
1236		&crtc_state->hw.adjusted_mode;
1237	unsigned int stride = plane_state->view.color_plane[0].mapping_stride;
1238	unsigned int cpp = fb->format->cpp[0];
1239	unsigned int width_bytes;
1240	int min_width, min_height;
1241
1242	crtc_w = drm_rect_width(dst);
1243	crtc_h = drm_rect_height(dst);
1244
1245	src_x = src->x1 >> 16;
1246	src_w = drm_rect_width(src) >> 16;
1247	src_h = drm_rect_height(src) >> 16;
1248
1249	if (src_w == crtc_w && src_h == crtc_h)
1250		return 0;
1251
1252	min_width = 3;
1253
1254	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
1255		if (src_h & 1) {
1256			drm_dbg_kms(&i915->drm, "Source height must be even with interlaced modes\n");
1257			return -EINVAL;
1258		}
1259		min_height = 6;
1260	} else {
1261		min_height = 3;
1262	}
1263
1264	width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
1265
1266	if (src_w < min_width || src_h < min_height ||
1267	    src_w > 2048 || src_h > 2048) {
1268		drm_dbg_kms(&i915->drm, "Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n",
1269			    src_w, src_h, min_width, min_height, 2048, 2048);
1270		return -EINVAL;
1271	}
1272
1273	if (width_bytes > 4096) {
1274		drm_dbg_kms(&i915->drm, "Fetch width (%d) exceeds hardware max with scaling (%u)\n",
1275			    width_bytes, 4096);
1276		return -EINVAL;
1277	}
1278
1279	if (stride > 4096) {
1280		drm_dbg_kms(&i915->drm, "Stride (%u) exceeds hardware max with scaling (%u)\n",
1281			    stride, 4096);
1282		return -EINVAL;
1283	}
1284
1285	return 0;
1286}
1287
1288static int
1289g4x_sprite_check(struct intel_crtc_state *crtc_state,
1290		 struct intel_plane_state *plane_state)
1291{
1292	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1293	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1294	int min_scale = DRM_PLANE_NO_SCALING;
1295	int max_scale = DRM_PLANE_NO_SCALING;
1296	int ret;
1297
1298	if (g4x_fb_scalable(plane_state->hw.fb)) {
1299		if (DISPLAY_VER(dev_priv) < 7) {
1300			min_scale = 1;
1301			max_scale = 16 << 16;
1302		} else if (IS_IVYBRIDGE(dev_priv)) {
1303			min_scale = 1;
1304			max_scale = 2 << 16;
1305		}
1306	}
1307
1308	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1309						min_scale, max_scale, true);
1310	if (ret)
1311		return ret;
1312
1313	ret = i9xx_check_plane_surface(plane_state);
1314	if (ret)
1315		return ret;
1316
1317	if (!plane_state->uapi.visible)
1318		return 0;
1319
1320	ret = intel_plane_check_src_coordinates(plane_state);
1321	if (ret)
1322		return ret;
1323
1324	ret = g4x_sprite_check_scaling(crtc_state, plane_state);
1325	if (ret)
1326		return ret;
1327
1328	if (DISPLAY_VER(dev_priv) >= 7)
1329		plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
1330	else
1331		plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state);
1332
1333	return 0;
1334}
1335
1336int chv_plane_check_rotation(const struct intel_plane_state *plane_state)
1337{
1338	struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
1339	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
1340	unsigned int rotation = plane_state->hw.rotation;
1341
1342	/* CHV ignores the mirror bit when the rotate bit is set :( */
1343	if (IS_CHERRYVIEW(dev_priv) &&
1344	    rotation & DRM_MODE_ROTATE_180 &&
1345	    rotation & DRM_MODE_REFLECT_X) {
1346		drm_dbg_kms(&dev_priv->drm,
1347			    "Cannot rotate and reflect at the same time\n");
1348		return -EINVAL;
1349	}
1350
1351	return 0;
1352}
1353
1354static int
1355vlv_sprite_check(struct intel_crtc_state *crtc_state,
1356		 struct intel_plane_state *plane_state)
1357{
1358	int ret;
1359
1360	ret = chv_plane_check_rotation(plane_state);
1361	if (ret)
1362		return ret;
1363
1364	ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
1365						DRM_PLANE_NO_SCALING,
1366						DRM_PLANE_NO_SCALING,
1367						true);
1368	if (ret)
1369		return ret;
1370
1371	ret = i9xx_check_plane_surface(plane_state);
1372	if (ret)
1373		return ret;
1374
1375	if (!plane_state->uapi.visible)
1376		return 0;
1377
1378	ret = intel_plane_check_src_coordinates(plane_state);
1379	if (ret)
1380		return ret;
1381
1382	plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
1383
1384	return 0;
1385}
1386
1387static const u32 g4x_sprite_formats[] = {
1388	DRM_FORMAT_XRGB8888,
1389	DRM_FORMAT_YUYV,
1390	DRM_FORMAT_YVYU,
1391	DRM_FORMAT_UYVY,
1392	DRM_FORMAT_VYUY,
1393};
1394
1395static const u32 snb_sprite_formats[] = {
1396	DRM_FORMAT_XRGB8888,
1397	DRM_FORMAT_XBGR8888,
1398	DRM_FORMAT_XRGB2101010,
1399	DRM_FORMAT_XBGR2101010,
1400	DRM_FORMAT_XRGB16161616F,
1401	DRM_FORMAT_XBGR16161616F,
1402	DRM_FORMAT_YUYV,
1403	DRM_FORMAT_YVYU,
1404	DRM_FORMAT_UYVY,
1405	DRM_FORMAT_VYUY,
1406};
1407
1408static const u32 vlv_sprite_formats[] = {
1409	DRM_FORMAT_C8,
1410	DRM_FORMAT_RGB565,
1411	DRM_FORMAT_XRGB8888,
1412	DRM_FORMAT_XBGR8888,
1413	DRM_FORMAT_ARGB8888,
1414	DRM_FORMAT_ABGR8888,
1415	DRM_FORMAT_XBGR2101010,
1416	DRM_FORMAT_ABGR2101010,
1417	DRM_FORMAT_YUYV,
1418	DRM_FORMAT_YVYU,
1419	DRM_FORMAT_UYVY,
1420	DRM_FORMAT_VYUY,
1421};
1422
1423static const u32 chv_pipe_b_sprite_formats[] = {
1424	DRM_FORMAT_C8,
1425	DRM_FORMAT_RGB565,
1426	DRM_FORMAT_XRGB8888,
1427	DRM_FORMAT_XBGR8888,
1428	DRM_FORMAT_ARGB8888,
1429	DRM_FORMAT_ABGR8888,
1430	DRM_FORMAT_XRGB2101010,
1431	DRM_FORMAT_XBGR2101010,
1432	DRM_FORMAT_ARGB2101010,
1433	DRM_FORMAT_ABGR2101010,
1434	DRM_FORMAT_YUYV,
1435	DRM_FORMAT_YVYU,
1436	DRM_FORMAT_UYVY,
1437	DRM_FORMAT_VYUY,
1438};
1439
1440static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
1441					    u32 format, u64 modifier)
1442{
1443	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1444		return false;
1445
1446	switch (format) {
1447	case DRM_FORMAT_XRGB8888:
1448	case DRM_FORMAT_YUYV:
1449	case DRM_FORMAT_YVYU:
1450	case DRM_FORMAT_UYVY:
1451	case DRM_FORMAT_VYUY:
1452		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1453		    modifier == I915_FORMAT_MOD_X_TILED)
1454			return true;
1455		fallthrough;
1456	default:
1457		return false;
1458	}
1459}
1460
1461static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
1462					    u32 format, u64 modifier)
1463{
1464	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1465		return false;
1466
1467	switch (format) {
1468	case DRM_FORMAT_XRGB8888:
1469	case DRM_FORMAT_XBGR8888:
1470	case DRM_FORMAT_XRGB2101010:
1471	case DRM_FORMAT_XBGR2101010:
1472	case DRM_FORMAT_XRGB16161616F:
1473	case DRM_FORMAT_XBGR16161616F:
1474	case DRM_FORMAT_YUYV:
1475	case DRM_FORMAT_YVYU:
1476	case DRM_FORMAT_UYVY:
1477	case DRM_FORMAT_VYUY:
1478		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1479		    modifier == I915_FORMAT_MOD_X_TILED)
1480			return true;
1481		fallthrough;
1482	default:
1483		return false;
1484	}
1485}
1486
1487static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
1488					    u32 format, u64 modifier)
1489{
1490	if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
1491		return false;
1492
1493	switch (format) {
1494	case DRM_FORMAT_C8:
1495	case DRM_FORMAT_RGB565:
1496	case DRM_FORMAT_ABGR8888:
1497	case DRM_FORMAT_ARGB8888:
1498	case DRM_FORMAT_XBGR8888:
1499	case DRM_FORMAT_XRGB8888:
1500	case DRM_FORMAT_XBGR2101010:
1501	case DRM_FORMAT_ABGR2101010:
1502	case DRM_FORMAT_XRGB2101010:
1503	case DRM_FORMAT_ARGB2101010:
1504	case DRM_FORMAT_YUYV:
1505	case DRM_FORMAT_YVYU:
1506	case DRM_FORMAT_UYVY:
1507	case DRM_FORMAT_VYUY:
1508		if (modifier == DRM_FORMAT_MOD_LINEAR ||
1509		    modifier == I915_FORMAT_MOD_X_TILED)
1510			return true;
1511		fallthrough;
1512	default:
1513		return false;
1514	}
1515}
1516
1517static const struct drm_plane_funcs g4x_sprite_funcs = {
1518	.update_plane = drm_atomic_helper_update_plane,
1519	.disable_plane = drm_atomic_helper_disable_plane,
1520	.destroy = intel_plane_destroy,
1521	.atomic_duplicate_state = intel_plane_duplicate_state,
1522	.atomic_destroy_state = intel_plane_destroy_state,
1523	.format_mod_supported = g4x_sprite_format_mod_supported,
1524};
1525
1526static const struct drm_plane_funcs snb_sprite_funcs = {
1527	.update_plane = drm_atomic_helper_update_plane,
1528	.disable_plane = drm_atomic_helper_disable_plane,
1529	.destroy = intel_plane_destroy,
1530	.atomic_duplicate_state = intel_plane_duplicate_state,
1531	.atomic_destroy_state = intel_plane_destroy_state,
1532	.format_mod_supported = snb_sprite_format_mod_supported,
1533};
1534
1535static const struct drm_plane_funcs vlv_sprite_funcs = {
1536	.update_plane = drm_atomic_helper_update_plane,
1537	.disable_plane = drm_atomic_helper_disable_plane,
1538	.destroy = intel_plane_destroy,
1539	.atomic_duplicate_state = intel_plane_duplicate_state,
1540	.atomic_destroy_state = intel_plane_destroy_state,
1541	.format_mod_supported = vlv_sprite_format_mod_supported,
1542};
1543
1544struct intel_plane *
1545intel_sprite_plane_create(struct drm_i915_private *dev_priv,
1546			  enum pipe pipe, int sprite)
1547{
1548	struct intel_plane *plane;
1549	const struct drm_plane_funcs *plane_funcs;
1550	unsigned int supported_rotations;
1551	const u64 *modifiers;
1552	const u32 *formats;
1553	int num_formats;
1554	int ret, zpos;
1555
1556	plane = intel_plane_alloc();
1557	if (IS_ERR(plane))
1558		return plane;
1559
1560	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
1561		plane->update_noarm = vlv_sprite_update_noarm;
1562		plane->update_arm = vlv_sprite_update_arm;
1563		plane->disable_arm = vlv_sprite_disable_arm;
1564		plane->get_hw_state = vlv_sprite_get_hw_state;
1565		plane->check_plane = vlv_sprite_check;
1566		plane->max_stride = i965_plane_max_stride;
1567		plane->min_cdclk = vlv_plane_min_cdclk;
1568
1569		if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1570			formats = chv_pipe_b_sprite_formats;
1571			num_formats = ARRAY_SIZE(chv_pipe_b_sprite_formats);
1572		} else {
1573			formats = vlv_sprite_formats;
1574			num_formats = ARRAY_SIZE(vlv_sprite_formats);
1575		}
1576
1577		plane_funcs = &vlv_sprite_funcs;
1578	} else if (DISPLAY_VER(dev_priv) >= 7) {
1579		plane->update_noarm = ivb_sprite_update_noarm;
1580		plane->update_arm = ivb_sprite_update_arm;
1581		plane->disable_arm = ivb_sprite_disable_arm;
1582		plane->get_hw_state = ivb_sprite_get_hw_state;
1583		plane->check_plane = g4x_sprite_check;
1584
1585		if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
1586			plane->max_stride = hsw_sprite_max_stride;
1587			plane->min_cdclk = hsw_plane_min_cdclk;
1588		} else {
1589			plane->max_stride = g4x_sprite_max_stride;
1590			plane->min_cdclk = ivb_sprite_min_cdclk;
1591		}
1592
1593		formats = snb_sprite_formats;
1594		num_formats = ARRAY_SIZE(snb_sprite_formats);
1595
1596		plane_funcs = &snb_sprite_funcs;
1597	} else {
1598		plane->update_noarm = g4x_sprite_update_noarm;
1599		plane->update_arm = g4x_sprite_update_arm;
1600		plane->disable_arm = g4x_sprite_disable_arm;
1601		plane->get_hw_state = g4x_sprite_get_hw_state;
1602		plane->check_plane = g4x_sprite_check;
1603		plane->max_stride = g4x_sprite_max_stride;
1604		plane->min_cdclk = g4x_sprite_min_cdclk;
1605
1606		if (IS_SANDYBRIDGE(dev_priv)) {
1607			formats = snb_sprite_formats;
1608			num_formats = ARRAY_SIZE(snb_sprite_formats);
1609
1610			plane_funcs = &snb_sprite_funcs;
1611		} else {
1612			formats = g4x_sprite_formats;
1613			num_formats = ARRAY_SIZE(g4x_sprite_formats);
1614
1615			plane_funcs = &g4x_sprite_funcs;
1616		}
1617	}
1618
1619	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
1620		supported_rotations =
1621			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1622			DRM_MODE_REFLECT_X;
1623	} else {
1624		supported_rotations =
1625			DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1626	}
1627
1628	plane->pipe = pipe;
1629	plane->id = PLANE_SPRITE0 + sprite;
1630	plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
1631
1632	modifiers = intel_fb_plane_get_modifiers(dev_priv, INTEL_PLANE_CAP_TILING_X);
1633
1634	ret = drm_universal_plane_init(&dev_priv->drm, &plane->base,
1635				       0, plane_funcs,
1636				       formats, num_formats, modifiers,
1637				       DRM_PLANE_TYPE_OVERLAY,
1638				       "sprite %c", sprite_name(pipe, sprite));
1639	kfree(modifiers);
1640
1641	if (ret)
1642		goto fail;
1643
1644	drm_plane_create_rotation_property(&plane->base,
1645					   DRM_MODE_ROTATE_0,
1646					   supported_rotations);
1647
1648	drm_plane_create_color_properties(&plane->base,
1649					  BIT(DRM_COLOR_YCBCR_BT601) |
1650					  BIT(DRM_COLOR_YCBCR_BT709),
1651					  BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
1652					  BIT(DRM_COLOR_YCBCR_FULL_RANGE),
1653					  DRM_COLOR_YCBCR_BT709,
1654					  DRM_COLOR_YCBCR_LIMITED_RANGE);
1655
1656	zpos = sprite + 1;
1657	drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1658
1659	intel_plane_helper_add(plane);
1660
1661	return plane;
1662
1663fail:
1664	intel_plane_free(plane);
1665
1666	return ERR_PTR(ret);
1667}
1668