1
2
3
4
5#include "intel_de.h"
6#include "intel_display_types.h"
7#include "skl_scaler.h"
8#include "skl_universal_plane.h"
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50static u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
51{
52 int phase = -0x8000;
53 u16 trip = 0;
54
55 if (chroma_cosited)
56 phase += (sub - 1) * 0x8000 / sub;
57
58 phase += scale / (2 * sub);
59
60
61
62
63
64
65 WARN_ON(phase < -0x8000 || phase > 0x18000);
66
67 if (phase < 0)
68 phase = 0x10000 + phase;
69 else
70 trip = PS_PHASE_TRIP;
71
72 return ((phase >> 2) & PS_PHASE_MASK) | trip;
73}
74
75#define SKL_MIN_SRC_W 8
76#define SKL_MAX_SRC_W 4096
77#define SKL_MIN_SRC_H 8
78#define SKL_MAX_SRC_H 4096
79#define SKL_MIN_DST_W 8
80#define SKL_MAX_DST_W 4096
81#define SKL_MIN_DST_H 8
82#define SKL_MAX_DST_H 4096
83#define ICL_MAX_SRC_W 5120
84#define ICL_MAX_SRC_H 4096
85#define ICL_MAX_DST_W 5120
86#define ICL_MAX_DST_H 4096
87#define SKL_MIN_YUV_420_SRC_W 16
88#define SKL_MIN_YUV_420_SRC_H 16
89
90static int
91skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
92 unsigned int scaler_user, int *scaler_id,
93 int src_w, int src_h, int dst_w, int dst_h,
94 const struct drm_format_info *format,
95 u64 modifier, bool need_scaler)
96{
97 struct intel_crtc_scaler_state *scaler_state =
98 &crtc_state->scaler_state;
99 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
100 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
101 const struct drm_display_mode *adjusted_mode =
102 &crtc_state->hw.adjusted_mode;
103
104
105
106
107
108
109 if (src_w != dst_w || src_h != dst_h)
110 need_scaler = true;
111
112
113
114
115
116
117
118 if (DISPLAY_VER(dev_priv) >= 9 && crtc_state->hw.enable &&
119 need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
120 drm_dbg_kms(&dev_priv->drm,
121 "Pipe/Plane scaling not supported with IF-ID mode\n");
122 return -EINVAL;
123 }
124
125
126
127
128
129
130
131
132
133
134
135 if (force_detach || !need_scaler) {
136 if (*scaler_id >= 0) {
137 scaler_state->scaler_users &= ~(1 << scaler_user);
138 scaler_state->scalers[*scaler_id].in_use = 0;
139
140 drm_dbg_kms(&dev_priv->drm,
141 "scaler_user index %u.%u: "
142 "Staged freeing scaler id %d scaler_users = 0x%x\n",
143 crtc->pipe, scaler_user, *scaler_id,
144 scaler_state->scaler_users);
145 *scaler_id = -1;
146 }
147 return 0;
148 }
149
150 if (format && intel_format_info_is_yuv_semiplanar(format, modifier) &&
151 (src_h < SKL_MIN_YUV_420_SRC_H || src_w < SKL_MIN_YUV_420_SRC_W)) {
152 drm_dbg_kms(&dev_priv->drm,
153 "Planar YUV: src dimensions not met\n");
154 return -EINVAL;
155 }
156
157
158 if (src_w < SKL_MIN_SRC_W || src_h < SKL_MIN_SRC_H ||
159 dst_w < SKL_MIN_DST_W || dst_h < SKL_MIN_DST_H ||
160 (DISPLAY_VER(dev_priv) >= 11 &&
161 (src_w > ICL_MAX_SRC_W || src_h > ICL_MAX_SRC_H ||
162 dst_w > ICL_MAX_DST_W || dst_h > ICL_MAX_DST_H)) ||
163 (DISPLAY_VER(dev_priv) < 11 &&
164 (src_w > SKL_MAX_SRC_W || src_h > SKL_MAX_SRC_H ||
165 dst_w > SKL_MAX_DST_W || dst_h > SKL_MAX_DST_H))) {
166 drm_dbg_kms(&dev_priv->drm,
167 "scaler_user index %u.%u: src %ux%u dst %ux%u "
168 "size is out of scaler range\n",
169 crtc->pipe, scaler_user, src_w, src_h,
170 dst_w, dst_h);
171 return -EINVAL;
172 }
173
174
175 scaler_state->scaler_users |= (1 << scaler_user);
176 drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: "
177 "staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n",
178 crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h,
179 scaler_state->scaler_users);
180
181 return 0;
182}
183
184int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state)
185{
186 const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode;
187 int width, height;
188
189 if (crtc_state->pch_pfit.enabled) {
190 width = drm_rect_width(&crtc_state->pch_pfit.dst);
191 height = drm_rect_height(&crtc_state->pch_pfit.dst);
192 } else {
193 width = pipe_mode->crtc_hdisplay;
194 height = pipe_mode->crtc_vdisplay;
195 }
196 return skl_update_scaler(crtc_state, !crtc_state->hw.active,
197 SKL_CRTC_INDEX,
198 &crtc_state->scaler_state.scaler_id,
199 crtc_state->pipe_src_w, crtc_state->pipe_src_h,
200 width, height, NULL, 0,
201 crtc_state->pch_pfit.enabled);
202}
203
204
205
206
207
208
209
210
211
212
213int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
214 struct intel_plane_state *plane_state)
215{
216 struct intel_plane *intel_plane =
217 to_intel_plane(plane_state->uapi.plane);
218 struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
219 struct drm_framebuffer *fb = plane_state->hw.fb;
220 int ret;
221 bool force_detach = !fb || !plane_state->uapi.visible;
222 bool need_scaler = false;
223
224
225 if (!icl_is_hdr_plane(dev_priv, intel_plane->id) &&
226 fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier))
227 need_scaler = true;
228
229 ret = skl_update_scaler(crtc_state, force_detach,
230 drm_plane_index(&intel_plane->base),
231 &plane_state->scaler_id,
232 drm_rect_width(&plane_state->uapi.src) >> 16,
233 drm_rect_height(&plane_state->uapi.src) >> 16,
234 drm_rect_width(&plane_state->uapi.dst),
235 drm_rect_height(&plane_state->uapi.dst),
236 fb ? fb->format : NULL,
237 fb ? fb->modifier : 0,
238 need_scaler);
239
240 if (ret || plane_state->scaler_id < 0)
241 return ret;
242
243
244 if (plane_state->ckey.flags) {
245 drm_dbg_kms(&dev_priv->drm,
246 "[PLANE:%d:%s] scaling with color key not allowed",
247 intel_plane->base.base.id,
248 intel_plane->base.name);
249 return -EINVAL;
250 }
251
252
253 switch (fb->format->format) {
254 case DRM_FORMAT_RGB565:
255 case DRM_FORMAT_XBGR8888:
256 case DRM_FORMAT_XRGB8888:
257 case DRM_FORMAT_ABGR8888:
258 case DRM_FORMAT_ARGB8888:
259 case DRM_FORMAT_XRGB2101010:
260 case DRM_FORMAT_XBGR2101010:
261 case DRM_FORMAT_ARGB2101010:
262 case DRM_FORMAT_ABGR2101010:
263 case DRM_FORMAT_YUYV:
264 case DRM_FORMAT_YVYU:
265 case DRM_FORMAT_UYVY:
266 case DRM_FORMAT_VYUY:
267 case DRM_FORMAT_NV12:
268 case DRM_FORMAT_XYUV8888:
269 case DRM_FORMAT_P010:
270 case DRM_FORMAT_P012:
271 case DRM_FORMAT_P016:
272 case DRM_FORMAT_Y210:
273 case DRM_FORMAT_Y212:
274 case DRM_FORMAT_Y216:
275 case DRM_FORMAT_XVYU2101010:
276 case DRM_FORMAT_XVYU12_16161616:
277 case DRM_FORMAT_XVYU16161616:
278 break;
279 case DRM_FORMAT_XBGR16161616F:
280 case DRM_FORMAT_ABGR16161616F:
281 case DRM_FORMAT_XRGB16161616F:
282 case DRM_FORMAT_ARGB16161616F:
283 if (DISPLAY_VER(dev_priv) >= 11)
284 break;
285 fallthrough;
286 default:
287 drm_dbg_kms(&dev_priv->drm,
288 "[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n",
289 intel_plane->base.base.id, intel_plane->base.name,
290 fb->base.id, fb->format->format);
291 return -EINVAL;
292 }
293
294 return 0;
295}
296
297static int glk_coef_tap(int i)
298{
299 return i % 7;
300}
301
302static u16 glk_nearest_filter_coef(int t)
303{
304 return t == 3 ? 0x0800 : 0x3000;
305}
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344static void glk_program_nearest_filter_coefs(struct drm_i915_private *dev_priv,
345 enum pipe pipe, int id, int set)
346{
347 int i;
348
349 intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set),
350 PS_COEE_INDEX_AUTO_INC);
351
352 for (i = 0; i < 17 * 7; i += 2) {
353 u32 tmp;
354 int t;
355
356 t = glk_coef_tap(i);
357 tmp = glk_nearest_filter_coef(t);
358
359 t = glk_coef_tap(i + 1);
360 tmp |= glk_nearest_filter_coef(t) << 16;
361
362 intel_de_write_fw(dev_priv, GLK_PS_COEF_DATA_SET(pipe, id, set),
363 tmp);
364 }
365
366 intel_de_write_fw(dev_priv, GLK_PS_COEF_INDEX_SET(pipe, id, set), 0);
367}
368
369static u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set)
370{
371 if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) {
372 return (PS_FILTER_PROGRAMMED |
373 PS_Y_VERT_FILTER_SELECT(set) |
374 PS_Y_HORZ_FILTER_SELECT(set) |
375 PS_UV_VERT_FILTER_SELECT(set) |
376 PS_UV_HORZ_FILTER_SELECT(set));
377 }
378
379 return PS_FILTER_MEDIUM;
380}
381
382static void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe,
383 int id, int set, enum drm_scaling_filter filter)
384{
385 switch (filter) {
386 case DRM_SCALING_FILTER_DEFAULT:
387 break;
388 case DRM_SCALING_FILTER_NEAREST_NEIGHBOR:
389 glk_program_nearest_filter_coefs(dev_priv, pipe, id, set);
390 break;
391 default:
392 MISSING_CASE(filter);
393 }
394}
395
396void skl_pfit_enable(const struct intel_crtc_state *crtc_state)
397{
398 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
399 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
400 const struct intel_crtc_scaler_state *scaler_state =
401 &crtc_state->scaler_state;
402 struct drm_rect src = {
403 .x2 = crtc_state->pipe_src_w << 16,
404 .y2 = crtc_state->pipe_src_h << 16,
405 };
406 const struct drm_rect *dst = &crtc_state->pch_pfit.dst;
407 u16 uv_rgb_hphase, uv_rgb_vphase;
408 enum pipe pipe = crtc->pipe;
409 int width = drm_rect_width(dst);
410 int height = drm_rect_height(dst);
411 int x = dst->x1;
412 int y = dst->y1;
413 int hscale, vscale;
414 unsigned long irqflags;
415 int id;
416 u32 ps_ctrl;
417
418 if (!crtc_state->pch_pfit.enabled)
419 return;
420
421 if (drm_WARN_ON(&dev_priv->drm,
422 crtc_state->scaler_state.scaler_id < 0))
423 return;
424
425 hscale = drm_rect_calc_hscale(&src, dst, 0, INT_MAX);
426 vscale = drm_rect_calc_vscale(&src, dst, 0, INT_MAX);
427
428 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
429 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
430
431 id = scaler_state->scaler_id;
432
433 ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0);
434 ps_ctrl |= PS_SCALER_EN | scaler_state->scalers[id].mode;
435
436 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
437
438 skl_scaler_setup_filter(dev_priv, pipe, id, 0,
439 crtc_state->hw.scaling_filter);
440
441 intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), ps_ctrl);
442
443 intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, id),
444 PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase));
445 intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id),
446 PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_hphase));
447 intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, id),
448 x << 16 | y);
449 intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id),
450 width << 16 | height);
451
452 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
453}
454
455void
456skl_program_plane_scaler(struct intel_plane *plane,
457 const struct intel_crtc_state *crtc_state,
458 const struct intel_plane_state *plane_state)
459{
460 struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
461 const struct drm_framebuffer *fb = plane_state->hw.fb;
462 enum pipe pipe = plane->pipe;
463 int scaler_id = plane_state->scaler_id;
464 const struct intel_scaler *scaler =
465 &crtc_state->scaler_state.scalers[scaler_id];
466 int crtc_x = plane_state->uapi.dst.x1;
467 int crtc_y = plane_state->uapi.dst.y1;
468 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst);
469 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst);
470 u16 y_hphase, uv_rgb_hphase;
471 u16 y_vphase, uv_rgb_vphase;
472 int hscale, vscale;
473 u32 ps_ctrl;
474
475 hscale = drm_rect_calc_hscale(&plane_state->uapi.src,
476 &plane_state->uapi.dst,
477 0, INT_MAX);
478 vscale = drm_rect_calc_vscale(&plane_state->uapi.src,
479 &plane_state->uapi.dst,
480 0, INT_MAX);
481
482
483 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) &&
484 !icl_is_hdr_plane(dev_priv, plane->id)) {
485 y_hphase = skl_scaler_calc_phase(1, hscale, false);
486 y_vphase = skl_scaler_calc_phase(1, vscale, false);
487
488
489 uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
490 uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
491 } else {
492
493 y_hphase = 0;
494 y_vphase = 0;
495
496 uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
497 uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
498 }
499
500 ps_ctrl = skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0);
501 ps_ctrl |= PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode;
502
503 skl_scaler_setup_filter(dev_priv, pipe, scaler_id, 0,
504 plane_state->hw.scaling_filter);
505
506 intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
507 intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, scaler_id),
508 PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
509 intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, scaler_id),
510 PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
511 intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(pipe, scaler_id),
512 (crtc_x << 16) | crtc_y);
513 intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, scaler_id),
514 (crtc_w << 16) | crtc_h);
515}
516
517static void skl_detach_scaler(struct intel_crtc *crtc, int id)
518{
519 struct drm_device *dev = crtc->base.dev;
520 struct drm_i915_private *dev_priv = to_i915(dev);
521 unsigned long irqflags;
522
523 spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
524
525 intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0);
526 intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0);
527 intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0);
528
529 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
530}
531
532
533
534
535void skl_detach_scalers(const struct intel_crtc_state *crtc_state)
536{
537 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
538 const struct intel_crtc_scaler_state *scaler_state =
539 &crtc_state->scaler_state;
540 int i;
541
542
543 for (i = 0; i < crtc->num_scalers; i++) {
544 if (!scaler_state->scalers[i].in_use)
545 skl_detach_scaler(crtc, i);
546 }
547}
548
549void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state)
550{
551 struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
552 int i;
553
554 for (i = 0; i < crtc->num_scalers; i++)
555 skl_detach_scaler(crtc, i);
556}
557