Lines Matching +full:display +full:- +full:pipe

1 // SPDX-License-Identifier: MIT
18 * -0.5. That matches how the hardware calculates the scaling
19 * factors (from top-left of the first pixel to bottom-right
30 * The same behaviour is observed on pre-SKL platforms as well.
32 * Theory behind the formula (note that we ignore sub-pixel
38 * -0.5
47 * -0.5
48 * | -0.375 (initial phase)
57 int phase = -0x8000; in skl_scaler_calc_phase()
61 phase += (sub - 1) * 0x8000 / sub; in skl_scaler_calc_phase()
66 * Hardware initial phase limited to [-0.5:1.5]. in skl_scaler_calc_phase()
70 WARN_ON(phase < -0x8000 || phase > 0x18000); in skl_scaler_calc_phase()
95 struct intel_display *display = to_intel_display(crtc); in skl_scaler_max_src_size() local
97 if (DISPLAY_VER(display) >= 14) { in skl_scaler_max_src_size()
100 } else if (DISPLAY_VER(display) >= 12) { in skl_scaler_max_src_size()
103 } else if (DISPLAY_VER(display) == 11) { in skl_scaler_max_src_size()
121 struct intel_display *display = to_intel_display(crtc); in skl_scaler_max_dst_size() local
123 if (DISPLAY_VER(display) >= 12) { in skl_scaler_max_dst_size()
126 } else if (DISPLAY_VER(display) == 11) { in skl_scaler_max_dst_size()
142 struct intel_display *display = to_intel_display(crtc_state); in skl_update_scaler() local
144 &crtc_state->scaler_state; in skl_update_scaler()
145 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); in skl_update_scaler()
147 &crtc_state->hw.adjusted_mode; in skl_update_scaler()
148 int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); in skl_update_scaler()
149 int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); in skl_update_scaler()
162 * Scaling/fitting not supported in IF-ID mode in GEN9+ in skl_update_scaler()
167 if (DISPLAY_VER(display) >= 9 && crtc_state->hw.enable && in skl_update_scaler()
168 need_scaler && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { in skl_update_scaler()
169 drm_dbg_kms(display->drm, in skl_update_scaler()
170 "[CRTC:%d:%s] scaling not supported with IF-ID mode\n", in skl_update_scaler()
171 crtc->base.base.id, crtc->base.name); in skl_update_scaler()
172 return -EINVAL; in skl_update_scaler()
177 * - free scaler binded to this plane/crtc in skl_update_scaler()
178 * - in order to do this, update crtc->scaler_usage in skl_update_scaler()
182 * update to free the scaler is done in plane/panel-fit programming. in skl_update_scaler()
183 * For this purpose crtc/plane_state->scaler_id isn't reset here. in skl_update_scaler()
187 scaler_state->scaler_users &= ~(1 << scaler_user); in skl_update_scaler()
188 scaler_state->scalers[*scaler_id].in_use = false; in skl_update_scaler()
190 drm_dbg_kms(display->drm, in skl_update_scaler()
193 crtc->base.base.id, crtc->base.name, in skl_update_scaler()
194 crtc->pipe, scaler_user, *scaler_id, in skl_update_scaler()
195 scaler_state->scaler_users); in skl_update_scaler()
196 *scaler_id = -1; in skl_update_scaler()
212 drm_dbg_kms(display->drm, in skl_update_scaler()
215 crtc->base.base.id, crtc->base.name, in skl_update_scaler()
216 crtc->pipe, scaler_user, src_w, src_h, in skl_update_scaler()
218 return -EINVAL; in skl_update_scaler()
222 * The pipe scaler does not use all the bits of PIPESRC, at least in skl_update_scaler()
224 * the *pipe* source size must not be too large. For simplicity in skl_update_scaler()
230 drm_dbg_kms(display->drm, in skl_update_scaler()
231 "[CRTC:%d:%s] scaler_user index %u.%u: pipe src size %ux%u " in skl_update_scaler()
233 crtc->base.base.id, crtc->base.name, in skl_update_scaler()
234 crtc->pipe, scaler_user, pipe_src_w, pipe_src_h); in skl_update_scaler()
235 return -EINVAL; in skl_update_scaler()
239 scaler_state->scaler_users |= (1 << scaler_user); in skl_update_scaler()
240 drm_dbg_kms(display->drm, "[CRTC:%d:%s] scaler_user index %u.%u: " in skl_update_scaler()
241 "staged scaling request for %ux%u->%ux%u scaler_users = 0x%x\n", in skl_update_scaler()
242 crtc->base.base.id, crtc->base.name, in skl_update_scaler()
243 crtc->pipe, scaler_user, src_w, src_h, dst_w, dst_h, in skl_update_scaler()
244 scaler_state->scaler_users); in skl_update_scaler()
251 const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; in skl_update_scaler_crtc()
254 if (crtc_state->pch_pfit.enabled) { in skl_update_scaler_crtc()
255 width = drm_rect_width(&crtc_state->pch_pfit.dst); in skl_update_scaler_crtc()
256 height = drm_rect_height(&crtc_state->pch_pfit.dst); in skl_update_scaler_crtc()
258 width = pipe_mode->crtc_hdisplay; in skl_update_scaler_crtc()
259 height = pipe_mode->crtc_vdisplay; in skl_update_scaler_crtc()
261 return skl_update_scaler(crtc_state, !crtc_state->hw.active, in skl_update_scaler_crtc()
263 &crtc_state->scaler_state.scaler_id, in skl_update_scaler_crtc()
264 drm_rect_width(&crtc_state->pipe_src), in skl_update_scaler_crtc()
265 drm_rect_height(&crtc_state->pipe_src), in skl_update_scaler_crtc()
267 crtc_state->pch_pfit.enabled); in skl_update_scaler_crtc()
271 * skl_update_scaler_plane - Stages update to scaler state for a given plane.
276 * 0 - scaler_usage updated successfully
277 * error - requested scaling cannot be supported or other error condition
282 struct intel_display *display = to_intel_display(plane_state); in skl_update_scaler_plane() local
283 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); in skl_update_scaler_plane()
284 struct drm_framebuffer *fb = plane_state->hw.fb; in skl_update_scaler_plane()
285 bool force_detach = !fb || !plane_state->uapi.visible; in skl_update_scaler_plane()
288 /* Pre-gen11 and SDR planes always need a scaler for planar formats. */ in skl_update_scaler_plane()
289 if (!icl_is_hdr_plane(display, plane->id) && in skl_update_scaler_plane()
290 fb && intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) in skl_update_scaler_plane()
294 drm_plane_index(&plane->base), in skl_update_scaler_plane()
295 &plane_state->scaler_id, in skl_update_scaler_plane()
296 drm_rect_width(&plane_state->uapi.src) >> 16, in skl_update_scaler_plane()
297 drm_rect_height(&plane_state->uapi.src) >> 16, in skl_update_scaler_plane()
298 drm_rect_width(&plane_state->uapi.dst), in skl_update_scaler_plane()
299 drm_rect_height(&plane_state->uapi.dst), in skl_update_scaler_plane()
300 fb ? fb->format : NULL, in skl_update_scaler_plane()
301 fb ? fb->modifier : 0, in skl_update_scaler_plane()
310 for (i = 0; i < crtc->num_scalers; i++) { in intel_allocate_scaler()
311 if (scaler_state->scalers[i].in_use) in intel_allocate_scaler()
314 scaler_state->scalers[i].in_use = true; in intel_allocate_scaler()
319 return -1; in intel_allocate_scaler()
328 struct intel_display *display = to_intel_display(crtc); in calculate_max_scale() local
338 if (DISPLAY_VER(display) >= 14) { in calculate_max_scale()
345 *max_hscale = 0x30000 - 1; in calculate_max_scale()
348 *max_vscale = 0x30000 - 1; in calculate_max_scale()
351 } else if (DISPLAY_VER(display) >= 10 || !is_yuv_semiplanar) { in calculate_max_scale()
352 *max_hscale = 0x30000 - 1; in calculate_max_scale()
353 *max_vscale = 0x30000 - 1; in calculate_max_scale()
355 *max_hscale = 0x20000 - 1; in calculate_max_scale()
356 *max_vscale = 0x20000 - 1; in calculate_max_scale()
366 struct intel_display *display = to_intel_display(crtc); in intel_atomic_setup_scaler() local
367 struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; in intel_atomic_setup_scaler()
375 if (drm_WARN(display->drm, *scaler_id < 0, in intel_atomic_setup_scaler()
377 return -EINVAL; in intel_atomic_setup_scaler()
380 if (plane_state && plane_state->hw.fb && in intel_atomic_setup_scaler()
381 plane_state->hw.fb->format->is_yuv && in intel_atomic_setup_scaler()
382 plane_state->hw.fb->format->num_planes > 1) { in intel_atomic_setup_scaler()
383 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); in intel_atomic_setup_scaler()
385 if (DISPLAY_VER(display) == 9) { in intel_atomic_setup_scaler()
387 } else if (icl_is_hdr_plane(display, plane->id)) { in intel_atomic_setup_scaler()
396 plane_state->planar_linked_plane; in intel_atomic_setup_scaler()
401 mode |= PS_BINDING_Y_PLANE(linked->id); in intel_atomic_setup_scaler()
403 } else if (DISPLAY_VER(display) >= 10) { in intel_atomic_setup_scaler()
405 } else if (num_scalers_need == 1 && crtc->num_scalers > 1) { in intel_atomic_setup_scaler()
407 * when only 1 scaler is in use on a pipe with 2 scalers in intel_atomic_setup_scaler()
411 scaler_state->scalers[*scaler_id].in_use = false; in intel_atomic_setup_scaler()
413 scaler_state->scalers[0].in_use = true; in intel_atomic_setup_scaler()
419 if (plane_state && plane_state->hw.fb) { in intel_atomic_setup_scaler()
420 const struct drm_framebuffer *fb = plane_state->hw.fb; in intel_atomic_setup_scaler()
421 const struct drm_rect *src = &plane_state->uapi.src; in intel_atomic_setup_scaler()
422 const struct drm_rect *dst = &plane_state->uapi.dst; in intel_atomic_setup_scaler()
426 intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier), in intel_atomic_setup_scaler()
430 * FIXME: We should change the if-else block above to in intel_atomic_setup_scaler()
439 drm_dbg_kms(display->drm, in intel_atomic_setup_scaler()
441 crtc->base.base.id, crtc->base.name, *scaler_id); in intel_atomic_setup_scaler()
445 return -EINVAL; in intel_atomic_setup_scaler()
449 if (crtc_state->pch_pfit.enabled) { in intel_atomic_setup_scaler()
454 drm_rect_width(&crtc_state->pipe_src) << 16, in intel_atomic_setup_scaler()
455 drm_rect_height(&crtc_state->pipe_src) << 16); in intel_atomic_setup_scaler()
461 * When configured for Pipe YUV 420 encoding for port output, in intel_atomic_setup_scaler()
465 if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) { in intel_atomic_setup_scaler()
466 max_hscale = 0x18000 - 1; in intel_atomic_setup_scaler()
470 hscale = drm_rect_calc_hscale(&src, &crtc_state->pch_pfit.dst, in intel_atomic_setup_scaler()
472 vscale = drm_rect_calc_vscale(&src, &crtc_state->pch_pfit.dst, in intel_atomic_setup_scaler()
476 drm_dbg_kms(display->drm, in intel_atomic_setup_scaler()
477 "Scaler %d doesn't support required pipe scaling\n", in intel_atomic_setup_scaler()
480 drm_rect_debug_print("dst: ", &crtc_state->pch_pfit.dst, false); in intel_atomic_setup_scaler()
482 return -EINVAL; in intel_atomic_setup_scaler()
486 scaler_state->scalers[*scaler_id].hscale = hscale; in intel_atomic_setup_scaler()
487 scaler_state->scalers[*scaler_id].vscale = vscale; in intel_atomic_setup_scaler()
489 drm_dbg_kms(display->drm, "[CRTC:%d:%s] attached scaler id %u.%u to %s:%d\n", in intel_atomic_setup_scaler()
490 crtc->base.base.id, crtc->base.name, in intel_atomic_setup_scaler()
491 crtc->pipe, *scaler_id, name, idx); in intel_atomic_setup_scaler()
492 scaler_state->scalers[*scaler_id].mode = mode; in intel_atomic_setup_scaler()
503 &crtc_state->scaler_state; in setup_crtc_scaler()
506 hweight32(scaler_state->scaler_users), in setup_crtc_scaler()
507 crtc, "CRTC", crtc->base.base.id, in setup_crtc_scaler()
508 NULL, &scaler_state->scaler_id); in setup_crtc_scaler()
515 struct intel_display *display = to_intel_display(state); in setup_plane_scaler() local
519 &crtc_state->scaler_state; in setup_plane_scaler()
523 if (drm_WARN_ON(display->drm, plane->pipe != crtc->pipe)) in setup_plane_scaler()
533 if (!plane_state && DISPLAY_VER(display) >= 10) in setup_plane_scaler()
541 hweight32(scaler_state->scaler_users), in setup_plane_scaler()
542 crtc, "PLANE", plane->base.base.id, in setup_plane_scaler()
543 plane_state, &plane_state->scaler_id); in setup_plane_scaler()
547 * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
559 * 0 - scalers were setup successfully
560 * error code - otherwise
565 struct intel_display *display = to_intel_display(crtc); in intel_atomic_setup_scalers() local
569 &crtc_state->scaler_state; in intel_atomic_setup_scalers()
573 num_scalers_need = hweight32(scaler_state->scaler_users); in intel_atomic_setup_scalers()
577 * - staged scaler requests are already in scaler_state->scaler_users in intel_atomic_setup_scalers()
578 * - check whether staged scaling requests can be supported in intel_atomic_setup_scalers()
579 * - add planes using scalers that aren't in current transaction in intel_atomic_setup_scalers()
580 * - assign scalers to requested users in intel_atomic_setup_scalers()
581 * - as part of plane commit, scalers will be committed in intel_atomic_setup_scalers()
583 * - as part of crtc_commit, scaler will be either attached or detached in intel_atomic_setup_scalers()
588 if (num_scalers_need > crtc->num_scalers) { in intel_atomic_setup_scalers()
589 drm_dbg_kms(display->drm, in intel_atomic_setup_scalers()
591 crtc->base.base.id, crtc->base.name, in intel_atomic_setup_scalers()
592 num_scalers_need, crtc->num_scalers); in intel_atomic_setup_scalers()
593 return -EINVAL; in intel_atomic_setup_scalers()
597 for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) { in intel_atomic_setup_scalers()
601 if (!(scaler_state->scaler_users & (1 << i))) in intel_atomic_setup_scalers()
610 to_intel_plane(drm_plane_from_index(display->drm, i)); in intel_atomic_setup_scalers()
632 * Theory behind setting nearest-neighbor integer scaling:
636 * represents the coefficient set for a phase (0-16).
638 * +------------+--------------------------+--------------------------+
640 * +------------+--------------------------+--------------------------+
642 * +------------+--------------------------+--------------------------+
644 * +------------+--------------------------+--------------------------+
646 * +------------+--------------------------+--------------------------+
648 * +------------+--------------------------+--------------------------+
650 * +------------+--------------------------+--------------------------+
652 * +------------+--------------------------+--------------------------+
654 * +------------+--------------------------+--------------------------+
656 * +------------+--------------------------+--------------------------+
658 * +------------+--------------------------+--------------------------+
660 * +------------+--------------------------+--------------------------+
662 * To enable nearest-neighbor scaling: program scaler coefficients with
668 static void glk_program_nearest_filter_coefs(struct intel_display *display, in glk_program_nearest_filter_coefs() argument
670 enum pipe pipe, int id, int set) in glk_program_nearest_filter_coefs() argument
674 intel_de_write_dsb(display, dsb, in glk_program_nearest_filter_coefs()
675 GLK_PS_COEF_INDEX_SET(pipe, id, set), in glk_program_nearest_filter_coefs()
688 intel_de_write_dsb(display, dsb, in glk_program_nearest_filter_coefs()
689 GLK_PS_COEF_DATA_SET(pipe, id, set), tmp); in glk_program_nearest_filter_coefs()
692 intel_de_write_dsb(display, dsb, in glk_program_nearest_filter_coefs()
693 GLK_PS_COEF_INDEX_SET(pipe, id, set), 0); in glk_program_nearest_filter_coefs()
709 static void skl_scaler_setup_filter(struct intel_display *display, in skl_scaler_setup_filter() argument
710 struct intel_dsb *dsb, enum pipe pipe, in skl_scaler_setup_filter() argument
717 glk_program_nearest_filter_coefs(display, dsb, pipe, id, set); in skl_scaler_setup_filter()
726 struct intel_display *display = to_intel_display(crtc_state); in skl_pfit_enable() local
727 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); in skl_pfit_enable()
729 &crtc_state->scaler_state; in skl_pfit_enable()
730 const struct drm_rect *dst = &crtc_state->pch_pfit.dst; in skl_pfit_enable()
732 enum pipe pipe = crtc->pipe; in skl_pfit_enable() local
735 int x = dst->x1; in skl_pfit_enable()
736 int y = dst->y1; in skl_pfit_enable()
742 if (!crtc_state->pch_pfit.enabled) in skl_pfit_enable()
745 if (drm_WARN_ON(display->drm, in skl_pfit_enable()
746 crtc_state->scaler_state.scaler_id < 0)) in skl_pfit_enable()
750 drm_rect_width(&crtc_state->pipe_src) << 16, in skl_pfit_enable()
751 drm_rect_height(&crtc_state->pipe_src) << 16); in skl_pfit_enable()
759 id = scaler_state->scaler_id; in skl_pfit_enable()
761 ps_ctrl = PS_SCALER_EN | PS_BINDING_PIPE | scaler_state->scalers[id].mode | in skl_pfit_enable()
762 skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0); in skl_pfit_enable()
766 skl_scaler_setup_filter(display, NULL, pipe, id, 0, in skl_pfit_enable()
767 crtc_state->hw.scaling_filter); in skl_pfit_enable()
769 intel_de_write_fw(display, SKL_PS_CTRL(pipe, id), ps_ctrl); in skl_pfit_enable()
771 intel_de_write_fw(display, SKL_PS_VPHASE(pipe, id), in skl_pfit_enable()
773 intel_de_write_fw(display, SKL_PS_HPHASE(pipe, id), in skl_pfit_enable()
775 intel_de_write_fw(display, SKL_PS_WIN_POS(pipe, id), in skl_pfit_enable()
777 intel_de_write_fw(display, SKL_PS_WIN_SZ(pipe, id), in skl_pfit_enable()
787 struct intel_display *display = to_intel_display(plane); in skl_program_plane_scaler() local
788 const struct drm_framebuffer *fb = plane_state->hw.fb; in skl_program_plane_scaler()
789 enum pipe pipe = plane->pipe; in skl_program_plane_scaler() local
790 int scaler_id = plane_state->scaler_id; in skl_program_plane_scaler()
792 &crtc_state->scaler_state.scalers[scaler_id]; in skl_program_plane_scaler()
793 int crtc_x = plane_state->uapi.dst.x1; in skl_program_plane_scaler()
794 int crtc_y = plane_state->uapi.dst.y1; in skl_program_plane_scaler()
795 u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); in skl_program_plane_scaler()
796 u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); in skl_program_plane_scaler()
802 hscale = drm_rect_calc_hscale(&plane_state->uapi.src, in skl_program_plane_scaler()
803 &plane_state->uapi.dst, in skl_program_plane_scaler()
805 vscale = drm_rect_calc_vscale(&plane_state->uapi.src, in skl_program_plane_scaler()
806 &plane_state->uapi.dst, in skl_program_plane_scaler()
809 /* TODO: handle sub-pixel coordinates */ in skl_program_plane_scaler()
810 if (intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier) && in skl_program_plane_scaler()
811 !icl_is_hdr_plane(display, plane->id)) { in skl_program_plane_scaler()
827 ps_ctrl = PS_SCALER_EN | PS_BINDING_PLANE(plane->id) | scaler->mode | in skl_program_plane_scaler()
828 skl_scaler_get_filter_select(plane_state->hw.scaling_filter, 0); in skl_program_plane_scaler()
833 skl_scaler_setup_filter(display, dsb, pipe, scaler_id, 0, in skl_program_plane_scaler()
834 plane_state->hw.scaling_filter); in skl_program_plane_scaler()
836 intel_de_write_dsb(display, dsb, SKL_PS_CTRL(pipe, scaler_id), in skl_program_plane_scaler()
838 intel_de_write_dsb(display, dsb, SKL_PS_VPHASE(pipe, scaler_id), in skl_program_plane_scaler()
840 intel_de_write_dsb(display, dsb, SKL_PS_HPHASE(pipe, scaler_id), in skl_program_plane_scaler()
842 intel_de_write_dsb(display, dsb, SKL_PS_WIN_POS(pipe, scaler_id), in skl_program_plane_scaler()
844 intel_de_write_dsb(display, dsb, SKL_PS_WIN_SZ(pipe, scaler_id), in skl_program_plane_scaler()
851 struct intel_display *display = to_intel_display(crtc); in skl_detach_scaler() local
855 intel_de_write_dsb(display, dsb, SKL_PS_CTRL(crtc->pipe, id), 0); in skl_detach_scaler()
856 intel_de_write_dsb(display, dsb, SKL_PS_WIN_POS(crtc->pipe, id), 0); in skl_detach_scaler()
857 intel_de_write_dsb(display, dsb, SKL_PS_WIN_SZ(crtc->pipe, id), 0); in skl_detach_scaler()
866 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); in skl_detach_scalers()
868 &crtc_state->scaler_state; in skl_detach_scalers()
872 for (i = 0; i < crtc->num_scalers; i++) { in skl_detach_scalers()
873 if (!scaler_state->scalers[i].in_use) in skl_detach_scalers()
880 struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); in skl_scaler_disable()
883 for (i = 0; i < crtc->num_scalers; i++) in skl_scaler_disable()
889 struct intel_display *display = to_intel_display(crtc_state); in skl_scaler_get_config() local
890 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); in skl_scaler_get_config()
891 struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; in skl_scaler_get_config()
892 int id = -1; in skl_scaler_get_config()
895 /* find scaler attached to this pipe */ in skl_scaler_get_config()
896 for (i = 0; i < crtc->num_scalers; i++) { in skl_scaler_get_config()
899 ctl = intel_de_read(display, SKL_PS_CTRL(crtc->pipe, i)); in skl_scaler_get_config()
904 crtc_state->pch_pfit.enabled = true; in skl_scaler_get_config()
906 pos = intel_de_read(display, SKL_PS_WIN_POS(crtc->pipe, i)); in skl_scaler_get_config()
907 size = intel_de_read(display, SKL_PS_WIN_SZ(crtc->pipe, i)); in skl_scaler_get_config()
909 drm_rect_init(&crtc_state->pch_pfit.dst, in skl_scaler_get_config()
915 scaler_state->scalers[i].in_use = true; in skl_scaler_get_config()
919 scaler_state->scaler_id = id; in skl_scaler_get_config()
921 scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX); in skl_scaler_get_config()
923 scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX); in skl_scaler_get_config()