| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: intel_display.c,v 1.9 2021/12/19 12:11:46 riastradh Exp $ */ | | 1 | /* $NetBSD: intel_display.c,v 1.10 2021/12/19 12:28:55 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright © 2006-2007 Intel Corporation | | 4 | * Copyright © 2006-2007 Intel Corporation |
5 | * | | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
7 | * copy of this software and associated documentation files (the "Software"), | | 7 | * copy of this software and associated documentation files (the "Software"), |
8 | * to deal in the Software without restriction, including without limitation | | 8 | * to deal in the Software without restriction, including without limitation |
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | | 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
10 | * and/or sell copies of the Software, and to permit persons to whom the | | 10 | * and/or sell copies of the Software, and to permit persons to whom the |
11 | * Software is furnished to do so, subject to the following conditions: | | 11 | * Software is furnished to do so, subject to the following conditions: |
12 | * | | 12 | * |
13 | * The above copyright notice and this permission notice (including the next | | 13 | * The above copyright notice and this permission notice (including the next |
14 | * paragraph) shall be included in all copies or substantial portions of the | | 14 | * paragraph) shall be included in all copies or substantial portions of the |
| @@ -17,27 +17,27 @@ | | | @@ -17,27 +17,27 @@ |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | | 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | | 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | | 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | | 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | | 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | | 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | * DEALINGS IN THE SOFTWARE. | | 23 | * DEALINGS IN THE SOFTWARE. |
24 | * | | 24 | * |
25 | * Authors: | | 25 | * Authors: |
26 | * Eric Anholt <eric@anholt.net> | | 26 | * Eric Anholt <eric@anholt.net> |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | __KERNEL_RCSID(0, "$NetBSD: intel_display.c,v 1.9 2021/12/19 12:11:46 riastradh Exp $"); | | 30 | __KERNEL_RCSID(0, "$NetBSD: intel_display.c,v 1.10 2021/12/19 12:28:55 riastradh Exp $"); |
31 | | | 31 | |
32 | #include "intel_display.h" /* for pipe_drmhack */ | | 32 | #include "intel_display.h" /* for pipe_drmhack */ |
33 | | | 33 | |
34 | #include <linux/i2c.h> | | 34 | #include <linux/i2c.h> |
35 | #include <linux/input.h> | | 35 | #include <linux/input.h> |
36 | #include <linux/intel-iommu.h> | | 36 | #include <linux/intel-iommu.h> |
37 | #include <linux/kernel.h> | | 37 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | | 38 | #include <linux/module.h> |
39 | #include <linux/dma-resv.h> | | 39 | #include <linux/dma-resv.h> |
40 | #include <linux/slab.h> | | 40 | #include <linux/slab.h> |
41 | | | 41 | |
42 | #include <drm/drm_atomic.h> | | 42 | #include <drm/drm_atomic.h> |
43 | #include <drm/drm_atomic_helper.h> | | 43 | #include <drm/drm_atomic_helper.h> |
| @@ -17319,107 +17319,131 @@ void intel_init_display_hooks(struct drm | | | @@ -17319,107 +17319,131 @@ void intel_init_display_hooks(struct drm |
17319 | dev_priv->display.commit_modeset_enables = skl_commit_modeset_enables; | | 17319 | dev_priv->display.commit_modeset_enables = skl_commit_modeset_enables; |
17320 | else | | 17320 | else |
17321 | dev_priv->display.commit_modeset_enables = intel_commit_modeset_enables; | | 17321 | dev_priv->display.commit_modeset_enables = intel_commit_modeset_enables; |
17322 | | | 17322 | |
17323 | } | | 17323 | } |
17324 | | | 17324 | |
17325 | void intel_modeset_init_hw(struct drm_i915_private *i915) | | 17325 | void intel_modeset_init_hw(struct drm_i915_private *i915) |
17326 | { | | 17326 | { |
17327 | intel_update_cdclk(i915); | | 17327 | intel_update_cdclk(i915); |
17328 | intel_dump_cdclk_state(&i915->cdclk.hw, "Current CDCLK"); | | 17328 | intel_dump_cdclk_state(&i915->cdclk.hw, "Current CDCLK"); |
17329 | i915->cdclk.logical = i915->cdclk.actual = i915->cdclk.hw; | | 17329 | i915->cdclk.logical = i915->cdclk.actual = i915->cdclk.hw; |
17330 | } | | 17330 | } |
17331 | | | 17331 | |
| | | 17332 | static int sanitize_watermarks_add_affected(struct drm_atomic_state *state) |
| | | 17333 | { |
| | | 17334 | struct drm_plane *plane; |
| | | 17335 | struct drm_crtc *crtc; |
| | | 17336 | |
| | | 17337 | drm_for_each_crtc(crtc, state->dev) { |
| | | 17338 | struct drm_crtc_state *crtc_state; |
| | | 17339 | |
| | | 17340 | crtc_state = drm_atomic_get_crtc_state(state, crtc); |
| | | 17341 | if (IS_ERR(crtc_state)) |
| | | 17342 | return PTR_ERR(crtc_state); |
| | | 17343 | } |
| | | 17344 | |
| | | 17345 | drm_for_each_plane(plane, state->dev) { |
| | | 17346 | struct drm_plane_state *plane_state; |
| | | 17347 | |
| | | 17348 | plane_state = drm_atomic_get_plane_state(state, plane); |
| | | 17349 | if (IS_ERR(plane_state)) |
| | | 17350 | return PTR_ERR(plane_state); |
| | | 17351 | } |
| | | 17352 | |
| | | 17353 | return 0; |
| | | 17354 | } |
| | | 17355 | |
17332 | /* | | 17356 | /* |
17333 | * Calculate what we think the watermarks should be for the state we've read | | 17357 | * Calculate what we think the watermarks should be for the state we've read |
17334 | * out of the hardware and then immediately program those watermarks so that | | 17358 | * out of the hardware and then immediately program those watermarks so that |
17335 | * we ensure the hardware settings match our internal state. | | 17359 | * we ensure the hardware settings match our internal state. |
17336 | * | | 17360 | * |
17337 | * We can calculate what we think WM's should be by creating a duplicate of the | | 17361 | * We can calculate what we think WM's should be by creating a duplicate of the |
17338 | * current state (which was constructed during hardware readout) and running it | | 17362 | * current state (which was constructed during hardware readout) and running it |
17339 | * through the atomic check code to calculate new watermark values in the | | 17363 | * through the atomic check code to calculate new watermark values in the |
17340 | * state object. | | 17364 | * state object. |
17341 | */ | | 17365 | */ |
17342 | static void sanitize_watermarks(struct drm_device *dev) | | 17366 | static void sanitize_watermarks(struct drm_i915_private *dev_priv) |
17343 | { | | 17367 | { |
17344 | struct drm_i915_private *dev_priv = to_i915(dev); | | | |
17345 | struct drm_atomic_state *state; | | 17368 | struct drm_atomic_state *state; |
17346 | struct intel_atomic_state *intel_state; | | 17369 | struct intel_atomic_state *intel_state; |
17347 | struct intel_crtc *crtc; | | 17370 | struct intel_crtc *crtc; |
17348 | struct intel_crtc_state *crtc_state; | | 17371 | struct intel_crtc_state *crtc_state; |
17349 | struct drm_modeset_acquire_ctx ctx; | | 17372 | struct drm_modeset_acquire_ctx ctx; |
17350 | int ret; | | 17373 | int ret; |
17351 | int i; | | 17374 | int i; |
17352 | | | 17375 | |
17353 | /* Only supported on platforms that use atomic watermark design */ | | 17376 | /* Only supported on platforms that use atomic watermark design */ |
17354 | if (!dev_priv->display.optimize_watermarks) | | 17377 | if (!dev_priv->display.optimize_watermarks) |
17355 | return; | | 17378 | return; |
17356 | | | 17379 | |
17357 | /* | | 17380 | state = drm_atomic_state_alloc(&dev_priv->drm); |
17358 | * We need to hold connection_mutex before calling duplicate_state so | | 17381 | if (WARN_ON(!state)) |
17359 | * that the connector loop is protected. | | 17382 | return; |
17360 | */ | | | |
17361 | drm_modeset_acquire_init(&ctx, 0); | | | |
17362 | retry: | | | |
17363 | ret = drm_modeset_lock_all_ctx(dev, &ctx); | | | |
17364 | if (ret == -EDEADLK) { | | | |
17365 | drm_modeset_backoff(&ctx); | | | |
17366 | goto retry; | | | |
17367 | } else if (WARN_ON(ret)) { | | | |
17368 | goto fail; | | | |
17369 | } | | | |
17370 | | | | |
17371 | state = drm_atomic_helper_duplicate_state(dev, &ctx); | | | |
17372 | if (WARN_ON(IS_ERR(state))) | | | |
17373 | goto fail; | | | |
17374 | | | 17383 | |
17375 | intel_state = to_intel_atomic_state(state); | | 17384 | intel_state = to_intel_atomic_state(state); |
17376 | | | 17385 | |
| | | 17386 | drm_modeset_acquire_init(&ctx, 0); |
| | | 17387 | |
| | | 17388 | retry: |
| | | 17389 | state->acquire_ctx = &ctx; |
| | | 17390 | |
17377 | /* | | 17391 | /* |
17378 | * Hardware readout is the only time we don't want to calculate | | 17392 | * Hardware readout is the only time we don't want to calculate |
17379 | * intermediate watermarks (since we don't trust the current | | 17393 | * intermediate watermarks (since we don't trust the current |
17380 | * watermarks). | | 17394 | * watermarks). |
17381 | */ | | 17395 | */ |
17382 | if (!HAS_GMCH(dev_priv)) | | 17396 | if (!HAS_GMCH(dev_priv)) |
17383 | intel_state->skip_intermediate_wm = true; | | 17397 | intel_state->skip_intermediate_wm = true; |
17384 | | | 17398 | |
17385 | ret = intel_atomic_check(dev, state); | | 17399 | ret = sanitize_watermarks_add_affected(state); |
17386 | if (ret) { | | 17400 | if (ret) |
17387 | /* | | 17401 | goto fail; |
17388 | * If we fail here, it means that the hardware appears to be | | 17402 | |
17389 | * programmed in a way that shouldn't be possible, given our | | 17403 | ret = intel_atomic_check(&dev_priv->drm, state); |
17390 | * understanding of watermark requirements. This might mean a | | 17404 | if (ret) |
17391 | * mistake in the hardware readout code or a mistake in the | | 17405 | goto fail; |
17392 | * watermark calculations for a given platform. Raise a WARN | | | |
17393 | * so that this is noticeable. | | | |
17394 | * | | | |
17395 | * If this actually happens, we'll have to just leave the | | | |
17396 | * BIOS-programmed watermarks untouched and hope for the best. | | | |
17397 | */ | | | |
17398 | WARN(true, "Could not determine valid watermarks for inherited state\n"); | | | |
17399 | goto put_state; | | | |
17400 | } | | | |
17401 | | | 17406 | |
17402 | /* Write calculated watermark values back */ | | 17407 | /* Write calculated watermark values back */ |
17403 | for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { | | 17408 | for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) { |
17404 | crtc_state->wm.need_postvbl_update = true; | | 17409 | crtc_state->wm.need_postvbl_update = true; |
17405 | dev_priv->display.optimize_watermarks(intel_state, crtc); | | 17410 | dev_priv->display.optimize_watermarks(intel_state, crtc); |
17406 | | | 17411 | |
17407 | to_intel_crtc_state(crtc->base.state)->wm = crtc_state->wm; | | 17412 | to_intel_crtc_state(crtc->base.state)->wm = crtc_state->wm; |
17408 | } | | 17413 | } |
17409 | | | 17414 | |
17410 | put_state: | | | |
17411 | drm_atomic_state_put(state); | | | |
17412 | fail: | | 17415 | fail: |
| | | 17416 | if (ret == -EDEADLK) { |
| | | 17417 | drm_atomic_state_clear(state); |
| | | 17418 | drm_modeset_backoff(&ctx); |
| | | 17419 | goto retry; |
| | | 17420 | } |
| | | 17421 | |
| | | 17422 | /* |
| | | 17423 | * If we fail here, it means that the hardware appears to be |
| | | 17424 | * programmed in a way that shouldn't be possible, given our |
| | | 17425 | * understanding of watermark requirements. This might mean a |
| | | 17426 | * mistake in the hardware readout code or a mistake in the |
| | | 17427 | * watermark calculations for a given platform. Raise a WARN |
| | | 17428 | * so that this is noticeable. |
| | | 17429 | * |
| | | 17430 | * If this actually happens, we'll have to just leave the |
| | | 17431 | * BIOS-programmed watermarks untouched and hope for the best. |
| | | 17432 | */ |
| | | 17433 | WARN(ret, "Could not determine valid watermarks for inherited state\n"); |
| | | 17434 | |
| | | 17435 | drm_atomic_state_put(state); |
| | | 17436 | |
17413 | drm_modeset_drop_locks(&ctx); | | 17437 | drm_modeset_drop_locks(&ctx); |
17414 | drm_modeset_acquire_fini(&ctx); | | 17438 | drm_modeset_acquire_fini(&ctx); |
17415 | } | | 17439 | } |
17416 | | | 17440 | |
17417 | static void intel_update_fdi_pll_freq(struct drm_i915_private *dev_priv) | | 17441 | static void intel_update_fdi_pll_freq(struct drm_i915_private *dev_priv) |
17418 | { | | 17442 | { |
17419 | if (IS_GEN(dev_priv, 5)) { | | 17443 | if (IS_GEN(dev_priv, 5)) { |
17420 | u32 fdi_pll_clk = | | 17444 | u32 fdi_pll_clk = |
17421 | I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK; | | 17445 | I915_READ(FDI_PLL_BIOS_0) & FDI_PLL_FB_CLOCK_MASK; |
17422 | | | 17446 | |
17423 | dev_priv->fdi_pll_freq = (fdi_pll_clk + 2) * 10000; | | 17447 | dev_priv->fdi_pll_freq = (fdi_pll_clk + 2) * 10000; |
17424 | } else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) { | | 17448 | } else if (IS_GEN(dev_priv, 6) || IS_IVYBRIDGE(dev_priv)) { |
17425 | dev_priv->fdi_pll_freq = 270000; | | 17449 | dev_priv->fdi_pll_freq = 270000; |
| @@ -17640,27 +17664,27 @@ int intel_modeset_init(struct drm_i915_p | | | @@ -17640,27 +17664,27 @@ int intel_modeset_init(struct drm_i915_p |
17640 | /* | | 17664 | /* |
17641 | * If the fb is shared between multiple heads, we'll | | 17665 | * If the fb is shared between multiple heads, we'll |
17642 | * just get the first one. | | 17666 | * just get the first one. |
17643 | */ | | 17667 | */ |
17644 | intel_find_initial_plane_obj(crtc, &plane_config); | | 17668 | intel_find_initial_plane_obj(crtc, &plane_config); |
17645 | } | | 17669 | } |
17646 | | | 17670 | |
17647 | /* | | 17671 | /* |
17648 | * Make sure hardware watermarks really match the state we read out. | | 17672 | * Make sure hardware watermarks really match the state we read out. |
17649 | * Note that we need to do this after reconstructing the BIOS fb's | | 17673 | * Note that we need to do this after reconstructing the BIOS fb's |
17650 | * since the watermark calculation done here will use pstate->fb. | | 17674 | * since the watermark calculation done here will use pstate->fb. |
17651 | */ | | 17675 | */ |
17652 | if (!HAS_GMCH(i915)) | | 17676 | if (!HAS_GMCH(i915)) |
17653 | sanitize_watermarks(dev); | | 17677 | sanitize_watermarks(i915); |
17654 | | | 17678 | |
17655 | /* | | 17679 | /* |
17656 | * Force all active planes to recompute their states. So that on | | 17680 | * Force all active planes to recompute their states. So that on |
17657 | * mode_setcrtc after probe, all the intel_plane_state variables | | 17681 | * mode_setcrtc after probe, all the intel_plane_state variables |
17658 | * are already calculated and there is no assert_plane warnings | | 17682 | * are already calculated and there is no assert_plane warnings |
17659 | * during bootup. | | 17683 | * during bootup. |
17660 | */ | | 17684 | */ |
17661 | ret = intel_initial_commit(dev); | | 17685 | ret = intel_initial_commit(dev); |
17662 | if (ret) | | 17686 | if (ret) |
17663 | DRM_DEBUG_KMS("Initial commit in probe failed.\n"); | | 17687 | DRM_DEBUG_KMS("Initial commit in probe failed.\n"); |
17664 | | | 17688 | |
17665 | return 0; | | 17689 | return 0; |
17666 | } | | 17690 | } |