1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright © 2020 Intel Corporation
4 */
5 #include <linux/kernel.h>
6
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_blend.h>
9 #include <drm/drm_fourcc.h>
10
11 #include "i915_drv.h"
12 #include "i915_reg.h"
13 #include "i9xx_plane.h"
14 #include "i9xx_plane_regs.h"
15 #include "intel_atomic.h"
16 #include "intel_atomic_plane.h"
17 #include "intel_de.h"
18 #include "intel_display_irq.h"
19 #include "intel_display_types.h"
20 #include "intel_fb.h"
21 #include "intel_fbc.h"
22 #include "intel_frontbuffer.h"
23 #include "intel_sprite.h"
24
25 /* Primary plane formats for gen <= 3 */
26 static const u32 i8xx_primary_formats[] = {
27 DRM_FORMAT_C8,
28 DRM_FORMAT_XRGB1555,
29 DRM_FORMAT_RGB565,
30 DRM_FORMAT_XRGB8888,
31 };
32
33 /* Primary plane formats for ivb (no fp16 due to hw issue) */
34 static const u32 ivb_primary_formats[] = {
35 DRM_FORMAT_C8,
36 DRM_FORMAT_RGB565,
37 DRM_FORMAT_XRGB8888,
38 DRM_FORMAT_XBGR8888,
39 DRM_FORMAT_XRGB2101010,
40 DRM_FORMAT_XBGR2101010,
41 };
42
43 /* Primary plane formats for gen >= 4, except ivb */
44 static const u32 i965_primary_formats[] = {
45 DRM_FORMAT_C8,
46 DRM_FORMAT_RGB565,
47 DRM_FORMAT_XRGB8888,
48 DRM_FORMAT_XBGR8888,
49 DRM_FORMAT_XRGB2101010,
50 DRM_FORMAT_XBGR2101010,
51 DRM_FORMAT_XBGR16161616F,
52 };
53
54 /* Primary plane formats for vlv/chv */
55 static const u32 vlv_primary_formats[] = {
56 DRM_FORMAT_C8,
57 DRM_FORMAT_RGB565,
58 DRM_FORMAT_XRGB8888,
59 DRM_FORMAT_XBGR8888,
60 DRM_FORMAT_ARGB8888,
61 DRM_FORMAT_ABGR8888,
62 DRM_FORMAT_XRGB2101010,
63 DRM_FORMAT_XBGR2101010,
64 DRM_FORMAT_ARGB2101010,
65 DRM_FORMAT_ABGR2101010,
66 DRM_FORMAT_XBGR16161616F,
67 };
68
i8xx_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)69 static bool i8xx_plane_format_mod_supported(struct drm_plane *_plane,
70 u32 format, u64 modifier)
71 {
72 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
73 return false;
74
75 switch (format) {
76 case DRM_FORMAT_C8:
77 case DRM_FORMAT_RGB565:
78 case DRM_FORMAT_XRGB1555:
79 case DRM_FORMAT_XRGB8888:
80 return modifier == DRM_FORMAT_MOD_LINEAR ||
81 modifier == I915_FORMAT_MOD_X_TILED;
82 default:
83 return false;
84 }
85 }
86
i965_plane_format_mod_supported(struct drm_plane * _plane,u32 format,u64 modifier)87 static bool i965_plane_format_mod_supported(struct drm_plane *_plane,
88 u32 format, u64 modifier)
89 {
90 if (!intel_fb_plane_supports_modifier(to_intel_plane(_plane), modifier))
91 return false;
92
93 switch (format) {
94 case DRM_FORMAT_C8:
95 case DRM_FORMAT_RGB565:
96 case DRM_FORMAT_XRGB8888:
97 case DRM_FORMAT_XBGR8888:
98 case DRM_FORMAT_ARGB8888:
99 case DRM_FORMAT_ABGR8888:
100 case DRM_FORMAT_XRGB2101010:
101 case DRM_FORMAT_XBGR2101010:
102 case DRM_FORMAT_ARGB2101010:
103 case DRM_FORMAT_ABGR2101010:
104 case DRM_FORMAT_XBGR16161616F:
105 return modifier == DRM_FORMAT_MOD_LINEAR ||
106 modifier == I915_FORMAT_MOD_X_TILED;
107 default:
108 return false;
109 }
110 }
111
i9xx_plane_has_fbc(struct intel_display * display,enum i9xx_plane_id i9xx_plane)112 static bool i9xx_plane_has_fbc(struct intel_display *display,
113 enum i9xx_plane_id i9xx_plane)
114 {
115 if (!HAS_FBC(display))
116 return false;
117
118 if (display->platform.broadwell || display->platform.haswell)
119 return i9xx_plane == PLANE_A; /* tied to pipe A */
120 else if (display->platform.ivybridge)
121 return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B ||
122 i9xx_plane == PLANE_C;
123 else if (DISPLAY_VER(display) >= 4)
124 return i9xx_plane == PLANE_A || i9xx_plane == PLANE_B;
125 else
126 return i9xx_plane == PLANE_A;
127 }
128
i9xx_plane_fbc(struct intel_display * display,enum i9xx_plane_id i9xx_plane)129 static struct intel_fbc *i9xx_plane_fbc(struct intel_display *display,
130 enum i9xx_plane_id i9xx_plane)
131 {
132 if (i9xx_plane_has_fbc(display, i9xx_plane))
133 return display->fbc[INTEL_FBC_A];
134 else
135 return NULL;
136 }
137
i9xx_plane_has_windowing(struct intel_plane * plane)138 static bool i9xx_plane_has_windowing(struct intel_plane *plane)
139 {
140 struct intel_display *display = to_intel_display(plane);
141 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
142
143 if (display->platform.cherryview)
144 return i9xx_plane == PLANE_B;
145 else if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
146 return false;
147 else if (DISPLAY_VER(display) == 4)
148 return i9xx_plane == PLANE_C;
149 else
150 return i9xx_plane == PLANE_B ||
151 i9xx_plane == PLANE_C;
152 }
153
i9xx_plane_ctl(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)154 static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
155 const struct intel_plane_state *plane_state)
156 {
157 struct intel_display *display = to_intel_display(plane_state);
158 const struct drm_framebuffer *fb = plane_state->hw.fb;
159 unsigned int rotation = plane_state->hw.rotation;
160 u32 dspcntr;
161
162 dspcntr = DISP_ENABLE;
163
164 if (display->platform.g4x || display->platform.ironlake ||
165 display->platform.sandybridge || display->platform.ivybridge)
166 dspcntr |= DISP_TRICKLE_FEED_DISABLE;
167
168 switch (fb->format->format) {
169 case DRM_FORMAT_C8:
170 dspcntr |= DISP_FORMAT_8BPP;
171 break;
172 case DRM_FORMAT_XRGB1555:
173 dspcntr |= DISP_FORMAT_BGRX555;
174 break;
175 case DRM_FORMAT_ARGB1555:
176 dspcntr |= DISP_FORMAT_BGRA555;
177 break;
178 case DRM_FORMAT_RGB565:
179 dspcntr |= DISP_FORMAT_BGRX565;
180 break;
181 case DRM_FORMAT_XRGB8888:
182 dspcntr |= DISP_FORMAT_BGRX888;
183 break;
184 case DRM_FORMAT_XBGR8888:
185 dspcntr |= DISP_FORMAT_RGBX888;
186 break;
187 case DRM_FORMAT_ARGB8888:
188 dspcntr |= DISP_FORMAT_BGRA888;
189 break;
190 case DRM_FORMAT_ABGR8888:
191 dspcntr |= DISP_FORMAT_RGBA888;
192 break;
193 case DRM_FORMAT_XRGB2101010:
194 dspcntr |= DISP_FORMAT_BGRX101010;
195 break;
196 case DRM_FORMAT_XBGR2101010:
197 dspcntr |= DISP_FORMAT_RGBX101010;
198 break;
199 case DRM_FORMAT_ARGB2101010:
200 dspcntr |= DISP_FORMAT_BGRA101010;
201 break;
202 case DRM_FORMAT_ABGR2101010:
203 dspcntr |= DISP_FORMAT_RGBA101010;
204 break;
205 case DRM_FORMAT_XBGR16161616F:
206 dspcntr |= DISP_FORMAT_RGBX161616;
207 break;
208 default:
209 MISSING_CASE(fb->format->format);
210 return 0;
211 }
212
213 if (DISPLAY_VER(display) >= 4 &&
214 fb->modifier == I915_FORMAT_MOD_X_TILED)
215 dspcntr |= DISP_TILED;
216
217 if (rotation & DRM_MODE_ROTATE_180)
218 dspcntr |= DISP_ROTATE_180;
219
220 if (rotation & DRM_MODE_REFLECT_X)
221 dspcntr |= DISP_MIRROR;
222
223 return dspcntr;
224 }
225
i9xx_check_plane_surface(struct intel_plane_state * plane_state)226 int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
227 {
228 struct intel_display *display = to_intel_display(plane_state);
229 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
230 const struct drm_framebuffer *fb = plane_state->hw.fb;
231 int src_x, src_y, src_w;
232 u32 offset;
233 int ret;
234
235 ret = intel_plane_compute_gtt(plane_state);
236 if (ret)
237 return ret;
238
239 if (!plane_state->uapi.visible)
240 return 0;
241
242 src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
243 src_x = plane_state->uapi.src.x1 >> 16;
244 src_y = plane_state->uapi.src.y1 >> 16;
245
246 /* Undocumented hardware limit on i965/g4x/vlv/chv */
247 if (HAS_GMCH(display) && fb->format->cpp[0] == 8 && src_w > 2048) {
248 drm_dbg_kms(display->drm,
249 "[PLANE:%d:%s] plane too wide (%d) for 64bpp\n",
250 plane->base.base.id, plane->base.name, src_w);
251 return -EINVAL;
252 }
253
254 intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
255
256 if (DISPLAY_VER(display) >= 4)
257 offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
258 plane_state, 0);
259 else
260 offset = 0;
261
262 /*
263 * When using an X-tiled surface the plane starts to
264 * misbehave if the x offset + width exceeds the stride.
265 * hsw/bdw: underrun galore
266 * ilk/snb/ivb: wrap to the next tile row mid scanout
267 * i965/g4x: so far appear immune to this
268 * vlv/chv: TODO check
269 *
270 * Linear surfaces seem to work just fine, even on hsw/bdw
271 * despite them not using the linear offset anymore.
272 */
273 if (DISPLAY_VER(display) >= 4 && fb->modifier == I915_FORMAT_MOD_X_TILED) {
274 unsigned int alignment = plane->min_alignment(plane, fb, 0);
275 int cpp = fb->format->cpp[0];
276
277 while ((src_x + src_w) * cpp > plane_state->view.color_plane[0].mapping_stride) {
278 if (offset == 0) {
279 drm_dbg_kms(display->drm,
280 "[PLANE:%d:%s] unable to find suitable display surface offset due to X-tiling\n",
281 plane->base.base.id, plane->base.name);
282 return -EINVAL;
283 }
284
285 offset = intel_plane_adjust_aligned_offset(&src_x, &src_y, plane_state, 0,
286 offset, offset - alignment);
287 }
288 }
289
290 /*
291 * Put the final coordinates back so that the src
292 * coordinate checks will see the right values.
293 */
294 drm_rect_translate_to(&plane_state->uapi.src,
295 src_x << 16, src_y << 16);
296
297 /* HSW/BDW do this automagically in hardware */
298 if (!display->platform.haswell && !display->platform.broadwell) {
299 unsigned int rotation = plane_state->hw.rotation;
300 int src_w = drm_rect_width(&plane_state->uapi.src) >> 16;
301 int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
302
303 if (rotation & DRM_MODE_ROTATE_180) {
304 src_x += src_w - 1;
305 src_y += src_h - 1;
306 } else if (rotation & DRM_MODE_REFLECT_X) {
307 src_x += src_w - 1;
308 }
309 }
310
311 if (display->platform.haswell || display->platform.broadwell) {
312 drm_WARN_ON(display->drm, src_x > 8191 || src_y > 4095);
313 } else if (DISPLAY_VER(display) >= 4 &&
314 fb->modifier == I915_FORMAT_MOD_X_TILED) {
315 drm_WARN_ON(display->drm, src_x > 4095 || src_y > 4095);
316 }
317
318 plane_state->view.color_plane[0].offset = offset;
319 plane_state->view.color_plane[0].x = src_x;
320 plane_state->view.color_plane[0].y = src_y;
321
322 return 0;
323 }
324
325 static int
i9xx_plane_check(struct intel_crtc_state * crtc_state,struct intel_plane_state * plane_state)326 i9xx_plane_check(struct intel_crtc_state *crtc_state,
327 struct intel_plane_state *plane_state)
328 {
329 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
330 int ret;
331
332 ret = chv_plane_check_rotation(plane_state);
333 if (ret)
334 return ret;
335
336 ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
337 DRM_PLANE_NO_SCALING,
338 DRM_PLANE_NO_SCALING,
339 i9xx_plane_has_windowing(plane));
340 if (ret)
341 return ret;
342
343 ret = i9xx_check_plane_surface(plane_state);
344 if (ret)
345 return ret;
346
347 if (!plane_state->uapi.visible)
348 return 0;
349
350 ret = intel_plane_check_src_coordinates(plane_state);
351 if (ret)
352 return ret;
353
354 plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
355
356 return 0;
357 }
358
i9xx_plane_ctl_crtc(const struct intel_crtc_state * crtc_state)359 static u32 i9xx_plane_ctl_crtc(const struct intel_crtc_state *crtc_state)
360 {
361 struct intel_display *display = to_intel_display(crtc_state);
362 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
363 u32 dspcntr = 0;
364
365 if (crtc_state->gamma_enable)
366 dspcntr |= DISP_PIPE_GAMMA_ENABLE;
367
368 if (crtc_state->csc_enable)
369 dspcntr |= DISP_PIPE_CSC_ENABLE;
370
371 if (DISPLAY_VER(display) < 5)
372 dspcntr |= DISP_PIPE_SEL(crtc->pipe);
373
374 return dspcntr;
375 }
376
i9xx_plane_ratio(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,unsigned int * num,unsigned int * den)377 static void i9xx_plane_ratio(const struct intel_crtc_state *crtc_state,
378 const struct intel_plane_state *plane_state,
379 unsigned int *num, unsigned int *den)
380 {
381 const struct drm_framebuffer *fb = plane_state->hw.fb;
382 unsigned int cpp = fb->format->cpp[0];
383
384 /*
385 * g4x bspec says 64bpp pixel rate can't exceed 80%
386 * of cdclk when the sprite plane is enabled on the
387 * same pipe. ilk/snb bspec says 64bpp pixel rate is
388 * never allowed to exceed 80% of cdclk. Let's just go
389 * with the ilk/snb limit always.
390 */
391 if (cpp == 8) {
392 *num = 10;
393 *den = 8;
394 } else {
395 *num = 1;
396 *den = 1;
397 }
398 }
399
i9xx_plane_min_cdclk(const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)400 static int i9xx_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
401 const struct intel_plane_state *plane_state)
402 {
403 unsigned int pixel_rate;
404 unsigned int num, den;
405
406 /*
407 * Note that crtc_state->pixel_rate accounts for both
408 * horizontal and vertical panel fitter downscaling factors.
409 * Pre-HSW bspec tells us to only consider the horizontal
410 * downscaling factor here. We ignore that and just consider
411 * both for simplicity.
412 */
413 pixel_rate = crtc_state->pixel_rate;
414
415 i9xx_plane_ratio(crtc_state, plane_state, &num, &den);
416
417 /* two pixels per clock with double wide pipe */
418 if (crtc_state->double_wide)
419 den *= 2;
420
421 return DIV_ROUND_UP(pixel_rate * num, den);
422 }
423
i9xx_plane_update_noarm(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)424 static void i9xx_plane_update_noarm(struct intel_dsb *dsb,
425 struct intel_plane *plane,
426 const struct intel_crtc_state *crtc_state,
427 const struct intel_plane_state *plane_state)
428 {
429 struct intel_display *display = to_intel_display(plane);
430 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
431
432 intel_de_write_fw(display, DSPSTRIDE(display, i9xx_plane),
433 plane_state->view.color_plane[0].mapping_stride);
434
435 if (DISPLAY_VER(display) < 4) {
436 int crtc_x = plane_state->uapi.dst.x1;
437 int crtc_y = plane_state->uapi.dst.y1;
438 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
439 int crtc_h = drm_rect_height(&plane_state->uapi.dst);
440
441 /*
442 * PLANE_A doesn't actually have a full window
443 * generator but let's assume we still need to
444 * program whatever is there.
445 */
446 intel_de_write_fw(display, DSPPOS(display, i9xx_plane),
447 DISP_POS_Y(crtc_y) | DISP_POS_X(crtc_x));
448 intel_de_write_fw(display, DSPSIZE(display, i9xx_plane),
449 DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1));
450 }
451 }
452
i9xx_plane_update_arm(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)453 static void i9xx_plane_update_arm(struct intel_dsb *dsb,
454 struct intel_plane *plane,
455 const struct intel_crtc_state *crtc_state,
456 const struct intel_plane_state *plane_state)
457 {
458 struct intel_display *display = to_intel_display(plane);
459 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
460 int x = plane_state->view.color_plane[0].x;
461 int y = plane_state->view.color_plane[0].y;
462 u32 dspcntr, dspaddr_offset, linear_offset;
463
464 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
465
466 /* see intel_plane_atomic_calc_changes() */
467 if (plane->need_async_flip_toggle_wa &&
468 crtc_state->async_flip_planes & BIT(plane->id))
469 dspcntr |= DISP_ASYNC_FLIP;
470
471 linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
472
473 if (DISPLAY_VER(display) >= 4)
474 dspaddr_offset = plane_state->view.color_plane[0].offset;
475 else
476 dspaddr_offset = linear_offset;
477
478 if (display->platform.cherryview && i9xx_plane == PLANE_B) {
479 int crtc_x = plane_state->uapi.dst.x1;
480 int crtc_y = plane_state->uapi.dst.y1;
481 int crtc_w = drm_rect_width(&plane_state->uapi.dst);
482 int crtc_h = drm_rect_height(&plane_state->uapi.dst);
483
484 intel_de_write_fw(display, PRIMPOS(display, i9xx_plane),
485 PRIM_POS_Y(crtc_y) | PRIM_POS_X(crtc_x));
486 intel_de_write_fw(display, PRIMSIZE(display, i9xx_plane),
487 PRIM_HEIGHT(crtc_h - 1) | PRIM_WIDTH(crtc_w - 1));
488 intel_de_write_fw(display,
489 PRIMCNSTALPHA(display, i9xx_plane), 0);
490 }
491
492 if (display->platform.haswell || display->platform.broadwell) {
493 intel_de_write_fw(display, DSPOFFSET(display, i9xx_plane),
494 DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
495 } else if (DISPLAY_VER(display) >= 4) {
496 intel_de_write_fw(display, DSPLINOFF(display, i9xx_plane),
497 linear_offset);
498 intel_de_write_fw(display, DSPTILEOFF(display, i9xx_plane),
499 DISP_OFFSET_Y(y) | DISP_OFFSET_X(x));
500 }
501
502 /*
503 * The control register self-arms if the plane was previously
504 * disabled. Try to make the plane enable atomic by writing
505 * the control register just before the surface register.
506 */
507 intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
508
509 if (DISPLAY_VER(display) >= 4)
510 intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
511 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
512 else
513 intel_de_write_fw(display, DSPADDR(display, i9xx_plane),
514 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
515 }
516
i830_plane_update_arm(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state)517 static void i830_plane_update_arm(struct intel_dsb *dsb,
518 struct intel_plane *plane,
519 const struct intel_crtc_state *crtc_state,
520 const struct intel_plane_state *plane_state)
521 {
522 /*
523 * On i830/i845 all registers are self-arming [ALM040].
524 *
525 * Additional breakage on i830 causes register reads to return
526 * the last latched value instead of the last written value [ALM026].
527 */
528 i9xx_plane_update_noarm(dsb, plane, crtc_state, plane_state);
529 i9xx_plane_update_arm(dsb, plane, crtc_state, plane_state);
530 }
531
i9xx_plane_disable_arm(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state)532 static void i9xx_plane_disable_arm(struct intel_dsb *dsb,
533 struct intel_plane *plane,
534 const struct intel_crtc_state *crtc_state)
535 {
536 struct intel_display *display = to_intel_display(plane);
537 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
538 u32 dspcntr;
539
540 /*
541 * DSPCNTR pipe gamma enable on g4x+ and pipe csc
542 * enable on ilk+ affect the pipe bottom color as
543 * well, so we must configure them even if the plane
544 * is disabled.
545 *
546 * On pre-g4x there is no way to gamma correct the
547 * pipe bottom color but we'll keep on doing this
548 * anyway so that the crtc state readout works correctly.
549 */
550 dspcntr = i9xx_plane_ctl_crtc(crtc_state);
551
552 intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
553
554 if (DISPLAY_VER(display) >= 4)
555 intel_de_write_fw(display, DSPSURF(display, i9xx_plane), 0);
556 else
557 intel_de_write_fw(display, DSPADDR(display, i9xx_plane), 0);
558 }
559
g4x_primary_capture_error(struct intel_crtc * crtc,struct intel_plane * plane,struct intel_plane_error * error)560 static void g4x_primary_capture_error(struct intel_crtc *crtc,
561 struct intel_plane *plane,
562 struct intel_plane_error *error)
563 {
564 struct intel_display *display = to_intel_display(plane);
565 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
566
567 error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
568 error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane));
569 error->surflive = intel_de_read(display, DSPSURFLIVE(display, i9xx_plane));
570 }
571
i965_plane_capture_error(struct intel_crtc * crtc,struct intel_plane * plane,struct intel_plane_error * error)572 static void i965_plane_capture_error(struct intel_crtc *crtc,
573 struct intel_plane *plane,
574 struct intel_plane_error *error)
575 {
576 struct intel_display *display = to_intel_display(plane);
577 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
578
579 error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
580 error->surf = intel_de_read(display, DSPSURF(display, i9xx_plane));
581 }
582
i8xx_plane_capture_error(struct intel_crtc * crtc,struct intel_plane * plane,struct intel_plane_error * error)583 static void i8xx_plane_capture_error(struct intel_crtc *crtc,
584 struct intel_plane *plane,
585 struct intel_plane_error *error)
586 {
587 struct intel_display *display = to_intel_display(plane);
588 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
589
590 error->ctl = intel_de_read(display, DSPCNTR(display, i9xx_plane));
591 error->surf = intel_de_read(display, DSPADDR(display, i9xx_plane));
592 }
593
594 static void
g4x_primary_async_flip(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,bool async_flip)595 g4x_primary_async_flip(struct intel_dsb *dsb,
596 struct intel_plane *plane,
597 const struct intel_crtc_state *crtc_state,
598 const struct intel_plane_state *plane_state,
599 bool async_flip)
600 {
601 struct intel_display *display = to_intel_display(plane);
602 u32 dspcntr = plane_state->ctl | i9xx_plane_ctl_crtc(crtc_state);
603 u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
604 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
605
606 if (async_flip)
607 dspcntr |= DISP_ASYNC_FLIP;
608
609 intel_de_write_fw(display, DSPCNTR(display, i9xx_plane), dspcntr);
610
611 intel_de_write_fw(display, DSPSURF(display, i9xx_plane),
612 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
613 }
614
615 static void
vlv_primary_async_flip(struct intel_dsb * dsb,struct intel_plane * plane,const struct intel_crtc_state * crtc_state,const struct intel_plane_state * plane_state,bool async_flip)616 vlv_primary_async_flip(struct intel_dsb *dsb,
617 struct intel_plane *plane,
618 const struct intel_crtc_state *crtc_state,
619 const struct intel_plane_state *plane_state,
620 bool async_flip)
621 {
622 struct intel_display *display = to_intel_display(plane);
623 u32 dspaddr_offset = plane_state->view.color_plane[0].offset;
624 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
625
626 intel_de_write_fw(display, DSPADDR_VLV(display, i9xx_plane),
627 intel_plane_ggtt_offset(plane_state) + dspaddr_offset);
628 }
629
630 static void
bdw_primary_enable_flip_done(struct intel_plane * plane)631 bdw_primary_enable_flip_done(struct intel_plane *plane)
632 {
633 struct drm_i915_private *i915 = to_i915(plane->base.dev);
634 enum pipe pipe = plane->pipe;
635
636 spin_lock_irq(&i915->irq_lock);
637 bdw_enable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
638 spin_unlock_irq(&i915->irq_lock);
639 }
640
641 static void
bdw_primary_disable_flip_done(struct intel_plane * plane)642 bdw_primary_disable_flip_done(struct intel_plane *plane)
643 {
644 struct drm_i915_private *i915 = to_i915(plane->base.dev);
645 enum pipe pipe = plane->pipe;
646
647 spin_lock_irq(&i915->irq_lock);
648 bdw_disable_pipe_irq(i915, pipe, GEN8_PIPE_PRIMARY_FLIP_DONE);
649 spin_unlock_irq(&i915->irq_lock);
650 }
651
652 static void
ivb_primary_enable_flip_done(struct intel_plane * plane)653 ivb_primary_enable_flip_done(struct intel_plane *plane)
654 {
655 struct drm_i915_private *i915 = to_i915(plane->base.dev);
656
657 spin_lock_irq(&i915->irq_lock);
658 ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
659 spin_unlock_irq(&i915->irq_lock);
660 }
661
662 static void
ivb_primary_disable_flip_done(struct intel_plane * plane)663 ivb_primary_disable_flip_done(struct intel_plane *plane)
664 {
665 struct drm_i915_private *i915 = to_i915(plane->base.dev);
666
667 spin_lock_irq(&i915->irq_lock);
668 ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE_IVB(plane->i9xx_plane));
669 spin_unlock_irq(&i915->irq_lock);
670 }
671
672 static void
ilk_primary_enable_flip_done(struct intel_plane * plane)673 ilk_primary_enable_flip_done(struct intel_plane *plane)
674 {
675 struct drm_i915_private *i915 = to_i915(plane->base.dev);
676
677 spin_lock_irq(&i915->irq_lock);
678 ilk_enable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
679 spin_unlock_irq(&i915->irq_lock);
680 }
681
682 static void
ilk_primary_disable_flip_done(struct intel_plane * plane)683 ilk_primary_disable_flip_done(struct intel_plane *plane)
684 {
685 struct drm_i915_private *i915 = to_i915(plane->base.dev);
686
687 spin_lock_irq(&i915->irq_lock);
688 ilk_disable_display_irq(i915, DE_PLANE_FLIP_DONE(plane->i9xx_plane));
689 spin_unlock_irq(&i915->irq_lock);
690 }
691
692 static void
vlv_primary_enable_flip_done(struct intel_plane * plane)693 vlv_primary_enable_flip_done(struct intel_plane *plane)
694 {
695 struct drm_i915_private *i915 = to_i915(plane->base.dev);
696 enum pipe pipe = plane->pipe;
697
698 spin_lock_irq(&i915->irq_lock);
699 i915_enable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
700 spin_unlock_irq(&i915->irq_lock);
701 }
702
703 static void
vlv_primary_disable_flip_done(struct intel_plane * plane)704 vlv_primary_disable_flip_done(struct intel_plane *plane)
705 {
706 struct drm_i915_private *i915 = to_i915(plane->base.dev);
707 enum pipe pipe = plane->pipe;
708
709 spin_lock_irq(&i915->irq_lock);
710 i915_disable_pipestat(i915, pipe, PLANE_FLIP_DONE_INT_STATUS_VLV);
711 spin_unlock_irq(&i915->irq_lock);
712 }
713
i9xx_plane_can_async_flip(u64 modifier)714 static bool i9xx_plane_can_async_flip(u64 modifier)
715 {
716 return modifier == I915_FORMAT_MOD_X_TILED;
717 }
718
i9xx_plane_get_hw_state(struct intel_plane * plane,enum pipe * pipe)719 static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
720 enum pipe *pipe)
721 {
722 struct intel_display *display = to_intel_display(plane);
723 enum intel_display_power_domain power_domain;
724 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
725 intel_wakeref_t wakeref;
726 bool ret;
727 u32 val;
728
729 /*
730 * Not 100% correct for planes that can move between pipes,
731 * but that's only the case for gen2-4 which don't have any
732 * display power wells.
733 */
734 power_domain = POWER_DOMAIN_PIPE(plane->pipe);
735 wakeref = intel_display_power_get_if_enabled(display, power_domain);
736 if (!wakeref)
737 return false;
738
739 val = intel_de_read(display, DSPCNTR(display, i9xx_plane));
740
741 ret = val & DISP_ENABLE;
742
743 if (DISPLAY_VER(display) >= 5)
744 *pipe = plane->pipe;
745 else
746 *pipe = REG_FIELD_GET(DISP_PIPE_SEL_MASK, val);
747
748 intel_display_power_put(display, power_domain, wakeref);
749
750 return ret;
751 }
752
753 static unsigned int
hsw_primary_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)754 hsw_primary_max_stride(struct intel_plane *plane,
755 u32 pixel_format, u64 modifier,
756 unsigned int rotation)
757 {
758 const struct drm_format_info *info = drm_format_info(pixel_format);
759 int cpp = info->cpp[0];
760
761 /* Limit to 8k pixels to guarantee OFFSET.x doesn't get too big. */
762 return min(8192 * cpp, 32 * 1024);
763 }
764
765 static unsigned int
ilk_primary_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)766 ilk_primary_max_stride(struct intel_plane *plane,
767 u32 pixel_format, u64 modifier,
768 unsigned int rotation)
769 {
770 const struct drm_format_info *info = drm_format_info(pixel_format);
771 int cpp = info->cpp[0];
772
773 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
774 if (modifier == I915_FORMAT_MOD_X_TILED)
775 return min(4096 * cpp, 32 * 1024);
776 else
777 return 32 * 1024;
778 }
779
780 unsigned int
i965_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)781 i965_plane_max_stride(struct intel_plane *plane,
782 u32 pixel_format, u64 modifier,
783 unsigned int rotation)
784 {
785 const struct drm_format_info *info = drm_format_info(pixel_format);
786 int cpp = info->cpp[0];
787
788 /* Limit to 4k pixels to guarantee TILEOFF.x doesn't get too big. */
789 if (modifier == I915_FORMAT_MOD_X_TILED)
790 return min(4096 * cpp, 16 * 1024);
791 else
792 return 32 * 1024;
793 }
794
795 static unsigned int
i915_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)796 i915_plane_max_stride(struct intel_plane *plane,
797 u32 pixel_format, u64 modifier,
798 unsigned int rotation)
799 {
800 if (modifier == I915_FORMAT_MOD_X_TILED)
801 return 8 * 1024;
802 else
803 return 16 * 1024;
804 }
805
806 static unsigned int
i8xx_plane_max_stride(struct intel_plane * plane,u32 pixel_format,u64 modifier,unsigned int rotation)807 i8xx_plane_max_stride(struct intel_plane *plane,
808 u32 pixel_format, u64 modifier,
809 unsigned int rotation)
810 {
811 if (plane->i9xx_plane == PLANE_C)
812 return 4 * 1024;
813 else
814 return 8 * 1024;
815 }
816
vlv_plane_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)817 unsigned int vlv_plane_min_alignment(struct intel_plane *plane,
818 const struct drm_framebuffer *fb,
819 int color_plane)
820 {
821 struct intel_display *display = to_intel_display(plane);
822
823 if (intel_plane_can_async_flip(plane, fb->modifier))
824 return 256 * 1024;
825
826 /* FIXME undocumented so not sure what's actually needed */
827 if (intel_scanout_needs_vtd_wa(display))
828 return 256 * 1024;
829
830 switch (fb->modifier) {
831 case I915_FORMAT_MOD_X_TILED:
832 return 4 * 1024;
833 case DRM_FORMAT_MOD_LINEAR:
834 return 128 * 1024;
835 default:
836 MISSING_CASE(fb->modifier);
837 return 0;
838 }
839 }
840
g4x_primary_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)841 static unsigned int g4x_primary_min_alignment(struct intel_plane *plane,
842 const struct drm_framebuffer *fb,
843 int color_plane)
844 {
845 struct intel_display *display = to_intel_display(plane);
846
847 if (intel_plane_can_async_flip(plane, fb->modifier))
848 return 256 * 1024;
849
850 if (intel_scanout_needs_vtd_wa(display))
851 return 256 * 1024;
852
853 switch (fb->modifier) {
854 case I915_FORMAT_MOD_X_TILED:
855 case DRM_FORMAT_MOD_LINEAR:
856 return 4 * 1024;
857 default:
858 MISSING_CASE(fb->modifier);
859 return 0;
860 }
861 }
862
i965_plane_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)863 static unsigned int i965_plane_min_alignment(struct intel_plane *plane,
864 const struct drm_framebuffer *fb,
865 int color_plane)
866 {
867 switch (fb->modifier) {
868 case I915_FORMAT_MOD_X_TILED:
869 return 4 * 1024;
870 case DRM_FORMAT_MOD_LINEAR:
871 return 128 * 1024;
872 default:
873 MISSING_CASE(fb->modifier);
874 return 0;
875 }
876 }
877
i9xx_plane_min_alignment(struct intel_plane * plane,const struct drm_framebuffer * fb,int color_plane)878 static unsigned int i9xx_plane_min_alignment(struct intel_plane *plane,
879 const struct drm_framebuffer *fb,
880 int color_plane)
881 {
882 return 0;
883 }
884
885 static const struct drm_plane_funcs i965_plane_funcs = {
886 .update_plane = drm_atomic_helper_update_plane,
887 .disable_plane = drm_atomic_helper_disable_plane,
888 .destroy = intel_plane_destroy,
889 .atomic_duplicate_state = intel_plane_duplicate_state,
890 .atomic_destroy_state = intel_plane_destroy_state,
891 .format_mod_supported = i965_plane_format_mod_supported,
892 };
893
894 static const struct drm_plane_funcs i8xx_plane_funcs = {
895 .update_plane = drm_atomic_helper_update_plane,
896 .disable_plane = drm_atomic_helper_disable_plane,
897 .destroy = intel_plane_destroy,
898 .atomic_duplicate_state = intel_plane_duplicate_state,
899 .atomic_destroy_state = intel_plane_destroy_state,
900 .format_mod_supported = i8xx_plane_format_mod_supported,
901 };
902
903 struct intel_plane *
intel_primary_plane_create(struct intel_display * display,enum pipe pipe)904 intel_primary_plane_create(struct intel_display *display, enum pipe pipe)
905 {
906 struct intel_plane *plane;
907 const struct drm_plane_funcs *plane_funcs;
908 unsigned int supported_rotations;
909 const u64 *modifiers;
910 const u32 *formats;
911 int num_formats;
912 int ret, zpos;
913
914 plane = intel_plane_alloc();
915 if (IS_ERR(plane))
916 return plane;
917
918 plane->pipe = pipe;
919 /*
920 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
921 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
922 */
923 if (HAS_FBC(display) && DISPLAY_VER(display) < 4 &&
924 INTEL_NUM_PIPES(display) == 2)
925 plane->i9xx_plane = (enum i9xx_plane_id) !pipe;
926 else
927 plane->i9xx_plane = (enum i9xx_plane_id) pipe;
928 plane->id = PLANE_PRIMARY;
929 plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, plane->id);
930
931 intel_fbc_add_plane(i9xx_plane_fbc(display, plane->i9xx_plane), plane);
932
933 if (display->platform.valleyview || display->platform.cherryview) {
934 formats = vlv_primary_formats;
935 num_formats = ARRAY_SIZE(vlv_primary_formats);
936 } else if (DISPLAY_VER(display) >= 4) {
937 /*
938 * WaFP16GammaEnabling:ivb
939 * "Workaround : When using the 64-bit format, the plane
940 * output on each color channel has one quarter amplitude.
941 * It can be brought up to full amplitude by using pipe
942 * gamma correction or pipe color space conversion to
943 * multiply the plane output by four."
944 *
945 * There is no dedicated plane gamma for the primary plane,
946 * and using the pipe gamma/csc could conflict with other
947 * planes, so we choose not to expose fp16 on IVB primary
948 * planes. HSW primary planes no longer have this problem.
949 */
950 if (display->platform.ivybridge) {
951 formats = ivb_primary_formats;
952 num_formats = ARRAY_SIZE(ivb_primary_formats);
953 } else {
954 formats = i965_primary_formats;
955 num_formats = ARRAY_SIZE(i965_primary_formats);
956 }
957 } else {
958 formats = i8xx_primary_formats;
959 num_formats = ARRAY_SIZE(i8xx_primary_formats);
960 }
961
962 if (DISPLAY_VER(display) >= 4)
963 plane_funcs = &i965_plane_funcs;
964 else
965 plane_funcs = &i8xx_plane_funcs;
966
967 if (display->platform.valleyview || display->platform.cherryview)
968 plane->min_cdclk = vlv_plane_min_cdclk;
969 else if (display->platform.broadwell || display->platform.haswell)
970 plane->min_cdclk = hsw_plane_min_cdclk;
971 else if (display->platform.ivybridge)
972 plane->min_cdclk = ivb_plane_min_cdclk;
973 else
974 plane->min_cdclk = i9xx_plane_min_cdclk;
975
976 if (HAS_GMCH(display)) {
977 if (DISPLAY_VER(display) >= 4)
978 plane->max_stride = i965_plane_max_stride;
979 else if (DISPLAY_VER(display) == 3)
980 plane->max_stride = i915_plane_max_stride;
981 else
982 plane->max_stride = i8xx_plane_max_stride;
983 } else {
984 if (display->platform.broadwell || display->platform.haswell)
985 plane->max_stride = hsw_primary_max_stride;
986 else
987 plane->max_stride = ilk_primary_max_stride;
988 }
989
990 if (display->platform.valleyview || display->platform.cherryview)
991 plane->min_alignment = vlv_plane_min_alignment;
992 else if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
993 plane->min_alignment = g4x_primary_min_alignment;
994 else if (DISPLAY_VER(display) == 4)
995 plane->min_alignment = i965_plane_min_alignment;
996 else
997 plane->min_alignment = i9xx_plane_min_alignment;
998
999 /* FIXME undocumented for VLV/CHV so not sure what's actually needed */
1000 if (intel_scanout_needs_vtd_wa(display))
1001 plane->vtd_guard = 128;
1002
1003 if (display->platform.i830 || display->platform.i845g) {
1004 plane->update_arm = i830_plane_update_arm;
1005 } else {
1006 plane->update_noarm = i9xx_plane_update_noarm;
1007 plane->update_arm = i9xx_plane_update_arm;
1008 }
1009 plane->disable_arm = i9xx_plane_disable_arm;
1010 plane->get_hw_state = i9xx_plane_get_hw_state;
1011 plane->check_plane = i9xx_plane_check;
1012
1013 if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
1014 plane->capture_error = g4x_primary_capture_error;
1015 else if (DISPLAY_VER(display) >= 4)
1016 plane->capture_error = i965_plane_capture_error;
1017 else
1018 plane->capture_error = i8xx_plane_capture_error;
1019
1020 if (HAS_ASYNC_FLIPS(display)) {
1021 if (display->platform.valleyview || display->platform.cherryview) {
1022 plane->async_flip = vlv_primary_async_flip;
1023 plane->enable_flip_done = vlv_primary_enable_flip_done;
1024 plane->disable_flip_done = vlv_primary_disable_flip_done;
1025 plane->can_async_flip = i9xx_plane_can_async_flip;
1026 } else if (display->platform.broadwell) {
1027 plane->need_async_flip_toggle_wa = true;
1028 plane->async_flip = g4x_primary_async_flip;
1029 plane->enable_flip_done = bdw_primary_enable_flip_done;
1030 plane->disable_flip_done = bdw_primary_disable_flip_done;
1031 plane->can_async_flip = i9xx_plane_can_async_flip;
1032 } else if (DISPLAY_VER(display) >= 7) {
1033 plane->async_flip = g4x_primary_async_flip;
1034 plane->enable_flip_done = ivb_primary_enable_flip_done;
1035 plane->disable_flip_done = ivb_primary_disable_flip_done;
1036 plane->can_async_flip = i9xx_plane_can_async_flip;
1037 } else if (DISPLAY_VER(display) >= 5) {
1038 plane->async_flip = g4x_primary_async_flip;
1039 plane->enable_flip_done = ilk_primary_enable_flip_done;
1040 plane->disable_flip_done = ilk_primary_disable_flip_done;
1041 plane->can_async_flip = i9xx_plane_can_async_flip;
1042 }
1043 }
1044
1045 modifiers = intel_fb_plane_get_modifiers(display, INTEL_PLANE_CAP_TILING_X);
1046
1047 if (DISPLAY_VER(display) >= 5 || display->platform.g4x)
1048 ret = drm_universal_plane_init(display->drm, &plane->base,
1049 0, plane_funcs,
1050 formats, num_formats,
1051 modifiers,
1052 DRM_PLANE_TYPE_PRIMARY,
1053 "primary %c", pipe_name(pipe));
1054 else
1055 ret = drm_universal_plane_init(display->drm, &plane->base,
1056 0, plane_funcs,
1057 formats, num_formats,
1058 modifiers,
1059 DRM_PLANE_TYPE_PRIMARY,
1060 "plane %c",
1061 plane_name(plane->i9xx_plane));
1062
1063 kfree(modifiers);
1064
1065 if (ret)
1066 goto fail;
1067
1068 if (display->platform.cherryview && pipe == PIPE_B) {
1069 supported_rotations =
1070 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180 |
1071 DRM_MODE_REFLECT_X;
1072 } else if (DISPLAY_VER(display) >= 4) {
1073 supported_rotations =
1074 DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
1075 } else {
1076 supported_rotations = DRM_MODE_ROTATE_0;
1077 }
1078
1079 if (DISPLAY_VER(display) >= 4)
1080 drm_plane_create_rotation_property(&plane->base,
1081 DRM_MODE_ROTATE_0,
1082 supported_rotations);
1083
1084 zpos = 0;
1085 drm_plane_create_zpos_immutable_property(&plane->base, zpos);
1086
1087 intel_plane_helper_add(plane);
1088
1089 return plane;
1090
1091 fail:
1092 intel_plane_free(plane);
1093
1094 return ERR_PTR(ret);
1095 }
1096
i9xx_format_to_fourcc(int format)1097 static int i9xx_format_to_fourcc(int format)
1098 {
1099 switch (format) {
1100 case DISP_FORMAT_8BPP:
1101 return DRM_FORMAT_C8;
1102 case DISP_FORMAT_BGRA555:
1103 return DRM_FORMAT_ARGB1555;
1104 case DISP_FORMAT_BGRX555:
1105 return DRM_FORMAT_XRGB1555;
1106 case DISP_FORMAT_BGRX565:
1107 return DRM_FORMAT_RGB565;
1108 default:
1109 case DISP_FORMAT_BGRX888:
1110 return DRM_FORMAT_XRGB8888;
1111 case DISP_FORMAT_RGBX888:
1112 return DRM_FORMAT_XBGR8888;
1113 case DISP_FORMAT_BGRA888:
1114 return DRM_FORMAT_ARGB8888;
1115 case DISP_FORMAT_RGBA888:
1116 return DRM_FORMAT_ABGR8888;
1117 case DISP_FORMAT_BGRX101010:
1118 return DRM_FORMAT_XRGB2101010;
1119 case DISP_FORMAT_RGBX101010:
1120 return DRM_FORMAT_XBGR2101010;
1121 case DISP_FORMAT_BGRA101010:
1122 return DRM_FORMAT_ARGB2101010;
1123 case DISP_FORMAT_RGBA101010:
1124 return DRM_FORMAT_ABGR2101010;
1125 case DISP_FORMAT_RGBX161616:
1126 return DRM_FORMAT_XBGR16161616F;
1127 }
1128 }
1129
1130 void
i9xx_get_initial_plane_config(struct intel_crtc * crtc,struct intel_initial_plane_config * plane_config)1131 i9xx_get_initial_plane_config(struct intel_crtc *crtc,
1132 struct intel_initial_plane_config *plane_config)
1133 {
1134 struct intel_display *display = to_intel_display(crtc);
1135 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
1136 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
1137 enum pipe pipe;
1138 u32 val, base, offset;
1139 int fourcc, pixel_format;
1140 unsigned int aligned_height;
1141 struct drm_framebuffer *fb;
1142 struct intel_framebuffer *intel_fb;
1143
1144 if (!plane->get_hw_state(plane, &pipe))
1145 return;
1146
1147 drm_WARN_ON(display->drm, pipe != crtc->pipe);
1148
1149 intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
1150 if (!intel_fb) {
1151 drm_dbg_kms(display->drm, "failed to alloc fb\n");
1152 return;
1153 }
1154
1155 fb = &intel_fb->base;
1156
1157 fb->dev = display->drm;
1158
1159 val = intel_de_read(display, DSPCNTR(display, i9xx_plane));
1160
1161 if (DISPLAY_VER(display) >= 4) {
1162 if (val & DISP_TILED) {
1163 plane_config->tiling = I915_TILING_X;
1164 fb->modifier = I915_FORMAT_MOD_X_TILED;
1165 }
1166
1167 if (val & DISP_ROTATE_180)
1168 plane_config->rotation = DRM_MODE_ROTATE_180;
1169 }
1170
1171 if (display->platform.cherryview &&
1172 pipe == PIPE_B && val & DISP_MIRROR)
1173 plane_config->rotation |= DRM_MODE_REFLECT_X;
1174
1175 pixel_format = val & DISP_FORMAT_MASK;
1176 fourcc = i9xx_format_to_fourcc(pixel_format);
1177 fb->format = drm_format_info(fourcc);
1178
1179 if (display->platform.haswell || display->platform.broadwell) {
1180 offset = intel_de_read(display,
1181 DSPOFFSET(display, i9xx_plane));
1182 base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK;
1183 } else if (DISPLAY_VER(display) >= 4) {
1184 if (plane_config->tiling)
1185 offset = intel_de_read(display,
1186 DSPTILEOFF(display, i9xx_plane));
1187 else
1188 offset = intel_de_read(display,
1189 DSPLINOFF(display, i9xx_plane));
1190 base = intel_de_read(display, DSPSURF(display, i9xx_plane)) & DISP_ADDR_MASK;
1191 } else {
1192 offset = 0;
1193 base = intel_de_read(display, DSPADDR(display, i9xx_plane));
1194 }
1195 plane_config->base = base;
1196
1197 drm_WARN_ON(display->drm, offset != 0);
1198
1199 val = intel_de_read(display, PIPESRC(display, pipe));
1200 fb->width = REG_FIELD_GET(PIPESRC_WIDTH_MASK, val) + 1;
1201 fb->height = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, val) + 1;
1202
1203 val = intel_de_read(display, DSPSTRIDE(display, i9xx_plane));
1204 fb->pitches[0] = val & 0xffffffc0;
1205
1206 aligned_height = intel_fb_align_height(fb, 0, fb->height);
1207
1208 plane_config->size = fb->pitches[0] * aligned_height;
1209
1210 drm_dbg_kms(display->drm,
1211 "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
1212 crtc->base.base.id, crtc->base.name,
1213 plane->base.base.id, plane->base.name,
1214 fb->width, fb->height, fb->format->cpp[0] * 8,
1215 base, fb->pitches[0], plane_config->size);
1216
1217 plane_config->fb = intel_fb;
1218 }
1219
i9xx_fixup_initial_plane_config(struct intel_crtc * crtc,const struct intel_initial_plane_config * plane_config)1220 bool i9xx_fixup_initial_plane_config(struct intel_crtc *crtc,
1221 const struct intel_initial_plane_config *plane_config)
1222 {
1223 struct intel_display *display = to_intel_display(crtc);
1224 struct intel_plane *plane = to_intel_plane(crtc->base.primary);
1225 const struct intel_plane_state *plane_state =
1226 to_intel_plane_state(plane->base.state);
1227 enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
1228 u32 base;
1229
1230 if (!plane_state->uapi.visible)
1231 return false;
1232
1233 base = intel_plane_ggtt_offset(plane_state);
1234
1235 /*
1236 * We may have moved the surface to a different
1237 * part of ggtt, make the plane aware of that.
1238 */
1239 if (plane_config->base == base)
1240 return false;
1241
1242 if (DISPLAY_VER(display) >= 4)
1243 intel_de_write(display, DSPSURF(display, i9xx_plane), base);
1244 else
1245 intel_de_write(display, DSPADDR(display, i9xx_plane), base);
1246
1247 return true;
1248 }
1249