diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-14 11:07:56 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-14 11:07:56 -0800 |
| commit | 1d36dffa5d887715dacca0f717f4519b7be5e498 (patch) | |
| tree | a68f7c00dbb3036a67806ed6c6b8cc61c3cff60d /drivers/gpu/drm/i915/display/intel_display.c | |
| parent | 2c85ebc57b3e1817b6ce1a6b703928e113a90442 (diff) | |
| parent | b10733527bfd864605c33ab2e9a886eec317ec39 (diff) | |
| download | linux-1d36dffa5d887715dacca0f717f4519b7be5e498.tar.gz linux-1d36dffa5d887715dacca0f717f4519b7be5e498.tar.bz2 linux-1d36dffa5d887715dacca0f717f4519b7be5e498.zip | |
Merge tag 'drm-next-2020-12-11' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"Not a huge amount of big things here, AMD has support for a few new HW
variants (vangogh, green sardine, dimgrey cavefish), Intel has some
more DG1 enablement. We have a few big reworks of the TTM layers and
interfaces, GEM and atomic internal API reworks cross tree. fbdev is
marked orphaned in here as well to reflect the current reality.
core:
- documentation updates
- deprecate DRM_FORMAT_MOD_NONE
- atomic crtc enable/disable rework
- GEM convert drivers to gem object functions
- remove SCATTER_LIST_MAX_SEGMENT
sched:
- avoid infinite waits
ttm:
- remove AGP support
- don't modify caching for swapout
- ttm pinning rework
- major TTM reworks
- new backend allocator
- multihop support
vram-helper:
- top down BO placement fix
- TTM changes
- GEM object support
displayport:
- DP 2.0 DPCD prep work
- DP MST extended DPCD caps
fbdev:
- mark as orphaned
amdgpu:
- Initial Vangogh support
- Green Sardine support
- Dimgrey Cavefish support
- SG display support for renoir
- SMU7 improvements
- gfx9+ modiifier support
- CI BACO fixes
radeon:
- expose voltage via hwmon on SUMO
amdkfd:
- fix unique id handling
i915:
- more DG1 enablement
- bigjoiner support
- integer scaling filter support
- async flip support
- ICL+ DSI command mode
- Improve display shutdown
- Display refactoring
- eLLC machine fbdev loading fix
- dma scatterlist fixes
- TGL hang fixes
- eLLC display buffer caching on SKL+
- MOCS PTE seeting for gen9+
msm:
- Shutdown hook
- GPU cooling device support
- DSI 7nm and 10nm phy/pll updates
- sm8150/sm2850 DPU support
- GEM locking re-work
- LLCC system cache support
aspeed:
- sysfs output config support
ast:
- LUT fix
- new display mode
gma500:
- remove 2d framebuffer accel
panfrost:
- move gpu reset to a worker
exynos:
- new HDMI mode support
mediatek:
- MT8167 support
- yaml bindings
- MIPI DSI phy code moved
etnaviv:
- new perf counter
- more lockdep annotation
hibmc:
- i2c DDC support
ingenic:
- pixel clock reset fix
- reserved memory support
- allow both DMA channels at once
- different pixel format support
- 30/24/8-bit palette modes
tilcdc:
- don't keep vblank irq enabled
vc4:
- new maintainer added
- DSI registration fix
virtio:
- blob resource support
- host visible and cross-device support
- uuid api support"
* tag 'drm-next-2020-12-11' of git://anongit.freedesktop.org/drm/drm: (1754 commits)
drm/amdgpu: Initialise drm_gem_object_funcs for imported BOs
drm/amdgpu: fix size calculation with stolen vga memory
drm/amdgpu: remove amdgpu_ttm_late_init and amdgpu_bo_late_init
drm/amdgpu: free the pre-OS console framebuffer after the first modeset
drm/amdgpu: enable runtime pm using BACO on CI dGPUs
drm/amdgpu/cik: enable BACO reset on Bonaire
drm/amd/pm: update smu10.h WORKLOAD_PPLIB setting for raven
drm/amd/pm: remove one unsupported smu function for vangogh
drm/amd/display: setup system context for APUs
drm/amd/display: add S/G support for Vangogh
drm/amdkfd: Fix leak in dmabuf import
drm/amdgpu: use AMDGPU_NUM_VMID when possible
drm/amdgpu: fix sdma instance fw version and feature version init
drm/amd/pm: update driver if version for dimgrey_cavefish
drm/amd/display: 3.2.115
drm/amd/display: [FW Promotion] Release 0.0.45
drm/amd/display: Revert DCN2.1 dram_clock_change_latency update
drm/amd/display: Enable gpu_vm_support for dcn3.01
drm/amd/display: Fixed the audio noise during mode switching with HDCP mode on
drm/amd/display: Add wm table for Renoir
...
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_display.c | 1689 |
1 files changed, 1222 insertions, 467 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index aabf09f89cad..53a00cf3fa32 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -154,7 +154,7 @@ static void ilk_pch_clock_get(struct intel_crtc *crtc, static int intel_framebuffer_init(struct intel_framebuffer *ifb, struct drm_i915_gem_object *obj, struct drm_mode_fb_cmd2 *mode_cmd); -static void intel_set_pipe_timings(const struct intel_crtc_state *crtc_state); +static void intel_set_transcoder_timings(const struct intel_crtc_state *crtc_state); static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state); static void intel_cpu_transcoder_set_m_n(const struct intel_crtc_state *crtc_state, const struct intel_link_m_n *m_n, @@ -1808,6 +1808,17 @@ enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) static u32 intel_crtc_max_vblank_count(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 mode_flags = crtc->mode_flags; + + /* + * From Gen 11, In case of dsi cmd mode, frame counter wouldnt + * have updated at the beginning of TE, if we want to use + * the hw counter, then we would find it updated in only + * the next TE, hence switching to sw counter. + */ + if (mode_flags & (I915_MODE_FLAG_DSI_USE_TE0 | I915_MODE_FLAG_DSI_USE_TE1)) + return 0; /* * On i965gm the hardware frame counter reads @@ -1990,13 +2001,17 @@ static int ccs_to_main_plane(const struct drm_framebuffer *fb, int ccs_plane) return ccs_plane - fb->format->num_planes / 2; } -/* Return either the main plane's CCS or - if not a CCS FB - UV plane */ int intel_main_to_aux_plane(const struct drm_framebuffer *fb, int main_plane) { + struct drm_i915_private *i915 = to_i915(fb->dev); + if (is_ccs_modifier(fb->modifier)) return main_to_ccs_plane(fb, main_plane); - - return 1; + else if (INTEL_GEN(i915) < 11 && + intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) + return 1; + else + return 0; } bool @@ -3616,6 +3631,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, struct intel_plane *intel_plane = to_intel_plane(primary); struct intel_plane_state *intel_state = to_intel_plane_state(plane_state); + struct intel_crtc_state *crtc_state = + to_intel_crtc_state(intel_crtc->base.state); struct drm_framebuffer *fb; struct i915_vma *vma; @@ -3638,7 +3655,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, if (c == &intel_crtc->base) continue; - if (!to_intel_crtc(c)->active) + if (!to_intel_crtc_state(c->state)->uapi.active) continue; state = to_intel_plane_state(c->primary->state); @@ -3660,6 +3677,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, * pretend the BIOS never had it enabled. */ intel_plane_disable_noatomic(intel_crtc, intel_plane); + if (crtc_state->bigjoiner) { + struct intel_crtc *slave = + crtc_state->bigjoiner_linked_crtc; + intel_plane_disable_noatomic(slave, to_intel_plane(slave->base.primary)); + } return; @@ -3696,7 +3718,8 @@ valid_fb: drm_framebuffer_get(fb); plane_state->crtc = &intel_crtc->base; - intel_plane_copy_uapi_to_hw_state(intel_state, intel_state); + intel_plane_copy_uapi_to_hw_state(intel_state, intel_state, + intel_crtc); intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB); @@ -3704,127 +3727,6 @@ valid_fb: &to_intel_frontbuffer(fb)->bits); } -static int skl_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - int cpp = fb->format->cpp[color_plane]; - - switch (fb->modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - /* - * Validated limit is 4k, but has 5k should - * work apart from the following features: - * - Ytile (already limited to 4k) - * - FP16 (already limited to 4k) - * - render compression (already limited to 4k) - * - KVMR sprite and cursor (don't care) - * - horizontal panning (TODO verify this) - * - pipe and plane scaling (TODO verify this) - */ - if (cpp == 8) - return 4096; - else - return 5120; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: - /* FIXME AUX plane? */ - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - if (cpp == 8) - return 2048; - else - return 4096; - default: - MISSING_CASE(fb->modifier); - return 2048; - } -} - -static int glk_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - int cpp = fb->format->cpp[color_plane]; - - switch (fb->modifier) { - case DRM_FORMAT_MOD_LINEAR: - case I915_FORMAT_MOD_X_TILED: - if (cpp == 8) - return 4096; - else - return 5120; - case I915_FORMAT_MOD_Y_TILED_CCS: - case I915_FORMAT_MOD_Yf_TILED_CCS: - /* FIXME AUX plane? */ - case I915_FORMAT_MOD_Y_TILED: - case I915_FORMAT_MOD_Yf_TILED: - if (cpp == 8) - return 2048; - else - return 5120; - default: - MISSING_CASE(fb->modifier); - return 2048; - } -} - -static int icl_min_plane_width(const struct drm_framebuffer *fb) -{ - /* Wa_14011264657, Wa_14011050563: gen11+ */ - switch (fb->format->format) { - case DRM_FORMAT_C8: - return 18; - case DRM_FORMAT_RGB565: - return 10; - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_XBGR8888: - case DRM_FORMAT_ARGB8888: - case DRM_FORMAT_ABGR8888: - case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: - case DRM_FORMAT_ARGB2101010: - case DRM_FORMAT_ABGR2101010: - case DRM_FORMAT_XVYU2101010: - case DRM_FORMAT_Y212: - case DRM_FORMAT_Y216: - return 6; - case DRM_FORMAT_NV12: - return 20; - case DRM_FORMAT_P010: - case DRM_FORMAT_P012: - case DRM_FORMAT_P016: - return 12; - case DRM_FORMAT_XRGB16161616F: - case DRM_FORMAT_XBGR16161616F: - case DRM_FORMAT_ARGB16161616F: - case DRM_FORMAT_ABGR16161616F: - case DRM_FORMAT_XVYU12_16161616: - case DRM_FORMAT_XVYU16161616: - return 4; - default: - return 1; - } -} - -static int icl_max_plane_width(const struct drm_framebuffer *fb, - int color_plane, - unsigned int rotation) -{ - return 5120; -} - -static int skl_max_plane_height(void) -{ - return 4096; -} - -static int icl_max_plane_height(void) -{ - return 4320; -} static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state, @@ -3882,35 +3784,55 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state) return y; } +static int intel_plane_min_width(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->min_width) + return plane->min_width(fb, color_plane, rotation); + else + return 1; +} + +static int intel_plane_max_width(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->max_width) + return plane->max_width(fb, color_plane, rotation); + else + return INT_MAX; +} + +static int intel_plane_max_height(struct intel_plane *plane, + const struct drm_framebuffer *fb, + int color_plane, + unsigned int rotation) +{ + if (plane->max_height) + return plane->max_height(fb, color_plane, rotation); + else + return INT_MAX; +} + static int skl_check_main_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = to_i915(plane_state->uapi.plane->dev); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; int x = plane_state->uapi.src.x1 >> 16; int y = plane_state->uapi.src.y1 >> 16; int w = drm_rect_width(&plane_state->uapi.src) >> 16; int h = drm_rect_height(&plane_state->uapi.src) >> 16; - int max_width, min_width, max_height; - u32 alignment, offset; + int min_width = intel_plane_min_width(plane, fb, 0, rotation); + int max_width = intel_plane_max_width(plane, fb, 0, rotation); + int max_height = intel_plane_max_height(plane, fb, 0, rotation); int aux_plane = intel_main_to_aux_plane(fb, 0); u32 aux_offset = plane_state->color_plane[aux_plane].offset; - - if (INTEL_GEN(dev_priv) >= 11) { - max_width = icl_max_plane_width(fb, 0, rotation); - min_width = icl_min_plane_width(fb); - } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { - max_width = glk_max_plane_width(fb, 0, rotation); - min_width = 1; - } else { - max_width = skl_max_plane_width(fb, 0, rotation); - min_width = 1; - } - - if (INTEL_GEN(dev_priv) >= 11) - max_height = icl_max_plane_height(); - else - max_height = skl_max_plane_height(); + u32 alignment, offset; if (w > max_width || w < min_width || h > max_height) { drm_dbg_kms(&dev_priv->drm, @@ -3930,7 +3852,7 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) * main surface offset, and it must be non-negative. Make * sure that is what we will get. */ - if (offset > aux_offset) + if (aux_plane && offset > aux_offset) offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, offset, aux_offset & ~(alignment - 1)); @@ -3993,22 +3915,19 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + struct drm_i915_private *i915 = to_i915(plane->base.dev); const struct drm_framebuffer *fb = plane_state->hw.fb; unsigned int rotation = plane_state->hw.rotation; int uv_plane = 1; - int max_width = skl_max_plane_width(fb, uv_plane, rotation); - int max_height = 4096; + int max_width = intel_plane_max_width(plane, fb, uv_plane, rotation); + int max_height = intel_plane_max_height(plane, fb, uv_plane, rotation); int x = plane_state->uapi.src.x1 >> 17; int y = plane_state->uapi.src.y1 >> 17; int w = drm_rect_width(&plane_state->uapi.src) >> 17; int h = drm_rect_height(&plane_state->uapi.src) >> 17; u32 offset; - intel_add_fb_offsets(&x, &y, plane_state, uv_plane); - offset = intel_plane_compute_aligned_offset(&x, &y, - plane_state, uv_plane); - /* FIXME not quite sure how/if these apply to the chroma plane */ if (w > max_width || h > max_height) { drm_dbg_kms(&i915->drm, @@ -4017,10 +3936,14 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) return -EINVAL; } + intel_add_fb_offsets(&x, &y, plane_state, uv_plane); + offset = intel_plane_compute_aligned_offset(&x, &y, + plane_state, uv_plane); + if (is_ccs_modifier(fb->modifier)) { int ccs_plane = main_to_ccs_plane(fb, uv_plane); - int aux_offset = plane_state->color_plane[ccs_plane].offset; - int alignment = intel_surf_alignment(fb, uv_plane); + u32 aux_offset = plane_state->color_plane[ccs_plane].offset; + u32 alignment = intel_surf_alignment(fb, uv_plane); if (offset > aux_offset) offset = intel_plane_adjust_aligned_offset(&x, &y, @@ -4128,7 +4051,7 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state) } for (i = fb->format->num_planes; i < ARRAY_SIZE(plane_state->color_plane); i++) { - plane_state->color_plane[i].offset = ~0xfff; + plane_state->color_plane[i].offset = 0; plane_state->color_plane[i].x = 0; plane_state->color_plane[i].y = 0; } @@ -4392,12 +4315,10 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, if (ret) return ret; - ret = drm_atomic_helper_check_plane_state(&plane_state->uapi, - &crtc_state->uapi, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - i9xx_plane_has_windowing(plane), - true); + ret = intel_atomic_plane_check_clipping(plane_state, crtc_state, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + i9xx_plane_has_windowing(plane)); if (ret) return ret; @@ -4786,6 +4707,9 @@ u32 skl_plane_ctl_crtc(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); u32 plane_ctl = 0; + if (crtc_state->uapi.async_flip) + plane_ctl |= PLANE_CTL_ASYNC_FLIP; + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) return plane_ctl; @@ -4933,13 +4857,16 @@ static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv) intel_has_gpu_reset(&dev_priv->gt)); } -void intel_prepare_reset(struct drm_i915_private *dev_priv) +void intel_display_prepare_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; struct drm_atomic_state *state; int ret; + if (!HAS_DISPLAY(dev_priv)) + return; + /* reset doesn't touch the display */ if (!dev_priv->params.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) @@ -4993,13 +4920,16 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) state->acquire_ctx = ctx; } -void intel_finish_reset(struct drm_i915_private *dev_priv) +void intel_display_finish_reset(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx; struct drm_atomic_state *state; int ret; + if (!HAS_DISPLAY(dev_priv)) + return; + /* reset doesn't touch the display */ if (!test_bit(I915_RESET_MODESET, &dev_priv->gt.reset.flags)) return; @@ -5023,18 +4953,14 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) intel_pps_unlock_regs_wa(dev_priv); intel_modeset_init_hw(dev_priv); intel_init_clock_gating(dev_priv); - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display.hpd_irq_setup) - dev_priv->display.hpd_irq_setup(dev_priv); - spin_unlock_irq(&dev_priv->irq_lock); + intel_hpd_init(dev_priv); ret = __intel_display_resume(dev, state, ctx); if (ret) drm_err(&dev_priv->drm, "Restoring old state failed with %i\n", ret); - intel_hpd_init(dev_priv); + intel_hpd_poll_disable(dev_priv); } drm_atomic_state_put(state); @@ -6153,18 +6079,16 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, static int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state) { - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; + const struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int width, height; if (crtc_state->pch_pfit.enabled) { width = drm_rect_width(&crtc_state->pch_pfit.dst); height = drm_rect_height(&crtc_state->pch_pfit.dst); } else { - width = adjusted_mode->crtc_hdisplay; - height = adjusted_mode->crtc_vdisplay; + width = pipe_mode->crtc_hdisplay; + height = pipe_mode->crtc_vdisplay; } - return skl_update_scaler(crtc_state, !crtc_state->hw.active, SKL_CRTC_INDEX, &crtc_state->scaler_state.scaler_id, @@ -6275,6 +6199,105 @@ void skl_scaler_disable(const struct intel_crtc_state *old_crtc_state) skl_detach_scaler(crtc, i); } +static int cnl_coef_tap(int i) +{ + return i % 7; +} + +static u16 cnl_nearest_filter_coef(int t) +{ + return t == 3 ? 0x0800 : 0x3000; +} + +/* + * Theory behind setting nearest-neighbor integer scaling: + * + * 17 phase of 7 taps requires 119 coefficients in 60 dwords per set. + * The letter represents the filter tap (D is the center tap) and the number + * represents the coefficient set for a phase (0-16). + * + * +------------+------------------------+------------------------+ + * |Index value | Data value coeffient 1 | Data value coeffient 2 | + * +------------+------------------------+------------------------+ + * | 00h | B0 | A0 | + * +------------+------------------------+------------------------+ + * | 01h | D0 | C0 | + * +------------+------------------------+------------------------+ + * | 02h | F0 | E0 | + * +------------+------------------------+------------------------+ + * | 03h | A1 | G0 | + * +------------+------------------------+------------------------+ + * | 04h | C1 | B1 | + * +------------+------------------------+------------------------+ + * | ... | ... | ... | + * +------------+------------------------+------------------------+ + * | 38h | B16 | A16 | + * +------------+------------------------+------------------------+ + * | 39h | D16 | C16 | + * +------------+------------------------+------------------------+ + * | 3Ah | F16 | C16 | + * +------------+------------------------+------------------------+ + * | 3Bh | Reserved | G16 | + * +------------+------------------------+------------------------+ + * + * To enable nearest-neighbor scaling: program scaler coefficents with + * the center tap (Dxx) values set to 1 and all other values set to 0 as per + * SCALER_COEFFICIENT_FORMAT + * + */ + +static void cnl_program_nearest_filter_coefs(struct drm_i915_private *dev_priv, + enum pipe pipe, int id, int set) +{ + int i; + + intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), + PS_COEE_INDEX_AUTO_INC); + + for (i = 0; i < 17 * 7; i += 2) { + u32 tmp; + int t; + + t = cnl_coef_tap(i); + tmp = cnl_nearest_filter_coef(t); + + t = cnl_coef_tap(i + 1); + tmp |= cnl_nearest_filter_coef(t) << 16; + + intel_de_write_fw(dev_priv, CNL_PS_COEF_DATA_SET(pipe, id, set), + tmp); + } + + intel_de_write_fw(dev_priv, CNL_PS_COEF_INDEX_SET(pipe, id, set), 0); +} + +inline u32 skl_scaler_get_filter_select(enum drm_scaling_filter filter, int set) +{ + if (filter == DRM_SCALING_FILTER_NEAREST_NEIGHBOR) { + return (PS_FILTER_PROGRAMMED | + PS_Y_VERT_FILTER_SELECT(set) | + PS_Y_HORZ_FILTER_SELECT(set) | + PS_UV_VERT_FILTER_SELECT(set) | + PS_UV_HORZ_FILTER_SELECT(set)); + } + + return PS_FILTER_MEDIUM; +} + +void skl_scaler_setup_filter(struct drm_i915_private *dev_priv, enum pipe pipe, + int id, int set, enum drm_scaling_filter filter) +{ + switch (filter) { + case DRM_SCALING_FILTER_DEFAULT: + break; + case DRM_SCALING_FILTER_NEAREST_NEIGHBOR: + cnl_program_nearest_filter_coefs(dev_priv, pipe, id, set); + break; + default: + MISSING_CASE(filter); + } +} + static void skl_pfit_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -6295,6 +6318,7 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state) int hscale, vscale; unsigned long irqflags; int id; + u32 ps_ctrl; if (!crtc_state->pch_pfit.enabled) return; @@ -6311,10 +6335,16 @@ static void skl_pfit_enable(const struct intel_crtc_state *crtc_state) id = scaler_state->scaler_id; + ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0); + ps_ctrl |= PS_SCALER_EN | scaler_state->scalers[id].mode; + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), PS_SCALER_EN | - PS_FILTER_MEDIUM | scaler_state->scalers[id].mode); + skl_scaler_setup_filter(dev_priv, pipe, id, 0, + crtc_state->hw.scaling_filter); + + intel_de_write_fw(dev_priv, SKL_PS_CTRL(pipe, id), ps_ctrl); + intel_de_write_fw(dev_priv, SKL_PS_VPHASE(pipe, id), PS_Y_PHASE(0) | PS_UV_RGB_PHASE(uv_rgb_vphase)); intel_de_write_fw(dev_priv, SKL_PS_HPHASE(pipe, id), @@ -6560,6 +6590,43 @@ static void intel_post_plane_update(struct intel_atomic_state *state, icl_wa_scalerclkgating(dev_priv, pipe, false); } +static void skl_disable_async_flip_wa(struct intel_atomic_state *state, + struct intel_crtc *crtc, + const struct intel_crtc_state *new_crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct intel_plane *plane; + struct intel_plane_state *new_plane_state; + int i; + + for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) { + u32 update_mask = new_crtc_state->update_planes; + u32 plane_ctl, surf_addr; + enum plane_id plane_id; + unsigned long irqflags; + enum pipe pipe; + + if (crtc->pipe != plane->pipe || + !(update_mask & BIT(plane->id))) + continue; + + plane_id = plane->id; + pipe = plane->pipe; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + plane_ctl = intel_de_read_fw(dev_priv, PLANE_CTL(pipe, plane_id)); + surf_addr = intel_de_read_fw(dev_priv, PLANE_SURF(pipe, plane_id)); + + plane_ctl &= ~PLANE_CTL_ASYNC_FLIP; + + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), surf_addr); + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); + } + + intel_wait_for_vblank(dev_priv, crtc->pipe); +} + static void intel_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -6645,6 +6712,15 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, */ if (IS_GEN(dev_priv, 2) && planes_disabling(old_crtc_state, new_crtc_state)) intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + + /* + * WA for platforms where async address update enable bit + * is double buffered and only latched at start of vblank. + */ + if (old_crtc_state->uapi.async_flip && + !new_crtc_state->uapi.async_flip && + IS_GEN_RANGE(dev_priv, 9, 10)) + skl_disable_async_flip_wa(state, crtc, new_crtc_state); } static void intel_crtc_disable_planes(struct intel_atomic_state *state, @@ -6944,7 +7020,7 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, if (intel_crtc_has_dp_encoder(new_crtc_state)) intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(new_crtc_state); + intel_set_transcoder_timings(new_crtc_state); intel_set_pipe_src_size(new_crtc_state); if (new_crtc_state->has_pch_encoder) @@ -7068,6 +7144,45 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, reg, val); } +static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, + const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *master = to_intel_crtc(crtc_state->uapi.crtc); + struct intel_crtc_state *master_crtc_state; + struct drm_connector_state *conn_state; + struct drm_connector *conn; + struct intel_encoder *encoder = NULL; + int i; + + if (crtc_state->bigjoiner_slave) + master = crtc_state->bigjoiner_linked_crtc; + + master_crtc_state = intel_atomic_get_new_crtc_state(state, master); + + for_each_new_connector_in_state(&state->base, conn, conn_state, i) { + if (conn_state->crtc != &master->base) + continue; + + encoder = to_intel_encoder(conn_state->best_encoder); + break; + } + + if (!crtc_state->bigjoiner_slave) { + /* need to enable VDSC, which we skipped in pre-enable */ + intel_dsc_enable(encoder, crtc_state); + } else { + /* + * Enable sequence steps 1-7 on bigjoiner master + */ + intel_encoders_pre_pll_enable(state, master); + intel_enable_shared_dpll(master_crtc_state); + intel_encoders_pre_enable(state, master); + + /* and DSC on slave */ + intel_dsc_enable(NULL, crtc_state); + } +} + static void hsw_crtc_enable(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -7081,34 +7196,37 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; - intel_encoders_pre_pll_enable(state, crtc); - - if (new_crtc_state->shared_dpll) - intel_enable_shared_dpll(new_crtc_state); + if (!new_crtc_state->bigjoiner) { + intel_encoders_pre_pll_enable(state, crtc); - intel_encoders_pre_enable(state, crtc); + if (new_crtc_state->shared_dpll) + intel_enable_shared_dpll(new_crtc_state); - if (!transcoder_is_dsi(cpu_transcoder)) - intel_set_pipe_timings(new_crtc_state); + intel_encoders_pre_enable(state, crtc); + } else { + icl_ddi_bigjoiner_pre_enable(state, new_crtc_state); + } intel_set_pipe_src_size(new_crtc_state); + if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) + bdw_set_pipemisc(new_crtc_state); - if (cpu_transcoder != TRANSCODER_EDP && - !transcoder_is_dsi(cpu_transcoder)) - intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder), - new_crtc_state->pixel_multiplier - 1); + if (!new_crtc_state->bigjoiner_slave && !transcoder_is_dsi(cpu_transcoder)) { + intel_set_transcoder_timings(new_crtc_state); - if (new_crtc_state->has_pch_encoder) - intel_cpu_transcoder_set_m_n(new_crtc_state, - &new_crtc_state->fdi_m_n, NULL); + if (cpu_transcoder != TRANSCODER_EDP) + intel_de_write(dev_priv, PIPE_MULT(cpu_transcoder), + new_crtc_state->pixel_multiplier - 1); + + if (new_crtc_state->has_pch_encoder) + intel_cpu_transcoder_set_m_n(new_crtc_state, + &new_crtc_state->fdi_m_n, NULL); - if (!transcoder_is_dsi(cpu_transcoder)) { hsw_set_frame_start_delay(new_crtc_state); - hsw_set_pipeconf(new_crtc_state); } - if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) - bdw_set_pipemisc(new_crtc_state); + if (!transcoder_is_dsi(cpu_transcoder)) + hsw_set_pipeconf(new_crtc_state); crtc->active = true; @@ -7144,6 +7262,11 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (INTEL_GEN(dev_priv) >= 11) icl_pipe_mbus_enable(crtc); + if (new_crtc_state->bigjoiner_slave) { + trace_intel_pipe_enable(crtc); + intel_crtc_vblank_on(new_crtc_state); + } + intel_encoders_enable(state, crtc); if (psl_clkgate_wa) { @@ -7273,9 +7396,9 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) { if (phy == PHY_NONE) return false; - else if (IS_ROCKETLAKE(dev_priv)) + else if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return phy <= PHY_D; - else if (IS_ELKHARTLAKE(dev_priv)) + else if (IS_JSL_EHL(dev_priv)) return phy <= PHY_C; else if (INTEL_GEN(dev_priv) >= 11) return phy <= PHY_B; @@ -7285,11 +7408,11 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) { - if (IS_ROCKETLAKE(dev_priv)) + if (IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) return false; else if (INTEL_GEN(dev_priv) >= 12) return phy >= PHY_D && phy <= PHY_I; - else if (INTEL_GEN(dev_priv) >= 11 && !IS_ELKHARTLAKE(dev_priv)) + else if (INTEL_GEN(dev_priv) >= 11 && !IS_JSL_EHL(dev_priv)) return phy >= PHY_C && phy <= PHY_F; else return false; @@ -7297,23 +7420,23 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) { - if (IS_ROCKETLAKE(i915) && port >= PORT_D) - return (enum phy)port - 1; - else if (IS_ELKHARTLAKE(i915) && port == PORT_D) + if ((IS_DG1(i915) || IS_ROCKETLAKE(i915)) && port >= PORT_TC1) + return PHY_C + port - PORT_TC1; + else if (IS_JSL_EHL(i915) && port == PORT_D) return PHY_A; - return (enum phy)port; + return PHY_A + port - PORT_A; } enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port) { if (!intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv, port))) - return PORT_TC_NONE; + return TC_PORT_NONE; if (INTEL_GEN(dev_priv) >= 12) - return port - PORT_D; - - return port - PORT_C; + return TC_PORT_1 + port - PORT_TC1; + else + return TC_PORT_1 + port - PORT_C; } enum intel_display_power_domain intel_port_to_power_domain(enum port port) @@ -7438,6 +7561,9 @@ static u64 get_crtc_power_domains(struct intel_crtc_state *crtc_state) if (crtc_state->shared_dpll) mask |= BIT_ULL(POWER_DOMAIN_DISPLAY_CORE); + if (crtc_state->dsc.compression_enable) + mask |= BIT_ULL(intel_dsc_power_domain(crtc_state)); + return mask; } @@ -7484,7 +7610,7 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state, if (intel_crtc_has_dp_encoder(new_crtc_state)) intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(new_crtc_state); + intel_set_transcoder_timings(new_crtc_state); intel_set_pipe_src_size(new_crtc_state); if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { @@ -7552,7 +7678,7 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state, if (intel_crtc_has_dp_encoder(new_crtc_state)) intel_dp_set_m_n(new_crtc_state, M1_N1); - intel_set_pipe_timings(new_crtc_state); + intel_set_transcoder_timings(new_crtc_state); intel_set_pipe_src_size(new_crtc_state); i9xx_set_pipeconf(new_crtc_state); @@ -8026,7 +8152,7 @@ static bool intel_crtc_supports_double_wide(const struct intel_crtc *crtc) static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state) { - u32 pixel_rate = crtc_state->hw.adjusted_mode.crtc_clock; + u32 pixel_rate = crtc_state->hw.pipe_mode.crtc_clock; unsigned int pipe_w, pipe_h, pfit_w, pfit_h; /* @@ -8056,6 +8182,27 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state) pfit_w * pfit_h); } +static void intel_mode_from_crtc_timings(struct drm_display_mode *mode, + const struct drm_display_mode *timings) +{ + mode->hdisplay = timings->crtc_hdisplay; + mode->htotal = timings->crtc_htotal; + mode->hsync_start = timings->crtc_hsync_start; + mode->hsync_end = timings->crtc_hsync_end; + + mode->vdisplay = timings->crtc_vdisplay; + mode->vtotal = timings->crtc_vtotal; + mode->vsync_start = timings->crtc_vsync_start; + mode->vsync_end = timings->crtc_vsync_end; + + mode->flags = timings->flags; + mode->type = DRM_MODE_TYPE_DRIVER; + + mode->clock = timings->crtc_clock; + + drm_mode_set_name(mode); +} + static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); @@ -8063,19 +8210,75 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) if (HAS_GMCH(dev_priv)) /* FIXME calculate proper pipe pixel rate for GMCH pfit */ crtc_state->pixel_rate = - crtc_state->hw.adjusted_mode.crtc_clock; + crtc_state->hw.pipe_mode.crtc_clock; else crtc_state->pixel_rate = ilk_pipe_pixel_rate(crtc_state); } +static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state) +{ + struct drm_display_mode *mode = &crtc_state->hw.mode; < |
