Imre Deak [Tue, 16 Apr 2024 22:10:05 +0000 (01:10 +0300)]
drm/i915/dp_mst: Sanitize calculating the DSC DPT bpp limit
Instead of checking each compressed bpp value against the maximum
DSC/DPT bpp, simplify things by calculating the maximum bpp upfront and
limiting the range of bpps looped over using this maximum.
While at it add a comment about the origin of the DSC/DPT bpp limit.
Imre Deak [Tue, 16 Apr 2024 22:10:03 +0000 (01:10 +0300)]
drm/i915/dp_mst: Account for channel coding efficiency in the DSC DPT bpp limit
The DSC DPT interface BW limit check should take into account the link
clock's (aka DDI clock in bspec) channel coding efficiency overhead.
Bspec suggests that the FEC overhead needs to be applied, however HW
people claim this isn't the case, nor is any overhead applicable.
However based on testing various 5k/6k modes both on the DELL U3224KBA
monitor and the Unigraf UCD-500 CTS test device, both the channel coding
efficiency (which includes the FEC overhead) and an additional 3%
overhead must be accounted for to get these modes working.
Bspec: 49259
v2:
- Apply an additional 3% overhead, add a commit log and code comment
about these overheads and the relation to the Bspec BW limit formula.
Imre Deak [Tue, 16 Apr 2024 22:10:01 +0000 (01:10 +0300)]
drm/i915/dp_mst: Fix symbol clock when calculating the DSC DPT bpp limit
The expected link symbol clock unit when calculating the DSC DPT bpp
limit is kSymbols/sec, aligning with the dotclock's kPixels/sec unit
based on the crtc clock. As opposed to this port_clock is used - which
has a 10 kbits/sec unit - with the resulting symbol clock in 10
kSymbols/sec units (disregarding the rounding error for the 13.5Gbps
rate). Fix the calculation using the expected 10x factor.
Imre Deak [Tue, 16 Apr 2024 22:10:00 +0000 (01:10 +0300)]
drm/i915/dp: Fix DSC line buffer depth programming
Fix the calculation of the DSC line buffer depth. This is limited both
by the source's and sink's maximum line buffer depth, but the former one
was not taken into account. On all Intel platform's the source's maximum
buffer depth is 13, so the overall limit is simply the minimum of the
source/sink's limit, regardless of the DSC version.
This leaves the DSI DSC line buffer depth calculation as-is, trusting
VBT.
On DSC version 1.2 for sinks reporting a maximum line buffer depth of 16
the line buffer depth was incorrectly programmed as 0, leading to a
corruption in color gradients / lines on the decompressed screen image.
drm/i915/display: force qgv check after the hw state readout
The current intel_bw_atomic_check do not check the possbility
of a sagv configuration change after the hw state readout.
Hence cannot update the sagv configuration until some other
relevant changes like data rates, number of planes etc. happen.
Introduce a flag to force qgv check in such cases.
Stanislav Lisovskiy [Fri, 5 Apr 2024 11:35:32 +0000 (14:35 +0300)]
drm/i915/display: handle systems with duplicate psf gv points
There could be multiple qgv and psf gv points with similar values.
Apparently pcode's handling of psf and qgv points are different. For
qgv case, pcode sets whatever is asked by the driver. But in case
of psf gv points, it compares the bw from points before setting the
mask. This can cause problems in scenarios where we have to disable
sagv by setting the highest bw point and there could be multiple
points with highest bw. So to set the maximum psf gv point, find
out all the points with the highest bw and set all together.
v1: - use the same treatment to qgv points as well (Vinod)
v2: - pcode confirms that for qgv points, it sets whatever the
driver sets (Vinod)
Stanislav Lisovskiy [Fri, 5 Apr 2024 11:35:31 +0000 (14:35 +0300)]
drm/i915/display: Disable SAGV on bw init, to force QGV point recalculation
Problem is that on some platforms, we do get QGV point mask in wrong
state on boot. However driver assumes it is set to 0
(i.e all points allowed), however in reality we might get them all
restricted, causing issues.
Lets disable SAGV initially to force proper QGV point state.
If more QGV points are available, driver will recalculate and update
those then after next commit.
v2: - Added trace to see which QGV/PSF GV point is used when SAGV is
disabled.
v3: - Move force disable function to intel_bw_init in order to initialize
bw state as well, so that hw/sw are immediately in sync after init.
v4: - Don't try sending PCode request, seems like it is not possible at
intel_bw_init, however assigning bw->state to be restricted as if
SAGV is off, still forces driveer to send PCode request anyway on
next modeset, so the solution still works.
However we still need to address the case, when no display is
connected, which anyway requires much more changes.
v5: - Put PCode request back and apply temporary hack to make the
request succeed(in case if there 2 PSF GV points with same BW, PCode
accepts only if both points are restricted/unrestricted same time)
- Fix argument sequence for adl_qgv_bw(Ville Syrjälä)
v6: - Fix wrong platform checks, not to break everything else.
v7: - Split the handling of quplicate QGV/PSF GV points (Vinod)
Restrict force disable to display version below 14 (Vinod)
Stanislav Lisovskiy [Fri, 5 Apr 2024 11:35:29 +0000 (14:35 +0300)]
drm/i915/display: Extract code required to calculate max qgv/psf gv point
We need that in order to force disable SAGV in next patch.
Also it is beneficial to separate that code, as in majority cases,
when SAGV is enabled, we don't even need those calculations.
Also we probably need to determine max PSF GV point as well, however
currently we don't do that when we disable SAGV, which might be
actually causing some issues in that case.
v2: - Introduce helper adl_qgv_bw(counterpart to adl_psf_bw)
(Ville Syrjälä)
- Don't restrict psf gv points for SAGV disable case
(Ville Syrjälä)
v3: - Update icl_max_bw_qgv_point_mask to return max qgv point
mask (Vinod)
v4: - Minor changes in icl_find_qgv_points (Vinod)
v5: - use max_bw_point instead of max_bw_point_mask (stan)
Stanislav Lisovskiy [Fri, 5 Apr 2024 11:35:28 +0000 (14:35 +0300)]
drm/i915/display: Add meaningful traces for QGV point info error handling
For debug purposes we need those - error path won't flood the log,
however there has been already numerous cases, when due to lack
of debugs, we couldn't immediately tell what was the problem on
customer machine, which slowed down the investigation, requiring
to get access to target device and adding those traces manually.
v2: - Make the debug more generic and move it to intel_dram_detect
(Gustavo Sousa)
v3: - Use %u for unsigned variable in debug prints (Gustavo)
Jani Nikula [Wed, 17 Apr 2024 13:02:46 +0000 (16:02 +0300)]
drm/i915/de: allow intel_display and drm_i915_private for de functions
It would be too much noise to convert the intel_de_* functions from
using struct drm_i915_private to struct intel_display all at once. Add
generic wrappers using __to_intel_display() to accept both.
Jani Nikula [Wed, 17 Apr 2024 13:02:45 +0000 (16:02 +0300)]
drm/i915/dmc: convert dmc wakelock interface to struct intel_display
Convert the dmc wakelock interface to struct intel_display instead of
struct drm_i915_private. We'll want to convert the intel_de interfaces,
and there's a bit of coupling between the two, so start here.
Jani Nikula [Wed, 17 Apr 2024 13:02:41 +0000 (16:02 +0300)]
drm/i915: add generic __to_intel_display()
Add generic __to_intel_display() macro that accepts either struct
drm_i915_private * or struct intel_display *. This is to be used for
transitional stuff that eventually needs to be converted to use struct
intel_display *, and therefore is not part of to_intel_display().
Add new intel_display_conversion.h to host the helper to avoid
duplication between xe and i915 drivers.
Convert various pointers to struct intel_display * using _Generic().
Add some macro magic to make adding new conversions easier, and somewhat
abstract the need to cast each generic association. The cast is required
because all associations needs to compile, regardless of the type and
the generic selection.
The use of *p in the generic selection assignment expression removes the
need to add separate associations for const pointers.
Note: This intentionally does *not* cover struct drm_i915_private or
struct xe_device. They are not to be used in the long run, so avoid
using this macro for them.
As a baby step towards making struct intel_display the main data
structure for display, add a backpointer to struct drm_device that can
be used instead of &i915->drm.
Ville Syrjälä [Fri, 12 Apr 2024 18:27:03 +0000 (21:27 +0300)]
drm/i915: Suck snps/cx0 PLL states into dpll_hw_state
For some reason the snps/cx0 PLL states were added into
a union alongside dpll_hw_state. Just suck them into
dpll_hw_state so that we don't have so many levels of
unions/etc.
TODO: Get rid of 'clock' from the snps/cx0 PLL states
as it is not a register values and thus doesn't
belong there
Ville Syrjälä [Fri, 12 Apr 2024 18:27:02 +0000 (21:27 +0300)]
drm/i915: Unionize dpll_hw_state
intel_dpll_hw_state contains space for all possible PLL
register values across all platforms. That is rather wasteful
as each machine only needs to store the registers values
that are appropriate for the platform.
Turn intel_dpll_hw_state into a union so that we don't
waste memory for the register values of other platforms.
And let's use an anonymous union so that we don't have
to do tons of s/struct/union/ all over the place.
Ville Syrjälä [Fri, 12 Apr 2024 18:27:01 +0000 (21:27 +0300)]
drm/i915: Carve up struct intel_dpll_hw_state
struct intel_dpll_hw_state has a spot for all possible
PLL registers across all platforms (well, apart from
cx0/snps). This makes it rather confusing when trying to
figure out which members belong to which platform(s).
Split the struct up into five different platform specific
sub-structures. For now this will actually increase the size
a little bit as we have to duplicate a few members from
skl to icl, but that will be remedied soon when we turn
the thing into a union.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:56 +0000 (21:26 +0300)]
drm/i915: Inline {i9xx,ilk}_update_pll_dividers()
Now that *_compute_dpll() are no longer a mess
{i9xx,ilk}_update_pll_dividers() don't serve any real
purpose anymore. Just inline them into the callers.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:55 +0000 (21:26 +0300)]
drm/i915: Extract {i9xx,i8xx,ilk,vlv,chv}_dpll()
The *_compute_dpll() functions generally contain
two things:
- huge pile of inline code to calculate the DPLL
register value
- a few calls to helpers to calculate the
DPLL_MD and FP register values
Pull the DPLL register value calculations into a helpers
as well, so that *_compute_dpll() can focus on higher
level tasks.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:53 +0000 (21:26 +0300)]
drm/i915: Pass the PLL hw_state to pll->enable()
Stop rummaging around inside pll->state directly in the low
level pll->enable() functions, and instead let the higher level
code figure out where the correct state is stored and pass it in.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:52 +0000 (21:26 +0300)]
drm/i915: Extract i9xx_dpll_get_hw_state()
Start making the GMCH DPLL code a bit more like the more modern
platforms by separating out the DPLL hw state readout from the
rest of the pipe readout.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:49 +0000 (21:26 +0300)]
drm/i915: Introduce some local PLL state variables
Spinkle local PLL hw_state variables into various low
level PLL functions. Will make subsequent changes cleaner
when we don't have to touch so many places when renaming
struct members and whatnot.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:48 +0000 (21:26 +0300)]
drm/i915: Rename PLL hw_state variables/arguments
We have zero consistency in out PLL state naming scheme. Try
to unify things a bit by using 'dpll_hw_state' for high level
stuff and just 'hw_state' for low level stuff. Currently both
are the same, but I want to unionize intel_dpll_hw_state at
which point using different names can make it more clear whether
we're talking about the whole union or just the embedded platform
specific struct.
Ville Syrjälä [Fri, 12 Apr 2024 18:26:47 +0000 (21:26 +0300)]
drm/i915: Use printer for the rest of PLL debugfs dump
Since we now have the printer around for intel_dpll_dump_hw_state()
use it for all the other PLL prints as well. Just to make the thing
looks less crazy.
drm/i915/display: add module parameter to enable DMC wakelock
This feature should be disabled by default until properly tested and
mature. Add a module parameter to enable the feature for testing,
while keeping it disabled by default for now.
In order to reduce the DC5->DC2 restore time, wakelocks have been
introduced in DMC so the driver can tell it when registers and other
memory areas are going to be accessed and keep their respective blocks
awake.
Implement this in the driver by adding the concept of DMC wakelocks.
When the driver needs to access memory which lies inside pre-defined
ranges, it will tell DMC to set the wakelock, access the memory, then
wait for a while and clear the wakelock.
The wakelock state is protected in the driver with spinlocks to
prevent concurrency issues.
Stanislav Lisovskiy [Tue, 9 Apr 2024 16:35:00 +0000 (19:35 +0300)]
drm/i915: Handle joined pipes inside hsw_crtc_enable()
Handle only bigjoiner masters in skl_commit_modeset_enables/disables,
slave crtcs should be handled by master hooks. Same for encoders.
That way we can also remove a bunch of checks like intel_crtc_is_bigjoiner_slave.
v2: - Moved skl_pfit_enable, intel_dsc_enable, intel_crtc_vblank_on to intel_enable_ddi,
so that it is now finally symmetrical with the disable case, because currently
for some weird reason we are calling those from skl_commit_modeset_enables, while
for the disable case those are called from the ddi disable hooks.
v3: - Create intel_ddi_enable_hdmi_or_sst symmetrical to
intel_ddi_post_disable_hdmi_or_sst and move it also under non-mst check.
v4: - Fix intel_enable_ddi sequence
- Call intel_crtc_update_active_timings for slave pipes as well
[v5: vsyrjala: Use the name 'pipe_crtc' for the per-pipe crtc pointer
Use consistent style and naming
Protect macro arguments properly
Drop superfluous changes to the modeset sequence,
this now follows the old non-joiner sequence 100%
apart from just looping in places]
Signed-off-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> Tested-by: Vidya Srinivas <vidya.srinivas@intel.com> Reviewed-by: Manasi Navare <navaremanasi@chromium.org> #v4? Co-developed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240409163502.29633-5-ville.syrjala@linux.intel.com
Ville Syrjälä [Tue, 9 Apr 2024 16:34:59 +0000 (19:34 +0300)]
drm/i915: Handle joined pipes inside hsw_crtc_disable()
Reorganize the crtc disable path to only deal with the
master pipes/transcoders in intel_old_crtc_state_disables()
and offload the handling of joined pipes to hsw_crtc_disable().
This makes the whole thing much more sensible since we can
actually control the order in which we do the per-pipe vs.
per-transcoder modeset steps.
v2: Use the name 'pipe_crtc' for the per-pipe crtc pointer
Ville Syrjälä [Tue, 9 Apr 2024 16:34:58 +0000 (19:34 +0300)]
drm/i915: Utilize intel_crtc_joined_pipe_mask() more
Unify the master vs. slave handling in
intel_ddi_post_disable_hdmi_or_sst() by looping over all the
pipes in one go.
This also lets us move the intel_crtc_vblank_off() calls to
happen in a consistent place vs. the transcoder disable.
Previously we did the master vs. slaves on different sides
of that.
v2: Use the name 'pipe_crtc' for the per-pipe crtc pointer
Extract the "not-MST" stuff from intel_ddi_post_disable() so that
the whole thing isn't so cluttered.
The bigjoiner slave handling was outside of the !MST check,
but it really should have been inside it as its the counterpart
to the master handling inside the check. So we pull that
in as well. There is no functional change here as we don't
currently support bigjoiner+MST anyway.
v2: Rebase
v3: Actually extract the slave code as claimed in
the commit message (presumably a rebase fail in v2)
Imre Deak [Mon, 29 Jan 2024 17:55:32 +0000 (19:55 +0200)]
drm/i915/mtl+: Disable DP/DSC SF insertion at EOL WA
Disable the workaround inserting an SF symbol between the last DSC EOC
symbol and the subsequent BS symbol. The WA is enabled by default -
based on the register's reset value - and Bspec requires disabling it
explicitly. Bspec doesn't provide an actual WA ID for this.
Imre Deak [Mon, 29 Jan 2024 17:55:29 +0000 (19:55 +0200)]
drm/i915/adlp: Add MST short HBlank WA (Wa_14014143976)
Add a workaround to fix BS jitter issues on MST links if the HBLANK
period is less than 1 MTP. The WA applies only to UHBR rates while on
non-UHBR the specification requires disabling it explicitly - presumedly
because the register's reset value has the WA enabled.
Imre Deak [Mon, 29 Jan 2024 17:55:28 +0000 (19:55 +0200)]
drm/i915/adlp: Add MST FEC BS jitter WA (Wa_14013163432)
Add a workaround to fix BS (blank start) to BS jitter issues on MST
links when FEC is enabled. Neither Bspec requires this nor Windows
clears the WA when disabling the output - presumedly because
CHICKEN_MISC_3 gets reset after disabling the pipe/transcoder - so
follow suit.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:33 +0000 (00:34 +0300)]
drm/i915/mst: Check intel_dp_joiner_needs_dsc()
intel_dp_mst_compute_config() is missing the "does the
joiner need DSC?" check despite claiming to have a lot
of other joiner/dsc stuff in there (albeit disabled).
Replicate the logic from the SST side.
Jani Nikula [Fri, 5 Apr 2024 20:26:25 +0000 (23:26 +0300)]
drm/i915: use check_add_overflow() and drop local variants
Prefer common check_add_overflow() from overflow.h over the locally
rolled versions of it. While check_add_overflow() does require a
variable to assign to, unlike add_overflows_t(), it's still better than
having multiple versions around.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:25 +0000 (00:34 +0300)]
drm/i915: Update pipes in reverse order for bigjoiner
With bigjoiner the master crtc is the one that will send out the
uapi event/etc. We want that to happen after all the slaves are
done, so let's try to do the commits in reverse order so that
the master comes last.
Even worse, the modeset helper will simply complete the commit
on the slave pipe immediately as it consider the crtc to be inactive
(it can't see our crtc_state->hw.active/etc.).
With regular sync updates this generally doesn't matter all that
much as the slave pipe should typically finish its work during the
same frame as the master pipe. However in case the slave pipe's commit
slips into the next frame we end up in a bit of trouble. This is most
visible with either async flips (currently disabled with bigjoiner
exactly for this reason), and DSB gamma updates. With DSB the problem
happens because the DSB itself will wait until the next start vblank
before starting to execute. So if the master pipe already finished its
commit and the DSB on the slave pipe is still waiting for the next
vblank we will assume the DSB as gotten stuck and terminate it.
Reversing the commit order should ameliarate this for the most part
as the master pipe is guaranteed to start its commit after the slave
pipe started. The one thing that can still screw us over is the fact
that we aren't necessarily going to commit the pipes in the reverse
order as the actual order is dictated by the DDB overlap avoidance.
But that can only happen while other pipes are being enabled/disabled,
and so in the normal steady state we should be safe.
The full fix will involve making the commit machinery aware of the
slave pipes and not finish their commits prematurely. But that
will involve a bit more work than this. And this commit order
reversal will still be beneficial to avoid userspace getting an
-EBUSY from the following page flip if the second pipe's commit
does stretch into the next frame.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:30 +0000 (00:34 +0300)]
drm/i915: Fix intel_modeset_pipe_config_late() for bigjoiner
Currently intel_modeset_pipe_config_late() is called after the
bigjoiner state copy, and it will actually not do anything for
bigjoiner slaves. This can lead to a mismatched state between
the master and slave.
The two things that we do in the encoder .compute_config_late()
hook are mst master transcoder and port sync master transcoder
elections. So if either of either MST or port sync is combined
with bigjoiner then we can see the mismatch.
Currently this problem is more or less theoretical; MST+bigjoiner
has not been implemented yet, and port sync+bigjoiner would
require a tiled display with >5k tiles (or a very high
dotclock per tile). Although we do have kms_tiled_display in
igt which can fake a tiled display, and we can now force bigjoiner
via debugfs, so it is possible to trigger this if you try hard
enough.
Reorder the code such that intel_modeset_pipe_config_late()
will be called before the bigjoiner state copy happens so
that both pipes will end up with the same state.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:29 +0000 (00:34 +0300)]
drm/i915/vrr: Disable VRR when using bigjoiner
All joined pipes share the same transcoder/timing generator.
Currently we just do the commits per-pipe, which doesn't really
work if we need to change switch between non-VRR and VRR timings
generators on the fly, or even when sending the push to the
transcoder. For now just disable VRR when bigjoiner is needed.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:28 +0000 (00:34 +0300)]
drm/i915: Disable live M/N updates when using bigjoiner
All joined pipes share the same transcoder/timing generator.
Currently we just do the commits per-pipe, which doesn't really
work if we need to change the timings at the same time. For
now just disable live M/N updates when bigjoiner is needed.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:27 +0000 (00:34 +0300)]
drm/i915: Disable port sync when bigjoiner is used
The current modeset sequence can't handle port sync and bigjoiner
at the same time. Refuse port sync when bigjoiner is needed,
at least until we fix the modeset sequence.
Ville Syrjälä [Thu, 4 Apr 2024 21:34:26 +0000 (00:34 +0300)]
drm/i915/psr: Disable PSR when bigjoiner is used
Bigjoiner seem to be causing all kinds of grief to the PSR
code currently. I don't believe there is any hardware issue
but the code simply not handling this correctly. For now
just disable PSR when bigjoiner is needed.
Jani Nikula [Fri, 5 Apr 2024 19:37:40 +0000 (22:37 +0300)]
drm/i915: move i915_fixed.h to display/intel_fixed.h
All the users are in display, move the fixed point header under
display. We could also consider making these more general purpose
things, but that takes a bunch more effort. This allows the immediate
cleanup of xe compat i915_fixed.h.
Jani Nikula [Fri, 5 Apr 2024 19:37:39 +0000 (22:37 +0300)]
drm/i915/dmc: define firmware URL locally
Avoid the dependency on intel_uc_fw.h, and allow removal of xe compat
intel_uc_fw.h. If there needs to be duplication of the URL, at least
have the duplication in a sensible way.
Unify enabling and disabling of psr/panel replay for a sink. Modify
intel_psr_enable_sink accordingly and use it for both cases.
v3:
- move psr2_su_region_et_valid to be check for PSR2 only
v2:
- enable panel replay for sink before link training
- write ALPM_CONFIG only for PSR
- add DP_PSR_CRC_VERIFICATION only for PSR
- take care of disable sink as well
drm/i915/psr: Check possible errors for panel replay as well
On HPD interrupt we want to check if the reason for HPD was some panel
replay error detected by monitor/panel. This is already done for PSR. We
want to do this for panel replay as well. Modify intel_psr_short_pulse to
support panel replay as well.
drm/i915/psr: Intel_psr_pause/resume needs to support panel replay
Currently intel_psr_pause and intel_psr_resume do nothing in case of panel
replay. Change them to perform pause and return also in case of panel
replay.
drm/i915/psr: Set intel_crtc_state->has_psr on panel replay as well
Current code is setting only intel_crtc_state->has_panel_replay in panel
replay case. There are lots of stuff behind intel_crtc_state->has_psr that
is needed for panel replay as well. Instead of converting each check to
has_psr || has_panel_replay set has_psr in case of panel replay as
well. Code can then differentiate between psr and panel replay by using
intel_crtc_state->has_panel_replay.
Ville Syrjälä [Fri, 29 Mar 2024 01:23:31 +0000 (03:23 +0200)]
drm/i915: Fix i915_display_info output when connectors are not active
Currently intel_connector_info(), which prints the per-connector
output for i915_display_info, just bails out early if the connector
doesn't have a current encoder. That leads to very confusing output
where some of your connected (and properly detected) outputs appear
to have no enumerated modes.
Get rid of the encoder stuff and just rely on the connector itself
so that the output is always consistent.
Initialize HDCP capability variables to false to avoid UBSAN
warning in boolean value as some functions invoking this could
return without filling the two capability values.
Ville Syrjälä [Tue, 2 Apr 2024 15:50:16 +0000 (18:50 +0300)]
drm/i915: Optimize out redundant dbuf slice updates
if the new dbuf slices are a superset of the old
dbuf slices then we don't have to do anything in
intel_dbuf_post_plane_update(). Restructure the code
to skip such redundant dbuf slice updates. The main
benefit is slightly less confusing logs.
Currently we can't change MBUS join status without doing a modeset,
because we are lacking mechanism to synchronize those with vblank.
However then this means that we can't do a fastset, if there is a need
to change MBUS join state. Fix that by implementing such change.
We already call correspondent check and update at pre_plane dbuf update,
so the only thing left is to have a non-modeset version of that.
If active pipes stay the same then fastset is possible and only MBUS
join state/ddb allocation updates would be committed.
The full mbus/cdclk sequence will look as follows:
1. disable pipes
2. increase cdclk if necessary
2.1 reprogram cdclk
2.2 update dbuf tracker value
3. enable mbus joining if necessary
3.1 update mbus_ctl
3.2 update dbuf tracker value
4. reallocate dbuf for planes on active pipes
5. disable mbus joining if necessary
5.1 update dbuf tracker value
5.2 update mbus_ctl
6. enable pipes
7. decrease cdclk if necessary
7.1 update dbuf tracker value
7.2 reprogram cdclk
And in order to keep things in sync we need:
Step 2:
- mbus_join == old
- mdclk/cdclk ratio == new
Step 3:
- mbus_join == new
- mdclk/cdclk ratio == old when cdclk is changing in step 7
- mdclk/cdclk ratio == new when cdclk is changing in step 2
Step 5:
- mbus_join == new
- mdclk/cdclk ratio == old when cdclk is changing in step 7
- mdclk/cdclk ratio == new when cdclk is changing in step 2
Step 7:
- mbus_join == new
- mdclk/cdclk ratio == new
v2: - Removed redundant parentheses(Ville Syrjälä)
- Constified new_crtc_state in intel_mbus_joined_pipe(Ville Syrjälä)
- Removed pipe_select variable(Ville Syrjälä)
[v3: vsyrjala: Correctly sequence vs. cdclk updates,
properly describe the full sequence,
shuffle code around to make the diff more legible,
streamline a few things]
[v4: vsyrjala: Move the intel_cdclk_is_decreasing_later() stuff
to a separate patch]