diff --git a/.mailmap b/.mailmap index 59c9a841bf71..16b704e1d5d3 100644 --- a/.mailmap +++ b/.mailmap @@ -20,6 +20,7 @@ Adam Oldham Adam Radford Adriana Reus Adrian Bunk +Ajay Kaher Akhil P Oommen Alan Cox Alan Cox @@ -36,6 +37,17 @@ Alexei Avshalom Lazar Alexei Starovoitov Alexei Starovoitov Alexei Starovoitov +Alexey Makhalov +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder Alex Hung Alex Shi Alex Shi @@ -96,6 +108,8 @@ Ben Widawsky Ben Widawsky Ben Widawsky Benjamin Poirier +Benjamin Tissoires +Benjamin Tissoires Bjorn Andersson Bjorn Andersson Bjorn Andersson @@ -110,6 +124,7 @@ Brendan Higgins Brian Avery Brian King Brian Silverman +Bryan Tan Cai Huoqing Can Guo Carl Huang @@ -443,7 +458,8 @@ Mythri P K Nadav Amit Nadav Amit Nadia Yvette Chambers William Lee Irwin III -Naoya Horiguchi +Naoya Horiguchi +Naoya Horiguchi Nathan Chancellor Neeraj Upadhyay Neil Armstrong @@ -521,6 +537,7 @@ Rémi Denis-Courmont Ricardo Ribalda Ricardo Ribalda Ricardo Ribalda Delgado Ricardo Ribalda +Richard Genoud Richard Leitner Richard Leitner Richard Leitner @@ -529,6 +546,7 @@ Rocky Liao Roman Gushchin Roman Gushchin Roman Gushchin +Ronak Doshi Muchun Song Muchun Song Ross Zwisler @@ -651,6 +669,7 @@ Viresh Kumar Viresh Kumar Viresh Kumar Viresh Kumar +Vishnu Dasa Vivek Aknurwar Vivien Didelot Vlad Dogaru diff --git a/CREDITS b/CREDITS index c55c5a0ee4ff..0107047f807b 100644 --- a/CREDITS +++ b/CREDITS @@ -3146,6 +3146,10 @@ S: Triftstra=DFe 55 S: 13353 Berlin S: Germany +N: Gustavo Pimental +E: gustavo.pimentel@synopsys.com +D: PCI driver for Synopsys DesignWare + N: Emanuel Pirker E: epirker@edu.uni-klu.ac.at D: AIC5800 IEEE 1394, RAW I/O on 1394 diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index cce768afec6b..25a04cda4c2c 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically, the BHB might be shared across privilege levels even in the presence of Enhanced IBRS. -Currently the only known real-world BHB attack vector is via -unprivileged eBPF. Therefore, it's highly recommended to not enable -unprivileged eBPF, especially when eIBRS is used (without retpolines). -For a full mitigation against BHB attacks, it's recommended to use -retpolines (or eIBRS combined with retpolines). +Previously the only known real-world BHB attack vector was via unprivileged +eBPF. Further research has found attacks that don't require unprivileged eBPF. +For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or +use the BHB clearing sequence. Attack scenarios ---------------- @@ -430,6 +429,23 @@ The possible values in this file are: 'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB =========================== ======================================================= + - Branch History Injection (BHI) protection status: + +.. list-table:: + + * - BHI: Not affected + - System is not affected + * - BHI: Retpoline + - System is protected by retpoline + * - BHI: BHI_DIS_S + - System is protected by BHI_DIS_S + * - BHI: SW loop, KVM SW loop + - System is protected by software clearing sequence + * - BHI: Vulnerable + - System is vulnerable to BHI + * - BHI: Vulnerable, KVM: SW loop + - System is vulnerable; KVM is protected by software clearing sequence + Full mitigation might require a microcode update from the CPU vendor. When the necessary microcode is not available, the kernel will report vulnerability. @@ -484,7 +500,11 @@ Spectre variant 2 Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at boot, by setting the IBRS bit, and they're automatically protected against - Spectre v2 variant attacks. + some Spectre v2 variant attacks. The BHB can still influence the choice of + indirect branch predictor entry, and although branch predictor entries are + isolated between modes when eIBRS is enabled, the BHB itself is not isolated + between modes. Systems which support BHI_DIS_S will set it to protect against + BHI attacks. On Intel's enhanced IBRS systems, this includes cross-thread branch target injections on SMT systems (STIBP). In other words, Intel eIBRS enables @@ -638,6 +658,18 @@ kernel command line. spectre_v2=off. Spectre variant 1 mitigations cannot be disabled. + spectre_bhi= + + [X86] Control mitigation of Branch History Injection + (BHI) vulnerability. This setting affects the deployment + of the HW BHI control and the SW BHB clearing sequence. + + on + (default) Enable the HW or SW mitigation as + needed. + off + Disable the mitigation. + For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt Mitigation selection guide diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index bb884c14b2f6..213d0719e2b7 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3423,6 +3423,9 @@ arch-independent options, each of which is an aggregation of existing arch-specific options. + Note, "mitigations" is supported if and only if the + kernel was built with CPU_MITIGATIONS=y. + off Disable all optional CPU mitigations. This improves system performance, but it may also @@ -3444,6 +3447,7 @@ retbleed=off [X86] spec_rstack_overflow=off [X86] spec_store_bypass_disable=off [X86,PPC] + spectre_bhi=off [X86] spectre_v2_user=off [X86] srbds=off [X86,INTEL] ssbd=force-off [ARM64] @@ -6063,6 +6067,15 @@ sonypi.*= [HW] Sony Programmable I/O Control Device driver See Documentation/admin-guide/laptops/sonypi.rst + spectre_bhi= [X86] Control mitigation of Branch History Injection + (BHI) vulnerability. This setting affects the + deployment of the HW BHI control and the SW BHB + clearing sequence. + + on - (default) Enable the HW or SW mitigation + as needed. + off - Disable the mitigation. + spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 (indirect branch speculation) vulnerability. The default operation protects the kernel from @@ -6599,7 +6612,7 @@ To turn off having tracepoints sent to printk, echo 0 > /proc/sys/kernel/tracepoint_printk Note, echoing 1 into this file without the - tracepoint_printk kernel cmdline option has no effect. + tp_printk kernel cmdline option has no effect. The tp_printk_stop_on_boot (see below) can also be used to stop the printing of events to console at diff --git a/Documentation/admin-guide/mm/zswap.rst b/Documentation/admin-guide/mm/zswap.rst index b42132969e31..13632671adae 100644 --- a/Documentation/admin-guide/mm/zswap.rst +++ b/Documentation/admin-guide/mm/zswap.rst @@ -155,7 +155,7 @@ Setting this parameter to 100 will disable the hysteresis. Some users cannot tolerate the swapping that comes with zswap store failures and zswap writebacks. Swapping can be disabled entirely (without disabling -zswap itself) on a cgroup-basis as follows: +zswap itself) on a cgroup-basis as follows:: echo 0 > /sys/fs/cgroup//memory.zswap.writeback @@ -166,7 +166,7 @@ writeback (because the same pages might be rejected again and again). When there is a sizable amount of cold memory residing in the zswap pool, it can be advantageous to proactively write these cold pages to swap and reclaim the memory for other use cases. By default, the zswap shrinker is disabled. -User can enable it as follows: +User can enable it as follows:: echo Y > /sys/module/zswap/parameters/shrinker_enabled diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index d3504826f401..c389d4fd7599 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -29,7 +29,7 @@ The essence of the process (aka 'TL;DR') ======================================== *[If you are new to building or bisecting Linux, ignore this section and head -over to the* ":ref:`step-by-step guide`" *below. It utilizes +over to the* ':ref:`step-by-step guide `' *below. It utilizes the same commands as this section while describing them in brief fashion. The steps are nevertheless easy to follow and together with accompanying entries in a reference section mention many alternatives, pitfalls, and additional @@ -38,8 +38,8 @@ aspects, all of which might be essential in your present case.]* **In case you want to check if a bug is present in code currently supported by developers**, execute just the *preparations* and *segment 1*; while doing so, consider the newest Linux kernel you regularly use to be the 'working' kernel. -In the following example that's assumed to be 6.0.13, which is why the sources -of 6.0 will be used to prepare the .config file. +In the following example that's assumed to be 6.0, which is why its sources +will be used to prepare the .config file. **In case you face a regression**, follow the steps at least till the end of *segment 2*. Then you can submit a preliminary report -- or continue with @@ -61,7 +61,7 @@ will be considered the 'good' release and used to prepare the .config file. cd ~/linux/ git remote add -t master stable \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git - git checkout --detach v6.0 + git switch --detach v6.0 # * Hint: if you used an existing clone, ensure no stale .config is around. make olddefconfig # * Ensure the former command picked the .config of the 'working' kernel. @@ -87,7 +87,7 @@ will be considered the 'good' release and used to prepare the .config file. a) Checking out latest mainline code:: cd ~/linux/ - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master b) Build, install, and boot a kernel:: @@ -125,7 +125,7 @@ will be considered the 'good' release and used to prepare the .config file. a) Start by checking out the sources of the 'good' version:: cd ~/linux/ - git checkout --force --detach v6.0 + git switch --discard-changes --detach v6.0 b) Build, install, and boot a kernel as described earlier in *segment 1, section b* -- just feel free to skip the 'du' commands, as you have a rough @@ -136,8 +136,7 @@ will be considered the 'good' release and used to prepare the .config file. * **Segment 3**: perform and validate the bisection. - a) In case your 'broken' version is a stable/longterm release, add the Git - branch holding it:: + a) Retrieve the sources for your 'bad' version:: git remote set-branches --add stable linux-6.1.y git fetch stable @@ -157,11 +156,12 @@ will be considered the 'good' release and used to prepare the .config file. works with the newly built kernel. If it does, tell Git by executing ``git bisect good``; if it does not, run ``git bisect bad`` instead. - All three commands will make Git checkout another commit; then re-execute + All three commands will make Git check out another commit; then re-execute this step (e.g. build, install, boot, and test a kernel to then tell Git the outcome). Do so again and again until Git shows which commit broke things. If you run short of disk space during this process, check the - "Supplementary tasks" section below. + section 'Complementary tasks: cleanup during and after the process' + below. d) Once your finished the bisection, put a few things away:: @@ -172,14 +172,17 @@ will be considered the 'good' release and used to prepare the .config file. e) Try to verify the bisection result:: - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master git revert --no-edit cafec0cacaca0 + cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' This is optional, as some commits are impossible to revert. But if the second command worked flawlessly, build, install, and boot one more kernel - kernel, which should not show the regression. + kernel; just this time skip the first command copying the base .config file + over, as that already has been taken care off. -* **Supplementary tasks**: cleanup during and after the process. +* **Complementary tasks**: cleanup during and after the process. a) To avoid running out of disk space during a bisection, you might need to remove some kernels you built earlier. You most likely want to keep those @@ -202,13 +205,25 @@ will be considered the 'good' release and used to prepare the .config file. the kernels you built earlier and later you might want to keep around for a week or two. +* **Optional task**: test a debug patch or a proposed fix later:: + + git fetch mainline + git switch --discard-changes --detach mainline/master + git apply /tmp/foobars-proposed-fix-v1.patch + cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' + + Build, install, and boot a kernel as described in *segment 1, section b* -- + but this time omit the first command copying the build configuration over, + as that has been taken care of already. + .. _introguide_bissbs: Step-by-step guide on how to verify bugs and bisect regressions =============================================================== This guide describes how to set up your own Linux kernels for investigating bugs -or regressions you intent to report. How far you want to follow the instructions +or regressions you intend to report. How far you want to follow the instructions depends on your issue: Execute all steps till the end of *segment 1* to **verify if your kernel problem @@ -221,15 +236,17 @@ report; instead of the latter your could also head straight on and follow *segment 3* to **perform a bisection** for a full-fledged regression report developers are obliged to act upon. - :ref:`Preparations: set up everything to build your own kernels.` + :ref:`Preparations: set up everything to build your own kernels `. - :ref:`Segment 1: try to reproduce the problem with the latest codebase.` + :ref:`Segment 1: try to reproduce the problem with the latest codebase `. - :ref:`Segment 2: check if the kernels you build work fine.` + :ref:`Segment 2: check if the kernels you build work fine `. - :ref:`Segment 3: perform a bisection and validate the result.` + :ref:`Segment 3: perform a bisection and validate the result `. - :ref:`Supplementary tasks: cleanup during and after following this guide.` + :ref:`Complementary tasks: cleanup during and after following this guide `. + + :ref:`Optional tasks: test reverts, patches, or later versions `. The steps in each segment illustrate the important aspects of the process, while a comprehensive reference section holds additional details for almost all of the @@ -240,24 +257,35 @@ to get things rolling again. For further details on how to report Linux kernel issues or regressions check out Documentation/admin-guide/reporting-issues.rst, which works in conjunction with this document. It among others explains why you need to verify bugs with -the latest 'mainline' kernel, even if you face a problem with a kernel from a -'stable/longterm' series; for users facing a regression it also explains that -sending a preliminary report after finishing segment 2 might be wise, as the -regression and its culprit might be known already. For further details on -what actually qualifies as a regression check out -Documentation/admin-guide/reporting-regressions.rst. +the latest 'mainline' kernel (e.g. versions like 6.0, 6.1-rc1, or 6.1-rc6), +even if you face a problem with a kernel from a 'stable/longterm' series +(say 6.0.13). + +For users facing a regression that document also explains why sending a +preliminary report after segment 2 might be wise, as the regression and its +culprit might be known already. For further details on what actually qualifies +as a regression check out Documentation/admin-guide/reporting-regressions.rst. + +If you run into any problems while following this guide or have ideas how to +improve it, :ref:`please let the kernel developers know `. .. _introprep_bissbs: Preparations: set up everything to build your own kernels --------------------------------------------------------- +The following steps lay the groundwork for all further tasks. + +Note: the instructions assume you are building and testing on the same +machine; if you want to compile the kernel on another system, check +:ref:`Build kernels on a different machine ` below. + .. _backup_bissbs: * Create a fresh backup and put system repair and restore tools at hand, just to be prepared for the unlikely case of something going sideways. - [:ref:`details`] + [:ref:`details `] .. _vanilla_bissbs: @@ -265,7 +293,7 @@ Preparations: set up everything to build your own kernels builds them automatically. That includes but is not limited to DKMS, openZFS, VirtualBox, and Nvidia's graphics drivers (including the GPLed kernel module). - [:ref:`details`] + [:ref:`details `] .. _secureboot_bissbs: @@ -276,48 +304,49 @@ Preparations: set up everything to build your own kernels their restrictions through a process initiated by ``mokutil --disable-validation``. - [:ref:`details`] + [:ref:`details `] .. _rangecheck_bissbs: * Determine the kernel versions considered 'good' and 'bad' throughout this - guide. + guide: - Do you follow this guide to verify if a bug is present in the code developers - care for? Then consider the mainline release your 'working' kernel (the newest - one you regularly use) is based on to be the 'good' version; if your 'working' - kernel for example is 6.0.11, then your 'good' kernel is 6.0. + * Do you follow this guide to verify if a bug is present in the code the + primary developers care for? Then consider the version of the newest kernel + you regularly use currently as 'good' (e.g. 6.0, 6.0.13, or 6.1-rc2). - In case you face a regression, it depends on the version range where the - regression was introduced: + * Do you face a regression, e.g. something broke or works worse after + switching to a newer kernel version? In that case it depends on the version + range during which the problem appeared: - * Something which used to work in Linux 6.0 broke when switching to Linux - 6.1-rc1? Then henceforth regard 6.0 as the last known 'good' version - and 6.1-rc1 as the first 'bad' one. + * Something regressed when updating from a stable/longterm release + (say 6.0.13) to a newer mainline series (like 6.1-rc7 or 6.1) or a + stable/longterm version based on one (say 6.1.5)? Then consider the + mainline release your working kernel is based on to be the 'good' + version (e.g. 6.0) and the first version to be broken as the 'bad' one + (e.g. 6.1-rc7, 6.1, or 6.1.5). Note, at this point it is merely assumed + that 6.0 is fine; this hypothesis will be checked in segment 2. - * Some function stopped working when updating from 6.0.11 to 6.1.4? Then for - the time being consider 6.0 as the last 'good' version and 6.1.4 as - the 'bad' one. Note, at this point it is merely assumed that 6.0 is fine; - this assumption will be checked in segment 2. + * Something regressed when switching from one mainline version (say 6.0) to + a later one (like 6.1-rc1) or a stable/longterm release based on it + (say 6.1.5)? Then regard the last working version (e.g. 6.0) as 'good' and + the first broken (e.g. 6.1-rc1 or 6.1.5) as 'bad'. - * A feature you used in 6.0.11 does not work at all or worse in 6.1.13? In - that case you want to bisect within a stable/longterm series: consider - 6.0.11 as the last known 'good' version and 6.0.13 as the first 'bad' - one. Note, in this case you still want to compile and test a mainline kernel - as explained in segment 1: the outcome will determine if you need to report - your issue to the regular developers or the stable team. + * Something regressed when updating within a stable/longterm series (say + from 6.0.13 to 6.0.15)? Then consider those versions as 'good' and 'bad' + (e.g. 6.0.13 and 6.0.15), as you need to bisect within that series. *Note, do not confuse 'good' version with 'working' kernel; the latter term throughout this guide will refer to the last kernel that has been working fine.* - [:ref:`details`] + [:ref:`details `] .. _bootworking_bissbs: * Boot into the 'working' kernel and briefly use the apparently broken feature. - [:ref:`details`] + [:ref:`details `] .. _diskspace_bissbs: @@ -327,7 +356,7 @@ Preparations: set up everything to build your own kernels debug symbols: both explain approaches reducing the amount of space, which should allow you to master these tasks with about 4 Gigabytes free space. - [:ref:`details`] + [:ref:`details `] .. _buildrequires_bissbs: @@ -337,7 +366,7 @@ Preparations: set up everything to build your own kernels reference section shows how to quickly install those on various popular Linux distributions. - [:ref:`details`] + [:ref:`details `] .. _sources_bissbs: @@ -360,14 +389,23 @@ Preparations: set up everything to build your own kernels git remote add -t master stable \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git - [:ref:`details`] + [:ref:`details `] + +.. _stablesources_bissbs: + +* Is one of the versions you earlier established as 'good' or 'bad' a stable or + longterm release (say 6.1.5)? Then download the code for the series it belongs + to ('linux-6.1.y' in this example):: + + git remote set-branches --add stable linux-6.1.y + git fetch stable .. _oldconfig_bissbs: * Start preparing a kernel build configuration (the '.config' file). Before doing so, ensure you are still running the 'working' kernel an earlier - step told you to boot; if you are unsure, check the current kernel release + step told you to boot; if you are unsure, check the current kernelrelease identifier using ``uname -r``. Afterwards check out the source code for the version earlier established as @@ -375,7 +413,7 @@ Preparations: set up everything to build your own kernels the version number in this and all later Git commands needs to be prefixed with a 'v':: - git checkout --detach v6.0 + git switch --discard-changes --detach v6.0 Now create a build configuration file:: @@ -398,7 +436,7 @@ Preparations: set up everything to build your own kernels 'make olddefconfig' again and check if it now picked up the right config file as base. - [:ref:`details`] + [:ref:`details `] .. _localmodconfig_bissbs: @@ -432,7 +470,7 @@ Preparations: set up everything to build your own kernels spending much effort on, as long as it boots and allows to properly test the feature that causes trouble. - [:ref:`details`] + [:ref:`details `] .. _tagging_bissbs: @@ -442,7 +480,7 @@ Preparations: set up everything to build your own kernels ./scripts/config --set-str CONFIG_LOCALVERSION '-local' ./scripts/config -e CONFIG_LOCALVERSION_AUTO - [:ref:`details`] + [:ref:`details `] .. _debugsymbols_bissbs: @@ -461,7 +499,7 @@ Preparations: set up everything to build your own kernels ./scripts/config -d DEBUG_INFO -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \ -d DEBUG_INFO_DWARF4 -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE - [:ref:`details`] + [:ref:`details `] .. _configmods_bissbs: @@ -471,14 +509,14 @@ Preparations: set up everything to build your own kernels * Are you running Debian? Then you want to avoid known problems by performing additional adjustments explained in the reference section. - [:ref:`details`]. + [:ref:`details `]. * If you want to influence other aspects of the configuration, do so now using your preferred tool. Note, to use make targets like 'menuconfig' or 'nconfig', you will need to install the development files of ncurses; for 'xconfig' you likewise need the Qt5 or Qt6 headers. - [:ref:`details`]. + [:ref:`details `]. .. _saveconfig_bissbs: @@ -488,7 +526,7 @@ Preparations: set up everything to build your own kernels make olddefconfig cp .config ~/kernel-config-working - [:ref:`details`] + [:ref:`details `] .. _introlatestcheck_bissbs: @@ -498,16 +536,30 @@ Segment 1: try to reproduce the problem with the latest codebase The following steps verify if the problem occurs with the code currently supported by developers. In case you face a regression, it also checks that the problem is not caused by some .config change, as reporting the issue then would -be a waste of time. [:ref:`details`] +be a waste of time. [:ref:`details `] .. _checkoutmaster_bissbs: -* Check out the latest Linux codebase:: +* Check out the latest Linux codebase. - cd ~/linux/ - git checkout --force --detach mainline/master + * Are your 'good' and 'bad' versions from the same stable or longterm series? + Then check the `front page of kernel.org `_: if it + lists a release from that series without an '[EOL]' tag, checkout the series + latest version ('linux-6.1.y' in the following example):: - [:ref:`details`] + cd ~/linux/ + git switch --discard-changes --detach stable/linux-6.1.y + + Your series is unsupported, if is not listed or carrying a 'end of life' + tag. In that case you might want to check if a successor series (say + linux-6.2.y) or mainline (see next point) fix the bug. + + * In all other cases, run:: + + cd ~/linux/ + git switch --discard-changes --detach mainline/master + + [:ref:`details `] .. _build_bissbs: @@ -522,7 +574,7 @@ be a waste of time. [:ref:`details`] reference section for alternatives, which obviously will require other steps to install as well. - [:ref:`details`] + [:ref:`details `] .. _install_bissbs: @@ -555,7 +607,7 @@ be a waste of time. [:ref:`details`] down: if you will build more kernels as described in segment 2 and 3, you will have to perform those again after executing ``command -v installkernel [...]``. - [:ref:`details`] + [:ref:`details `] .. _storagespace_bissbs: @@ -568,7 +620,7 @@ be a waste of time. [:ref:`details`] Write down or remember those two values for later: they enable you to prevent running out of disk space accidentally during a bisection. - [:ref:`details`] + [:ref:`details `] .. _kernelrelease_bissbs: @@ -595,7 +647,7 @@ be a waste of time. [:ref:`details`] If that command does not return '0', check the reference section, as the cause for this might interfere with your testing. - [:ref:`details`] + [:ref:`details `] .. _recheckbroken_bissbs: @@ -603,21 +655,19 @@ be a waste of time. [:ref:`details`] out the instructions in the reference section to ensure nothing went sideways during your tests. - [:ref:`details`] + [:ref:`details `] .. _recheckstablebroken_bissbs: -* Are you facing a problem within a stable/longterm series, but failed to - reproduce it with the mainline kernel you just built? One that according to - the `front page of kernel.org `_ is still supported? Then - check if the latest codebase for the particular series might already fix the - problem. To do so, add the stable series Git branch for your 'good' kernel - (again, this here is assumed to be 6.0) and check out the latest version:: +* Did you just built a stable or longterm kernel? And were you able to reproduce + the regression with it? Then you should test the latest mainline codebase as + well, because the result determines which developers the bug must be submitted + to. + + To prepare that test, check out current mainline:: cd ~/linux/ - git remote set-branches --add stable linux-6.0.y - git fetch stable - git checkout --force --detach linux-6.0.y + git switch --discard-changes --detach mainline/master Now use the checked out code to build and install another kernel using the commands the earlier steps already described in more detail:: @@ -639,14 +689,16 @@ be a waste of time. [:ref:`details`] uname -r cat /proc/sys/kernel/tainted - Now verify if this kernel is showing the problem. + Now verify if this kernel is showing the problem. If it does, then you need + to report the bug to the primary developers; if it does not, report it to the + stable team. See Documentation/admin-guide/reporting-issues.rst for details. - [:ref:`details`] + [:ref:`details `] Do you follow this guide to verify if a problem is present in the code currently supported by Linux kernel developers? Then you are done at this point. If you later want to remove the kernel you just built, check out -:ref:`Supplementary tasks: cleanup during and after following this guide`. +:ref:`Complementary tasks: cleanup during and after following this guide `. In case you face a regression, move on and execute at least the next segment as well. @@ -658,7 +710,7 @@ Segment 2: check if the kernels you build work fine In case of a regression, you now want to ensure the trimmed configuration file you created earlier works as expected; a bisection with the .config file -otherwise would be a waste of time. [:ref:`details`] +otherwise would be a waste of time. [:ref:`details `] .. _recheckworking_bissbs: @@ -669,7 +721,7 @@ otherwise would be a waste of time. [:ref:`details`] 'good' (once again assumed to be 6.0 here):: cd ~/linux/ - git checkout --detach v6.0 + git switch --discard-changes --detach v6.0 Now use the checked out code to configure, build, and install another kernel using the commands the previous subsection explained in more detail:: @@ -693,7 +745,7 @@ otherwise would be a waste of time. [:ref:`details`] Now check if this kernel works as expected; if not, consult the reference section for further instructions. - [:ref:`details`] + [:ref:`details `] .. _introbisect_bissbs: @@ -703,18 +755,11 @@ Segment 3: perform the bisection and validate the result With all the preparations and precaution builds taken care of, you are now ready to begin the bisection. This will make you build quite a few kernels -- usually about 15 in case you encountered a regression when updating to a newer series -(say from 6.0.11 to 6.1.3). But do not worry, due to the trimmed build +(say from 6.0.13 to 6.1.5). But do not worry, due to the trimmed build configuration created earlier this works a lot faster than many people assume: overall on average it will often just take about 10 to 15 minutes to compile each kernel on commodity x86 machines. -* In case your 'bad' version is a stable/longterm release (say 6.1.5), add its - stable branch, unless you already did so earlier:: - - cd ~/linux/ - git remote set-branches --add stable linux-6.1.y - git fetch stable - .. _bisectstart_bissbs: * Start the bisection and tell Git about the versions earlier established as @@ -725,7 +770,7 @@ each kernel on commodity x86 machines. git bisect good v6.0 git bisect bad v6.1.5 - [:ref:`details`] + [:ref:`details `] .. _bisectbuild_bissbs: @@ -745,7 +790,7 @@ each kernel on commodity x86 machines. If compilation fails for some reason, run ``git bisect skip`` and restart executing the stack of commands from the beginning. - In case you skipped the "test latest codebase" step in the guide, check its + In case you skipped the 'test latest codebase' step in the guide, check its description as for why the 'df [...]' and 'make -s kernelrelease [...]' commands are here. @@ -754,7 +799,7 @@ each kernel on commodity x86 machines. totally normal to see release identifiers like '6.0-rc1-local-gcafec0cacaca0' if you bisect between versions 6.1 and 6.2 for example. - [:ref:`details`] + [:ref:`details `] .. _bisecttest_bissbs: @@ -794,7 +839,7 @@ each kernel on commodity x86 machines. might need to scroll up to see the message mentioning the culprit; alternatively, run ``git bisect log > ~/bisection-log``. - [:ref:`details`] + [:ref:`details `] .. _bisectlog_bissbs: @@ -806,7 +851,7 @@ each kernel on commodity x86 machines. cp .config ~/bisection-config-culprit git bisect reset - [:ref:`details`] + [:ref:`details `] .. _revert_bissbs: @@ -823,16 +868,16 @@ each kernel on commodity x86 machines. Begin by checking out the latest codebase depending on the range you bisected: * Did you face a regression within a stable/longterm series (say between - 6.0.11 and 6.0.13) that does not happen in mainline? Then check out the + 6.0.13 and 6.0.15) that does not happen in mainline? Then check out the latest codebase for the affected series like this:: git fetch stable - git checkout --force --detach linux-6.0.y + git switch --discard-changes --detach linux-6.0.y * In all other cases check out latest mainline:: git fetch mainline - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master If you bisected a regression within a stable/longterm series that also happens in mainline, there is one more thing to do: look up the mainline @@ -846,27 +891,33 @@ each kernel on commodity x86 machines. git revert --no-edit cafec0cacaca0 - If that fails, give up trying and move on to the next step. But if it works, - build a kernel again using the familiar command sequence:: + If that fails, give up trying and move on to the next step; if it works, + adjust the tag to facilitate the identification and prevent accidentally + overwriting another kernel:: cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' + + Build a kernel using the familiar command sequence, just without copying the + the base .config over:: + make olddefconfig && - make -j $(nproc --all) && + make -j $(nproc --all) # * Check if the free space suffices holding another kernel: df -h /boot/ /lib/modules/ sudo make modules_install command -v installkernel && sudo make install - Make -s kernelrelease | tee -a ~/kernels-built + make -s kernelrelease | tee -a ~/kernels-built reboot - Now check one last time if the feature that made you perform a bisection work - with that kernel. + Now check one last time if the feature that made you perform a bisection works + with that kernel: if everything went well, it should not show the regression. - [:ref:`details`] + [:ref:`details `] .. _introclosure_bissbs: -Supplementary tasks: cleanup during and after the bisection +Complementary tasks: cleanup during and after the bisection ----------------------------------------------------------- During and after following this guide you might want or need to remove some of @@ -903,7 +954,7 @@ space might run out. kernel image and related files behind; in that case remove them as described in the reference section. - [:ref:`details`] + [:ref:`details `] .. _finishingtouch_bissbs: @@ -926,18 +977,99 @@ space might run out. the version considered 'good', and the last three or four you compiled during the actual bisection process. - [:ref:`details`] + [:ref:`details `] + +.. _introoptional_bissbs: + +Optional: test reverts, patches, or later versions +-------------------------------------------------- + +While or after reporting a bug, you might want or potentially will be asked to +test reverts, debug patches, proposed fixes, or other versions. In that case +follow these instructions. + +* Update your Git clone and check out the latest code. + + * In case you want to test mainline, fetch its latest changes before checking + its code out:: + + git fetch mainline + git switch --discard-changes --detach mainline/master + + * In case you want to test a stable or longterm kernel, first add the branch + holding the series you are interested in (6.2 in the example), unless you + already did so earlier:: + + git remote set-branches --add stable linux-6.2.y + + Then fetch the latest changes and check out the latest version from the + series:: + + git fetch stable + git switch --discard-changes --detach stable/linux-6.2.y + +* Copy your kernel build configuration over:: + + cp ~/kernel-config-working .config + +* Your next step depends on what you want to do: + + * In case you just want to test the latest codebase, head to the next step, + you are already all set. + + * In case you want to test if a revert fixes an issue, revert one or multiple + changes by specifying their commit ids:: + + git revert --no-edit cafec0cacaca0 + + Now give that kernel a special tag to facilitates its identification and + prevent accidentally overwriting another kernel:: + + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' + + * In case you want to test a patch, store the patch in a file like + '/tmp/foobars-proposed-fix-v1.patch' and apply it like this:: + + git apply /tmp/foobars-proposed-fix-v1.patch + + In case of multiple patches, repeat this step with the others. + + Now give that kernel a special tag to facilitates its identification and + prevent accidentally overwriting another kernel:: + + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' + +* Build a kernel using the familiar commands, just without copying the kernel + build configuration over, as that has been taken care of already:: + + make olddefconfig && + make -j $(nproc --all) + # * Check if the free space suffices holding another kernel: + df -h /boot/ /lib/modules/ + sudo make modules_install + command -v installkernel && sudo make install + make -s kernelrelease | tee -a ~/kernels-built + reboot + +* Now verify you booted the newly built kernel and check it. + +[:ref:`details `] .. _submit_improvements: -This concludes the step-by-step guide. +Conclusion +---------- + +You have reached the end of the step-by-step guide. Did you run into trouble following any of the above steps not cleared up by the reference section below? Did you spot errors? Or do you have ideas how to -improve the guide? Then please take a moment and let the maintainer of this +improve the guide? + +If any of that applies, please take a moment and let the maintainer of this document know by email (Thorsten Leemhuis ), ideally while CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is -vital to improve this document further, which is in everybody's interest, as it +vital to improve this text further, which is in everybody's interest, as it will enable more people to master the task described here -- and hopefully also improve similar guides inspired by this one. @@ -948,10 +1080,20 @@ Reference section for the step-by-step guide This section holds additional information for almost all the items in the above step-by-step guide. +Preparations for building your own kernels +------------------------------------------ + + *The steps in this section lay the groundwork for all further tests.* + [:ref:`... `] + +The steps in all later sections of this guide depend on those described here. + +[:ref:`back to step-by-step guide `]. + .. _backup_bisref: Prepare for emergencies ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ *Create a fresh backup and put system repair and restore tools at hand.* [:ref:`... `] @@ -966,7 +1108,7 @@ for something going sideways, even if that should not happen. .. _vanilla_bisref: Remove anything related to externally maintained kernel modules ---------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Remove all software that depends on externally developed kernel drivers or builds them automatically.* [:ref:`...`] @@ -984,7 +1126,7 @@ explains in more detail. .. _secureboot_bisref: Deal with techniques like Secure Boot -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *On platforms with 'Secure Boot' or similar techniques, prepare everything to ensure the system will permit your self-compiled kernel to boot later.* @@ -1021,7 +1163,7 @@ Afterwards, permit MokManager to reboot the machine. .. _bootworking_bisref: Boot the last kernel that was working -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Boot into the last working kernel and briefly recheck if the feature that regressed really works.* [:ref:`...`] @@ -1034,7 +1176,7 @@ the right thing. .. _diskspace_bisref: Space requirements ------------------- +~~~~~~~~~~~~~~~~~~ *Ensure to have enough free space for building Linux.* [:ref:`... `] @@ -1052,32 +1194,32 @@ space by quite a few gigabytes. .. _rangecheck_bisref: Bisection range ---------------- +~~~~~~~~~~~~~~~ *Determine the kernel versions considered 'good' and 'bad' throughout this guide.* [:ref:`...`] Establishing the range of commits to be checked is mostly straightforward, except when a regression occurred when switching from a release of one stable -series to a release of a later series (e.g. from 6.0.11 to 6.1.4). In that case +series to a release of a later series (e.g. from 6.0.13 to 6.1.5). In that case Git will need some hand holding, as there is no straight line of descent. That's because with the release of 6.0 mainline carried on to 6.1 while the stable series 6.0.y branched to the side. It's therefore theoretically possible -that the issue you face with 6.1.4 only worked in 6.0.11, as it was fixed by a +that the issue you face with 6.1.5 only worked in 6.0.13, as it was fixed by a commit that went into one of the 6.0.y releases, but never hit mainline or the 6.1.y series. Thankfully that normally should not happen due to the way the stable/longterm maintainers maintain the code. It's thus pretty safe to assume 6.0 as a 'good' kernel. That assumption will be tested anyway, as that kernel will be built and tested in the segment '2' of this guide; Git would force you -to do this as well, if you tried bisecting between 6.0.11 and 6.1.13. +to do this as well, if you tried bisecting between 6.0.13 and 6.1.15. [:ref:`back to step-by-step guide `] .. _buildrequires_bisref: Install build requirements --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Install all software required to build a Linux kernel.* [:ref:`...`] @@ -1117,7 +1259,7 @@ These commands install a few packages that are often, but not always needed. You for example might want to skip installing the development headers for ncurses, which you will only need in case you later might want to adjust the kernel build configuration using make the targets 'menuconfig' or 'nconfig'; likewise omit -the headers of Qt6 is you do not plan to adjust the .config using 'xconfig'. +the headers of Qt6 if you do not plan to adjust the .config using 'xconfig'. You furthermore might need additional libraries and their development headers for tasks not covered in this guide -- for example when building utilities from @@ -1128,7 +1270,7 @@ the kernel's tools/ directory. .. _sources_bisref: Download the sources using Git ------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Retrieve the Linux mainline sources.* [:ref:`...`] @@ -1148,7 +1290,7 @@ work better for you: .. _sources_bundle_bisref: Downloading Linux mainline sources using a bundle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""""""""""""""""""""""""""" Use the following commands to retrieve the Linux mainline sources using a bundle:: @@ -1184,7 +1326,7 @@ First, execute the following command to retrieve the latest mainline codebase:: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git Now deepen your clone's history to the second predecessor of the mainline -release of your 'good' version. In case the latter are 6.0 or 6.0.11, 5.19 would +release of your 'good' version. In case the latter are 6.0 or 6.0.13, 5.19 would be the first predecessor and 5.18 the second -- hence deepen the history up to that version:: @@ -1219,7 +1361,7 @@ Note, shallow clones have a few peculiar characteristics: .. _oldconfig_bisref: Start defining the build configuration for your kernel ------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Start preparing a kernel build configuration (the '.config' file).* [:ref:`... `] @@ -1279,7 +1421,7 @@ that file to the build machine and store it as ~/linux/.config; afterwards run .. _localmodconfig_bisref: Trim the build configuration for your kernel --------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Disable any kernel modules apparently superfluous for your setup.* [:ref:`... `] @@ -1328,7 +1470,7 @@ step-by-step guide mentions:: .. _tagging_bisref: Tag the kernels about to be build ---------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Ensure all the kernels you will build are clearly identifiable using a special tag and a unique version identifier.* [:ref:`... `] @@ -1344,7 +1486,7 @@ confusing during the bisection. .. _debugsymbols_bisref: Decide to enable or disable debug symbols ------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Decide how to handle debug symbols.* [:ref:`... `] @@ -1373,7 +1515,7 @@ explains this process in more detail. .. _configmods_bisref: Adjust build configuration --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check if you may want or need to adjust some other kernel configuration options:* @@ -1384,7 +1526,7 @@ kernel configuration options. .. _configmods_distros_bisref: Distro specific adjustments -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""""" *Are you running* [:ref:`... `] @@ -1409,7 +1551,7 @@ when following this guide on a few commodity distributions. .. _configmods_individual_bisref: Individual adjustments -~~~~~~~~~~~~~~~~~~~~~~ +"""""""""""""""""""""" *If you want to influence the other aspects of the configuration, do so now.* [:ref:`... `] @@ -1426,13 +1568,13 @@ is missing. .. _saveconfig_bisref: Put the .config file aside --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Reprocess the .config after the latest changes and store it in a safe place.* [:ref:`... `] Put the .config you prepared aside, as you want to copy it back to the build -directory every time during this guide before you start building another +directory every time during this guide before you start building another kernel. That's because going back and forth between different versions can alter .config files in odd ways; those occasionally cause side effects that could confuse testing or in some cases render the result of your bisection @@ -1442,8 +1584,8 @@ meaningless. .. _introlatestcheck_bisref: -Try to reproduce the regression ------------------------------------------ +Try to reproduce the problem with the latest codebase +----------------------------------------------------- *Verify the regression is not caused by some .config change and check if it still occurs with the latest codebase.* [:ref:`... `] @@ -1490,28 +1632,28 @@ highly recommended for these reasons: Your report might be ignored if you send it to the wrong party -- and even when you get a reply there is a decent chance that developers tell you to - evaluate which of the two cases it is before they take a closer look. + evaluate which of the two cases it is before they take a closer look. [:ref:`back to step-by-step guide `] .. _checkoutmaster_bisref: Check out the latest Linux codebase ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check out the latest Linux codebase.* - [:ref:`... `] + [:ref:`... `] In case you later want to recheck if an ever newer codebase might fix the problem, remember to run that ``git fetch --shallow-exclude [...]`` command again mentioned earlier to update your local Git repository. -[:ref:`back to step-by-step guide `] +[:ref:`back to step-by-step guide `] .. _build_bisref: Build your kernel ------------------ +~~~~~~~~~~~~~~~~~ *Build the image and the modules of your first kernel using the config file you prepared.* [:ref:`... `] @@ -1521,7 +1663,7 @@ yourself. Another subsection explains how to directly package your kernel up as deb, rpm or tar file. Dealing with build errors -~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""" When a build error occurs, it might be caused by some aspect of your machine's setup that often can be fixed quickly; other times though the problem lies in @@ -1552,11 +1694,11 @@ by modifying your search terms or using another line from the error messages. In the end, most issues you run into have likely been encountered and reported by others already. That includes issues where the cause is not your -system, but lies in the code. If you run into one of those, you might thus find a -solution (e.g. a patch) or workaround for your issue, too. +system, but lies in the code. If you run into one of those, you might thus find +a solution (e.g. a patch) or workaround for your issue, too. Package your kernel up -~~~~~~~~~~~~~~~~~~~~~~ +"""""""""""""""""""""" The step-by-step guide uses the default make targets (e.g. 'bzImage' and 'modules' on x86) to build the image and the modules of your kernel, which later @@ -1587,7 +1729,7 @@ distribution's kernel packages. .. _install_bisref: Put the kernel in place ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ *Install the kernel you just built.* [:ref:`... `] @@ -1630,7 +1772,7 @@ process. Afterwards add your kernel to your bootloader configuration and reboot. .. _storagespace_bisref: Storage requirements per kernel -------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check how much storage space the kernel, its modules, and other related files like the initramfs consume.* [:ref:`... `] @@ -1651,7 +1793,7 @@ need to look in different places. .. _tainted_bisref: Check if your newly built kernel considers itself 'tainted' ------------------------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check if the kernel marked itself as 'tainted'.* [:ref:`... `] @@ -1670,7 +1812,7 @@ interest, as your testing might be flawed otherwise. .. _recheckbroken_bisref: Check the kernel built from a recent mainline codebase ------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Verify if your bug occurs with the newly built kernel.* [:ref:`... `] @@ -1696,7 +1838,7 @@ the kernel you built from the latest codebase. These are the most frequent: .. _recheckstablebroken_bisref: Check the kernel built from the latest stable/longterm codebase ---------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Are you facing a regression within a stable/longterm release, but failed to reproduce it with the kernel you just built using the latest mainline sources? @@ -1741,7 +1883,7 @@ ensure the kernel version you assumed to be 'good' earlier in the process (e.g. .. _recheckworking_bisref: Build your own version of the 'good' kernel -------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Build your own variant of the working kernel and check if the feature that regressed works as expected with it.* [:ref:`... `] @@ -1767,15 +1909,25 @@ multitude of reasons why this might happen. Some ideas where to look: Note, if you found and fixed problems with the .config file, you want to use it to build another kernel from the latest codebase, as your earlier tests with -mainline and the latest version from an affected stable/longterm series were most -likely flawed. +mainline and the latest version from an affected stable/longterm series were +most likely flawed. [:ref:`back to step-by-step guide `] +Perform a bisection and validate the result +------------------------------------------- + + *With all the preparations and precaution builds taken care of, you are now + ready to begin the bisection.* [:ref:`... `] + +The steps in this segment perform and validate the bisection. + +[:ref:`back to step-by-step guide `]. + .. _bisectstart_bisref: Start the bisection -------------------- +~~~~~~~~~~~~~~~~~~~ *Start the bisection and tell Git about the versions earlier established as 'good' and 'bad'.* [:ref:`... `] @@ -1789,7 +1941,7 @@ for you to test. .. _bisectbuild_bisref: Build a kernel from the bisection point ---------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Build, install, and boot a kernel from the code Git checked out using the same commands you used earlier.* [:ref:`... `] @@ -1817,7 +1969,7 @@ There are two things worth of note here: .. _bisecttest_bisref: Bisection checkpoint --------------------- +~~~~~~~~~~~~~~~~~~~~ *Check if the feature that regressed works in the kernel you just built.* [:ref:`... `] @@ -1831,7 +1983,7 @@ will be for nothing. .. _bisectlog_bisref: Put the bisection log away --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Store Git's bisection log and the current .config file in a safe place.* [:ref:`... `] @@ -1851,7 +2003,7 @@ ask for it after you report the regression. .. _revert_bisref: Try reverting the culprit -------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~ *Try reverting the culprit on top of the latest codebase to see if this fixes your regression.* [:ref:`... `] @@ -1869,14 +2021,20 @@ succeeds, test that kernel version instead. [:ref:`back to step-by-step guide `] +Cleanup steps during and after following this guide +--------------------------------------------------- -Supplementary tasks: cleanup during and after the bisection ------------------------------------------------------------ + *During and after following this guide you might want or need to remove some + of the kernels you installed.* [:ref:`... `] + +The steps in this section describe clean-up procedures. + +[:ref:`back to step-by-step guide `]. .. _makeroom_bisref: Cleaning up during the bisection --------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *To remove one of the kernels you installed, look up its 'kernelrelease' identifier.* [:ref:`... `] @@ -1911,13 +2069,13 @@ Now remove the boot entry for the kernel from your bootloader's configuration; the steps to do that vary quite a bit between Linux distributions. Note, be careful with wildcards like '*' when deleting files or directories -for kernels manually: you might accidentally remove files of a 6.0.11 kernel +for kernels manually: you might accidentally remove files of a 6.0.13 kernel when all you want is to remove 6.0 or 6.0.1. [:ref:`back to step-by-step guide `] Cleaning up after the bisection -------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _finishingtouch_bisref: @@ -1932,26 +2090,105 @@ build artifacts and the Linux sources, but will leave the Git repository (~/linux/.git/) behind -- a simple ``git reset --hard`` thus will bring the sources back. -Removing the repository as well would likely be unwise at this point: there is a -decent chance developers will ask you to build another kernel to perform -additional tests. This is often required to debug an issue or check proposed -fixes. Before doing so you want to run the ``git fetch mainline`` command again -followed by ``git checkout mainline/master`` to bring your clone up to date and -checkout the latest codebase. Then apply the patch using ``git apply -`` or ``git am `` and build yet another kernel using the -familiar commands. +Removing the repository as well would likely be unwise at this point: there +is a decent chance developers will ask you to build another kernel to +perform additional tests -- like testing a debug patch or a proposed fix. +Details on how to perform those can be found in the section :ref:`Optional +tasks: test reverts, patches, or later versions `. Additional tests are also the reason why you want to keep the ~/kernel-config-working file around for a few weeks. [:ref:`back to step-by-step guide `] +.. _introoptional_bisref: + +Test reverts, patches, or later versions +---------------------------------------- + + *While or after reporting a bug, you might want or potentially will be asked + to test reverts, patches, proposed fixes, or other versions.* + [:ref:`... `] + +All the commands used in this section should be pretty straight forward, so +there is not much to add except one thing: when setting a kernel tag as +instructed, ensure it is not much longer than the one used in the example, as +problems will arise if the kernelrelease identifier exceeds 63 characters. + +[:ref:`back to step-by-step guide `]. + + +Additional information +====================== + +.. _buildhost_bis: + +Build kernels on a different machine +------------------------------------ + +To compile kernels on another system, slightly alter the step-by-step guide's +instructions: + +* Start following the guide on the machine where you want to install and test + the kernels later. + +* After executing ':ref:`Boot into the working kernel and briefly use the + apparently broken feature `', save the list of loaded + modules to a file using ``lsmod > ~/test-machine-lsmod``. Then locate the + build configuration for the running kernel (see ':ref:`Start defining the + build configuration for your kernel `' for hints on where + to find it) and store it as '~/test-machine-config-working'. Transfer both + files to the home directory of your build host. + +* Continue the guide on the build host (e.g. with ':ref:`Ensure to have enough + free space for building [...] `'). + +* When you reach ':ref:`Start preparing a kernel build configuration[...] + `': before running ``make olddefconfig`` for the first time, + execute the following command to base your configuration on the one from the + test machine's 'working' kernel:: + + cp ~/test-machine-config-working ~/linux/.config + +* During the next step to ':ref:`disable any apparently superfluous kernel + modules `' use the following command instead:: + + yes '' | make localmodconfig LSMOD=~/lsmod_foo-machine localmodconfig + +* Continue the guide, but ignore the instructions outlining how to compile, + install, and reboot into a kernel every time they come up. Instead build + like this:: + + cp ~/kernel-config-working .config + make olddefconfig && + make -j $(nproc --all) targz-pkg + + This will generate a gzipped tar file whose name is printed in the last + line shown; for example, a kernel with the kernelrelease identifier + '6.0.0-rc1-local-g928a87efa423' built for x86 machines usually will + be stored as '~/linux/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz'. + + Copy that file to your test machine's home directory. + +* Switch to the test machine to check if you have enough space to hold another + kernel. Then extract the file you transferred:: + + sudo tar -xvzf ~/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz -C / + + Afterwards :ref:`generate the initramfs and add the kernel to your boot + loader's configuration `; on some distributions the following + command will take care of both these tasks:: + + sudo /sbin/installkernel 6.0.0-rc1-local-g928a87efa423 /boot/vmlinuz-6.0.0-rc1-local-g928a87efa423 + + Now reboot and ensure you started the intended kernel. + +This approach even works when building for another architecture: just install +cross-compilers and add the appropriate parameters to every invocation of make +(e.g. ``make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- [...]``). Additional reading material -=========================== - -Further sources ---------------- +--------------------------- * The `man page for 'git bisect' `_ and `fighting regressions with 'git bisect' `_ diff --git a/Documentation/dev-tools/testing-overview.rst b/Documentation/dev-tools/testing-overview.rst index 0aaf6ea53608..1619e5e5cc9c 100644 --- a/Documentation/dev-tools/testing-overview.rst +++ b/Documentation/dev-tools/testing-overview.rst @@ -104,6 +104,8 @@ Some of these tools are listed below: KASAN and can be used in production. See Documentation/dev-tools/kfence.rst * lockdep is a locking correctness validator. See Documentation/locking/lockdep-design.rst +* Runtime Verification (RV) supports checking specific behaviours for a given + subsystem. See Documentation/trace/rv/runtime-verification.rst * There are several other pieces of debug instrumentation in the kernel, many of which can be found in lib/Kconfig.debug diff --git a/Documentation/devicetree/bindings/clock/keystone-gate.txt b/Documentation/devicetree/bindings/clock/keystone-gate.txt index c5aa187026e3..43f6fb6c9392 100644 --- a/Documentation/devicetree/bindings/clock/keystone-gate.txt +++ b/Documentation/devicetree/bindings/clock/keystone-gate.txt @@ -1,5 +1,3 @@ -Status: Unstable - ABI compatibility may be broken in the future - Binding for Keystone gate control driver which uses PSC controller IP. This binding uses the common clock binding[1]. diff --git a/Documentation/devicetree/bindings/clock/keystone-pll.txt b/Documentation/devicetree/bindings/clock/keystone-pll.txt index 9a3fbc665606..69b0eb7c03c9 100644 --- a/Documentation/devicetree/bindings/clock/keystone-pll.txt +++ b/Documentation/devicetree/bindings/clock/keystone-pll.txt @@ -1,5 +1,3 @@ -Status: Unstable - ABI compatibility may be broken in the future - Binding for keystone PLLs. The main PLL IP typically has a multiplier, a divider and a post divider. The additional PLL IPs like ARMPLL, DDRPLL and PAPLL are controlled by the memory mapped register where as the Main diff --git a/Documentation/devicetree/bindings/clock/ti/adpll.txt b/Documentation/devicetree/bindings/clock/ti/adpll.txt index 4c8a2ce2cd70..3122360adcf3 100644 --- a/Documentation/devicetree/bindings/clock/ti/adpll.txt +++ b/Documentation/devicetree/bindings/clock/ti/adpll.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments ADPLL clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped ADPLL with two to three selectable input clocks and three to four children. diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt index ade4dd4c30f0..bbd505c1199d 100644 --- a/Documentation/devicetree/bindings/clock/ti/apll.txt +++ b/Documentation/devicetree/bindings/clock/ti/apll.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments APLL clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped APLL with usually two selectable input clocks (reference clock and bypass clock), with analog phase locked diff --git a/Documentation/devicetree/bindings/clock/ti/autoidle.txt b/Documentation/devicetree/bindings/clock/ti/autoidle.txt index 7c735dde9fe9..05645a10a9e3 100644 --- a/Documentation/devicetree/bindings/clock/ti/autoidle.txt +++ b/Documentation/devicetree/bindings/clock/ti/autoidle.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments autoidle clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register mapped clock which can be put to idle automatically by hardware based on the usage and a configuration bit setting. Autoidle clock is never an individual diff --git a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt index 9c6199249ce5..edf0b5d42768 100644 --- a/Documentation/devicetree/bindings/clock/ti/clockdomain.txt +++ b/Documentation/devicetree/bindings/clock/ti/clockdomain.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments clockdomain. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1] in consumer role. Every clock on TI SoC belongs to one clockdomain, but software only needs this information for specific clocks which require diff --git a/Documentation/devicetree/bindings/clock/ti/composite.txt b/Documentation/devicetree/bindings/clock/ti/composite.txt index 33ac7c9ad053..6f7e1331b546 100644 --- a/Documentation/devicetree/bindings/clock/ti/composite.txt +++ b/Documentation/devicetree/bindings/clock/ti/composite.txt @@ -1,7 +1,5 @@ Binding for TI composite clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped composite clock with multiple different sub-types; diff --git a/Documentation/devicetree/bindings/clock/ti/divider.txt b/Documentation/devicetree/bindings/clock/ti/divider.txt index 9b13b32974f9..4d7c76f0b356 100644 --- a/Documentation/devicetree/bindings/clock/ti/divider.txt +++ b/Documentation/devicetree/bindings/clock/ti/divider.txt @@ -1,7 +1,5 @@ Binding for TI divider clock -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped adjustable clock rate divider that does not gate and has only one input clock or parent. By default the value programmed into diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt index 37a7cb6ad07d..14a1b72c2e71 100644 --- a/Documentation/devicetree/bindings/clock/ti/dpll.txt +++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments DPLL clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped DPLL with usually two selectable input clocks (reference clock and bypass clock), with digital phase locked diff --git a/Documentation/devicetree/bindings/clock/ti/fapll.txt b/Documentation/devicetree/bindings/clock/ti/fapll.txt index c19b3f253b8c..88986ef39ddd 100644 --- a/Documentation/devicetree/bindings/clock/ti/fapll.txt +++ b/Documentation/devicetree/bindings/clock/ti/fapll.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments FAPLL clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped FAPLL with usually two selectable input clocks (reference clock and bypass clock), and one or more child diff --git a/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt b/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt index 518e3c142276..dc69477b6e98 100644 --- a/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt +++ b/Documentation/devicetree/bindings/clock/ti/fixed-factor-clock.txt @@ -1,7 +1,5 @@ Binding for TI fixed factor rate clock sources. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1], and also uses the autoidle support from TI autoidle clock [2]. diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt index 4982615c01b9..a8e0335b006a 100644 --- a/Documentation/devicetree/bindings/clock/ti/gate.txt +++ b/Documentation/devicetree/bindings/clock/ti/gate.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments gate clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. This clock is quite much similar to the basic gate-clock [2], however, it supports a number of additional features. If no register diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt index d3eb5ca92a7f..85fb1f2d2d28 100644 --- a/Documentation/devicetree/bindings/clock/ti/interface.txt +++ b/Documentation/devicetree/bindings/clock/ti/interface.txt @@ -1,7 +1,5 @@ Binding for Texas Instruments interface clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. This clock is quite much similar to the basic gate-clock [2], however, it supports a number of additional features, including diff --git a/Documentation/devicetree/bindings/clock/ti/mux.txt b/Documentation/devicetree/bindings/clock/ti/mux.txt index b33f641f1043..cd56d3c1c09f 100644 --- a/Documentation/devicetree/bindings/clock/ti/mux.txt +++ b/Documentation/devicetree/bindings/clock/ti/mux.txt @@ -1,7 +1,5 @@ Binding for TI mux clock. -Binding status: Unstable - ABI compatibility may be broken in the future - This binding uses the common clock binding[1]. It assumes a register-mapped multiplexer with multiple input clock signals or parents, one of which can be selected as output. This clock does not diff --git a/Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml b/Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml new file mode 100644 index 000000000000..862ef441ac9f --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml @@ -0,0 +1,55 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/microchip,sam9x75-lvds.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip SAM9X75 LVDS Controller + +maintainers: + - Dharma Balasubiramani + +description: + The Low Voltage Differential Signaling Controller (LVDSC) manages data + format conversion from the LCD Controller internal DPI bus to OpenLDI + LVDS output signals. LVDSC functions include bit mapping, balanced mode + management, and serializer. + +properties: + compatible: + const: microchip,sam9x75-lvds + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Peripheral Bus Clock + + clock-names: + items: + - const: pclk + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + lvds-controller@f8060000 { + compatible = "microchip,sam9x75-lvds"; + reg = <0xf8060000 0x100>; + interrupts = <56 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&pmc PMC_TYPE_PERIPHERAL 56>; + clock-names = "pclk"; + }; diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml index d879c700594a..258dd9cfd770 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358775.yaml @@ -10,7 +10,7 @@ maintainers: - Vinay Simha BN description: | - This binding supports DSI to LVDS bridge TC358775 + This binding supports DSI to LVDS bridges TC358765 and TC358775 MIPI DSI-RX Data 4-lane, CLK 1-lane with data rates up to 800 Mbps/lane. Video frame size: @@ -21,7 +21,9 @@ description: | properties: compatible: - const: toshiba,tc358775 + enum: + - toshiba,tc358765 + - toshiba,tc358775 reg: maxItems: 1 @@ -46,11 +48,27 @@ properties: properties: port@0: - $ref: /schemas/graph.yaml#/properties/port + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false description: | DSI Input. The remote endpoint phandle should be a reference to a valid mipi_dsi_host device node. + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + description: array of physical DSI data lane indexes. + minItems: 1 + items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + port@1: $ref: /schemas/graph.yaml#/properties/port description: | @@ -70,10 +88,19 @@ required: - reg - vdd-supply - vddio-supply - - stby-gpios - reset-gpios - ports +allOf: + - if: + properties: + compatible: + contains: + const: toshiba,tc358765 + then: + properties: + stby-gpios: false + additionalProperties: false examples: @@ -108,6 +135,7 @@ examples: reg = <0>; d2l_in_test: endpoint { remote-endpoint = <&dsi0_out>; + data-lanes = <1 2 3 4>; }; }; @@ -132,7 +160,6 @@ examples: reg = <1>; dsi0_out: endpoint { remote-endpoint = <&d2l_in_test>; - data-lanes = <0 1 2 3>; }; }; }; @@ -167,6 +194,7 @@ examples: reg = <0>; d2l_in_dual: endpoint { remote-endpoint = <&dsi0_out_dual>; + data-lanes = <1 2 3 4>; }; }; @@ -198,7 +226,6 @@ examples: reg = <1>; dsi0_out_dual: endpoint { remote-endpoint = <&d2l_in_dual>; - data-lanes = <0 1 2 3>; }; }; }; diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml index c6641acd75d6..b8b8e83ebc3f 100644 --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,gamma.yaml @@ -24,6 +24,7 @@ properties: - enum: - mediatek,mt8173-disp-gamma - mediatek,mt8183-disp-gamma + - mediatek,mt8195-disp-gamma - items: - enum: - mediatek,mt6795-disp-gamma @@ -35,6 +36,10 @@ properties: - mediatek,mt8192-disp-gamma - mediatek,mt8195-disp-gamma - const: mediatek,mt8183-disp-gamma + - items: + - enum: + - mediatek,mt8188-disp-gamma + - const: mediatek,mt8195-disp-gamma reg: maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml index c0d6a4fdff97..e6dc5494baee 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml @@ -53,6 +53,15 @@ patternProperties: compatible: const: qcom,sm8150-dpu + "^displayport-controller@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + contains: + const: qcom,sm8150-dp + "^dsi@[0-9a-f]+$": type: object additionalProperties: true diff --git a/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml new file mode 100644 index 000000000000..1e08648f5bc7 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/lg,sw43408.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: LG SW43408 1080x2160 DSI panel + +maintainers: + - Caleb Connolly + +description: + This panel is used on the Pixel 3, it is a 60hz OLED panel which + required DSC (Display Stream Compression) and has rounded corners. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - const: lg,sw43408 + + reg: true + port: true + vddi-supply: true + vpnl-supply: true + reset-gpios: true + +required: + - compatible + - vddi-supply + - vpnl-supply + - reset-gpios + +additionalProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "lg,sw43408"; + reg = <0>; + + vddi-supply = <&vreg_l14a_1p88>; + vpnl-supply = <&vreg_l28a_3p0>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>; + + port { + endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + }; + }; +... diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml index d3abd7f4ebcd..db5acd2807ed 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml @@ -36,6 +36,8 @@ properties: - jdi,fhd-r63452 # Khadas TS050 5" 1080x1920 LCD panel - khadas,ts050 + # Khadas TS050 V2 5" 1080x1920 LCD panel + - khadas,ts050v2 # Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel - kingdisplay,kd097d04 # LG ACX467AKM-7 4.95" 1080×1920 LCD Panel diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index e0f6aa9a025c..931d98836e12 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -190,6 +190,8 @@ properties: - innolux,g121i1-l01 # Innolux Corporation 12.1" G121X1-L03 XGA (1024x768) TFT LCD panel - innolux,g121x1-l03 + # Innolux Corporation 12.1" G121XCE-L01 XGA (1024x768) TFT LCD panel + - innolux,g121xce-l01 # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel - innolux,n116bca-ea1 # Innolux Corporation 11.6" WXGA (1366x768) TFT LCD panel diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm69380.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm69380.yaml new file mode 100644 index 000000000000..b17765b2b351 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/raydium,rm69380.yaml @@ -0,0 +1,89 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/raydium,rm69380.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Raydium RM69380-based DSI display panels + +maintainers: + - David Wronek + +description: + The Raydium RM69380 is a generic DSI panel IC used to control + OLED panels. + +allOf: + - $ref: panel-common-dual.yaml# + +properties: + compatible: + items: + - enum: + - lenovo,j716f-edo-rm69380 + - const: raydium,rm69380 + description: This indicates the panel manufacturer of the panel + that is in turn using the RM69380 panel driver. The compatible + string determines how the RM69380 panel driver shall be configured + to work with the indicated panel. The raydium,rm69380 compatible shall + always be provided as a fallback. + + avdd-supply: + description: Analog voltage rail + + vddio-supply: + description: I/O voltage rail + + reset-gpios: + maxItems: 1 + description: phandle of gpio for reset line - This should be active low + + reg: true + +required: + - compatible + - reg + - avdd-supply + - vddio-supply + - reset-gpios + +unevaluatedProperties: false + +examples: + - | + #include + + dsi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "lenovo,j716f-edo-rm69380", "raydium,rm69380"; + reg = <0>; + + avdd-supply = <&panel_avdd_regulator>; + vddio-supply = <&vreg_l14a>; + reset-gpios = <&tlmm 75 GPIO_ACTIVE_LOW>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + panel_in_0: endpoint { + remote-endpoint = <&mdss_dsi0_out>; + }; + }; + + port@1 { + reg = <1>; + panel_in_1: endpoint { + remote-endpoint = <&mdss_dsi1_out>; + }; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml index af638b6c0d21..2aac62219ff6 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-hdmi.yaml @@ -15,6 +15,7 @@ description: | allOf: - $ref: ../bridge/synopsys,dw-hdmi.yaml# + - $ref: /schemas/sound/dai-common.yaml# properties: compatible: @@ -124,6 +125,9 @@ properties: description: phandle to the GRF to mux vopl/vopb. + "#sound-dai-cells": + const: 0 + required: - compatible - reg @@ -153,6 +157,7 @@ examples: ddc-i2c-bus = <&i2c5>; power-domains = <&power RK3288_PD_VIO>; rockchip,grf = <&grf>; + #sound-dai-cells = <0>; ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml index be78dcfa1c76..5b87b0f1963e 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,inno-hdmi.yaml @@ -37,6 +37,9 @@ properties: power-domains: maxItems: 1 + "#sound-dai-cells": + const: 0 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -66,6 +69,7 @@ required: - ports allOf: + - $ref: /schemas/sound/dai-common.yaml# - if: properties: compatible: @@ -106,6 +110,7 @@ examples: clock-names = "pclk"; pinctrl-names = "default"; pinctrl-0 = <&hdmi_ctl>; + #sound-dai-cells = <0>; ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,rk3066-hdmi.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,rk3066-hdmi.yaml index 1a68a940d165..6d4b78a36576 100644 --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,rk3066-hdmi.yaml +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,rk3066-hdmi.yaml @@ -10,6 +10,9 @@ maintainers: - Sandy Huang - Heiko Stuebner +allOf: + - $ref: /schemas/sound/dai-common.yaml# + properties: compatible: const: rockchip,rk3066-hdmi @@ -34,6 +37,9 @@ properties: description: This soc uses GRF regs to switch the HDMI TX input between vop0 and vop1. + "#sound-dai-cells": + const: 0 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -83,6 +89,7 @@ examples: pinctrl-names = "default"; power-domains = <&power RK3066_PD_VIO>; rockchip,grf = <&grf>; + #sound-dai-cells = <0>; ports { #address-cells = <1>; diff --git a/Documentation/devicetree/bindings/dts-coding-style.rst b/Documentation/devicetree/bindings/dts-coding-style.rst index a9bdd2b59dca..8a68331075a0 100644 --- a/Documentation/devicetree/bindings/dts-coding-style.rst +++ b/Documentation/devicetree/bindings/dts-coding-style.rst @@ -144,6 +144,8 @@ Example:: #dma-cells = <1>; clocks = <&clock_controller 0>, <&clock_controller 1>; clock-names = "bus", "host"; + #address-cells = <1>; + #size-cells = <1>; vendor,custom-property = <2>; status = "disabled"; diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml index 1812ef31d5f1..3c36cd0510de 100644 --- a/Documentation/devicetree/bindings/eeprom/at24.yaml +++ b/Documentation/devicetree/bindings/eeprom/at24.yaml @@ -68,14 +68,10 @@ properties: pattern: cs16$ - items: pattern: c32$ - - items: - pattern: c32d-wl$ - items: pattern: cs32$ - items: pattern: c64$ - - items: - pattern: c64d-wl$ - items: pattern: cs64$ - items: @@ -136,6 +132,7 @@ properties: - renesas,r1ex24128 - samsung,s524ad0xd1 - const: atmel,24c128 + - pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st label: description: Descriptive name of the EEPROM. diff --git a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml index 528ef3572b62..055a3351880b 100644 --- a/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml +++ b/Documentation/devicetree/bindings/net/bluetooth/qualcomm-bluetooth.yaml @@ -94,6 +94,10 @@ properties: local-bd-address: true + qcom,local-bd-address-broken: + type: boolean + description: + boot firmware is incorrectly passing the address in big-endian order required: - compatible diff --git a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml index afcdeed4e88a..bc813fe74fab 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml @@ -52,6 +52,9 @@ properties: - const: main - const: mm + power-domains: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/remoteproc/ti,davinci-rproc.txt b/Documentation/devicetree/bindings/remoteproc/ti,davinci-rproc.txt index 25f8658e216f..48a49c516b62 100644 --- a/Documentation/devicetree/bindings/remoteproc/ti,davinci-rproc.txt +++ b/Documentation/devicetree/bindings/remoteproc/ti,davinci-rproc.txt @@ -1,9 +1,6 @@ TI Davinci DSP devices ======================= -Binding status: Unstable - Subject to changes for DT representation of clocks - and resets - The TI Davinci family of SoCs usually contains a TI DSP Core sub-system that is used to offload some of the processor-intensive tasks or algorithms, for achieving various system level goals. diff --git a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml index 65cb2e5c5eee..eb2992a447d7 100644 --- a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml +++ b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml @@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) maintainers: - - Richard Genoud + - Richard Genoud properties: compatible: diff --git a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml index 397f75909b20..ce1a6505eb51 100644 --- a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml +++ b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-dcfg.yaml @@ -51,7 +51,7 @@ properties: ranges: true patternProperties: - "^clock-controller@[0-9a-z]+$": + "^clock-controller@[0-9a-f]+$": $ref: /schemas/clock/fsl,flexspi-clock.yaml# required: diff --git a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml index 8d088b5fe823..a6a511b00a12 100644 --- a/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml +++ b/Documentation/devicetree/bindings/soc/fsl/fsl,layerscape-scfg.yaml @@ -41,7 +41,7 @@ properties: ranges: true patternProperties: - "^interrupt-controller@[a-z0-9]+$": + "^interrupt-controller@[a-f0-9]+$": $ref: /schemas/interrupt-controller/fsl,ls-extirq.yaml# required: diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml index 0b87c266760c..79798c747476 100644 --- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml +++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml @@ -171,6 +171,7 @@ allOf: unevaluatedProperties: false pcie-phy: + type: object description: Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt diff --git a/Documentation/devicetree/bindings/timer/arm,arch_timer_mmio.yaml b/Documentation/devicetree/bindings/timer/arm,arch_timer_mmio.yaml index 7a4a6ab85970..ab8f28993139 100644 --- a/Documentation/devicetree/bindings/timer/arm,arch_timer_mmio.yaml +++ b/Documentation/devicetree/bindings/timer/arm,arch_timer_mmio.yaml @@ -60,7 +60,7 @@ properties: be implemented in an always-on power domain." patternProperties: - '^frame@[0-9a-z]*$': + '^frame@[0-9a-f]+$': type: object additionalProperties: false description: A timer node has up to 8 frame sub-nodes, each with the following properties. diff --git a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml index 10c146424baa..cd3680dc002f 100644 --- a/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml +++ b/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml @@ -27,10 +27,13 @@ properties: - qcom,msm8996-ufshc - qcom,msm8998-ufshc - qcom,sa8775p-ufshc + - qcom,sc7180-ufshc - qcom,sc7280-ufshc + - qcom,sc8180x-ufshc - qcom,sc8280xp-ufshc - qcom,sdm845-ufshc - qcom,sm6115-ufshc + - qcom,sm6125-ufshc - qcom,sm6350-ufshc - qcom,sm8150-ufshc - qcom,sm8250-ufshc @@ -42,11 +45,11 @@ properties: - const: jedec,ufs-2.0 clocks: - minItems: 8 + minItems: 7 maxItems: 11 clock-names: - minItems: 8 + minItems: 7 maxItems: 11 dma-coherent: true @@ -112,6 +115,31 @@ required: allOf: - $ref: ufs-common.yaml + - if: + properties: + compatible: + contains: + enum: + - qcom,sc7180-ufshc + then: + properties: + clocks: + minItems: 7 + maxItems: 7 + clock-names: + items: + - const: core_clk + - const: bus_aggr_clk + - const: iface_clk + - const: core_clk_unipro + - const: ref_clk + - const: tx_lane0_sync_clk + - const: rx_lane0_sync_clk + reg: + maxItems: 1 + reg-names: + maxItems: 1 + - if: properties: compatible: @@ -120,6 +148,7 @@ allOf: - qcom,msm8998-ufshc - qcom,sa8775p-ufshc - qcom,sc7280-ufshc + - qcom,sc8180x-ufshc - qcom,sc8280xp-ufshc - qcom,sm8250-ufshc - qcom,sm8350-ufshc @@ -215,6 +244,7 @@ allOf: contains: enum: - qcom,sm6115-ufshc + - qcom,sm6125-ufshc then: properties: clocks: @@ -248,7 +278,7 @@ allOf: reg: maxItems: 1 clocks: - minItems: 8 + minItems: 7 maxItems: 8 else: properties: @@ -256,7 +286,7 @@ allOf: minItems: 1 maxItems: 2 clocks: - minItems: 8 + minItems: 7 maxItems: 11 unevaluatedProperties: false diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst index 0c153d79ccc4..29abf1eebf9f 100644 --- a/Documentation/driver-api/dma-buf.rst +++ b/Documentation/driver-api/dma-buf.rst @@ -77,7 +77,7 @@ consider though: the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other llseek operation will report -EINVAL. - If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all + If llseek on dma-buf FDs isn't supported the kernel will report -ESPIPE for all cases. Userspace can use this to detect support for discovering the dma-buf size using llseek. diff --git a/Documentation/driver-api/virtio/writing_virtio_drivers.rst b/Documentation/driver-api/virtio/writing_virtio_drivers.rst index e14c58796d25..e5de6f5d061a 100644 --- a/Documentation/driver-api/virtio/writing_virtio_drivers.rst +++ b/Documentation/driver-api/virtio/writing_virtio_drivers.rst @@ -97,7 +97,6 @@ like this:: static struct virtio_driver virtio_dummy_driver = { .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtio_dummy_probe, .remove = virtio_dummy_remove, diff --git a/Documentation/filesystems/bcachefs/index.rst b/Documentation/filesystems/bcachefs/index.rst new file mode 100644 index 000000000000..e2bd61ccd96f --- /dev/null +++ b/Documentation/filesystems/bcachefs/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================== +bcachefs Documentation +====================== + +.. toctree:: + :maxdepth: 2 + :numbered: + + errorcodes diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index 0ea1e44fa028..1f9b4c905a6a 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -69,6 +69,7 @@ Documentation for filesystem implementations. afs autofs autofs-mount-control + bcachefs/index befs bfs btrfs diff --git a/Documentation/gpu/amdgpu/debugging.rst b/Documentation/gpu/amdgpu/debugging.rst new file mode 100644 index 000000000000..e75f97d0e4ea --- /dev/null +++ b/Documentation/gpu/amdgpu/debugging.rst @@ -0,0 +1,80 @@ +=============== + GPU Debugging +=============== + +GPUVM Debugging +=============== + +To aid in debugging GPU virtual memory related problems, the driver supports a +number of options module parameters: + +`vm_fault_stop` - If non-0, halt the GPU memory controller on a GPU page fault. + +`vm_update_mode` - If non-0, use the CPU to update GPU page tables rather than +the GPU. + + +Decoding a GPUVM Page Fault +=========================== + +If you see a GPU page fault in the kernel log, you can decode it to figure +out what is going wrong in your application. A page fault in your kernel +log may look something like this: + +:: + + [gfxhub0] no-retry page fault (src_id:0 ring:24 vmid:3 pasid:32777, for process glxinfo pid 2424 thread glxinfo:cs0 pid 2425) + in page starting at address 0x0000800102800000 from IH client 0x1b (UTCL2) + VM_L2_PROTECTION_FAULT_STATUS:0x00301030 + Faulty UTCL2 client ID: TCP (0x8) + MORE_FAULTS: 0x0 + WALKER_ERROR: 0x0 + PERMISSION_FAULTS: 0x3 + MAPPING_ERROR: 0x0 + RW: 0x0 + +First you have the memory hub, gfxhub and mmhub. gfxhub is the memory +hub used for graphics, compute, and sdma on some chips. mmhub is the +memory hub used for multi-media and sdma on some chips. + +Next you have the vmid and pasid. If the vmid is 0, this fault was likely +caused by the kernel driver or firmware. If the vmid is non-0, it is generally +a fault in a user application. The pasid is used to link a vmid to a system +process id. If the process is active when the fault happens, the process +information will be printed. + +The GPU virtual address that caused the fault comes next. + +The client ID indicates the GPU block that caused the fault. +Some common client IDs: + +- CB/DB: The color/depth backend of the graphics pipe +- CPF: Command Processor Frontend +- CPC: Command Processor Compute +- CPG: Command Processor Graphics +- TCP/SQC/SQG: Shaders +- SDMA: SDMA engines +- VCN: Video encode/decode engines +- JPEG: JPEG engines + +PERMISSION_FAULTS describe what faults were encountered: + +- bit 0: the PTE was not valid +- bit 1: the PTE read bit was not set +- bit 2: the PTE write bit was not set +- bit 3: the PTE execute bit was not set + +Finally, RW, indicates whether the access was a read (0) or a write (1). + +In the example above, a shader (cliend id = TCP) generated a read (RW = 0x0) to +an invalid page (PERMISSION_FAULTS = 0x3) at GPU virtual address +0x0000800102800000. The user can then inspect their shader code and resource +descriptor state to determine what caused the GPU page fault. + +UMR +=== + +`umr `_ is a general purpose +GPU debugging and diagnostics tool. Please see the umr +`documentation `_ for more information +about its capabilities. diff --git a/Documentation/gpu/amdgpu/display/display-contributing.rst b/Documentation/gpu/amdgpu/display/display-contributing.rst index fdb2bea01d53..36f3077eee00 100644 --- a/Documentation/gpu/amdgpu/display/display-contributing.rst +++ b/Documentation/gpu/amdgpu/display/display-contributing.rst @@ -135,7 +135,7 @@ Enable underlay --------------- AMD display has this feature called underlay (which you can read more about at -'Documentation/GPU/amdgpu/display/mpo-overview.rst') which is intended to +'Documentation/gpu/amdgpu/display/mpo-overview.rst') which is intended to save power when playing a video. The basic idea is to put a video in the underlay plane at the bottom and the desktop in the plane above it with a hole in the video area. This feature is enabled in ChromeOS, and from our data diff --git a/Documentation/gpu/amdgpu/index.rst b/Documentation/gpu/amdgpu/index.rst index 912e699fd373..847e04924030 100644 --- a/Documentation/gpu/amdgpu/index.rst +++ b/Documentation/gpu/amdgpu/index.rst @@ -15,4 +15,5 @@ Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures. ras thermal driver-misc + debugging amdgpu-glossary diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index 13d3627d8bc0..abfe220764e1 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -398,6 +398,21 @@ Plane Damage Tracking Functions Reference .. kernel-doc:: include/drm/drm_damage_helper.h :internal: +Plane Panic Feature +------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_panic.c + :doc: overview + +Plane Panic Functions Reference +------------------------------- + +.. kernel-doc:: include/drm/drm_panic.h + :internal: + +.. kernel-doc:: drivers/gpu/drm/drm_panic.c + :export: + Display Modes Function Reference ================================ @@ -496,6 +511,13 @@ addition to the one mentioned above: * An IGT test must be submitted where reasonable. +For historical reasons, non-standard, driver-specific properties exist. If a KMS +driver wants to add support for one of those properties, the requirements for +new properties apply where possible. Additionally, the documented behavior must +match the de facto semantics of the existing property to ensure compatibility. +Developers of the driver that first added the property should help with those +tasks and must ACK the documented behavior if possible. + Property Types and Blob Property Support ---------------------------------------- diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index 0ca1550fd9dc..17261ba18313 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -204,6 +204,15 @@ DMC Firmware Support .. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc.c :internal: +DMC wakelock support +-------------------- + +.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c + :doc: DMC wakelock support + +.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c + :internal: + Video BIOS Table (VBT) ---------------------- diff --git a/Documentation/gpu/rfc/i915_vm_bind.h b/Documentation/gpu/rfc/i915_vm_bind.h index 8a8fcd4fceac..bc26dc126104 100644 --- a/Documentation/gpu/rfc/i915_vm_bind.h +++ b/Documentation/gpu/rfc/i915_vm_bind.h @@ -93,12 +93,11 @@ struct drm_i915_gem_timeline_fence { * Multiple VA mappings can be created to the same section of the object * (aliasing). * - * The @start, @offset and @length must be 4K page aligned. However the DG2 - * and XEHPSDV has 64K page size for device local memory and has compact page - * table. On those platforms, for binding device local-memory objects, the - * @start, @offset and @length must be 64K aligned. Also, UMDs should not mix - * the local memory 64K page and the system memory 4K page bindings in the same - * 2M range. + * The @start, @offset and @length must be 4K page aligned. However the DG2 has + * 64K page size for device local memory and has compact page table. On that + * platform, for binding device local-memory objects, the @start, @offset and + * @length must be 64K aligned. Also, UMDs should not mix the local memory 64K + * page and the system memory 4K page bindings in the same 2M range. * * Error code -EINVAL will be returned if @start, @offset and @length are not * properly aligned. In version 1 (See I915_PARAM_VM_BIND_VERSION), error code diff --git a/Documentation/mm/page_owner.rst b/Documentation/mm/page_owner.rst index 0d0334cd5179..3a45a20fc05a 100644 --- a/Documentation/mm/page_owner.rst +++ b/Documentation/mm/page_owner.rst @@ -24,10 +24,10 @@ fragmentation statistics can be obtained through gfp flag information of each page. It is already implemented and activated if page owner is enabled. Other usages are more than welcome. -It can also be used to show all the stacks and their outstanding -allocations, which gives us a quick overview of where the memory is going -without the need to screen through all the pages and match the allocation -and free operation. +It can also be used to show all the stacks and their current number of +allocated base pages, which gives us a quick overview of where the memory +is going without the need to screen through all the pages and match the +allocation and free operation. page owner is disabled by default. So, if you'd like to use it, you need to add "page_owner=on" to your boot cmdline. If the kernel is built @@ -75,42 +75,45 @@ Usage cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt cat stacks.txt - prep_new_page+0xa9/0x120 - get_page_from_freelist+0x7e6/0x2140 - __alloc_pages+0x18a/0x370 - new_slab+0xc8/0x580 - ___slab_alloc+0x1f2/0xaf0 - __slab_alloc.isra.86+0x22/0x40 - kmem_cache_alloc+0x31b/0x350 - __khugepaged_enter+0x39/0x100 - dup_mmap+0x1c7/0x5ce - copy_process+0x1afe/0x1c90 - kernel_clone+0x9a/0x3c0 - __do_sys_clone+0x66/0x90 - do_syscall_64+0x7f/0x160 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - stack_count: 234 + post_alloc_hook+0x177/0x1a0 + get_page_from_freelist+0xd01/0xd80 + __alloc_pages+0x39e/0x7e0 + allocate_slab+0xbc/0x3f0 + ___slab_alloc+0x528/0x8a0 + kmem_cache_alloc+0x224/0x3b0 + sk_prot_alloc+0x58/0x1a0 + sk_alloc+0x32/0x4f0 + inet_create+0x427/0xb50 + __sock_create+0x2e4/0x650 + inet_ctl_sock_create+0x30/0x180 + igmp_net_init+0xc1/0x130 + ops_init+0x167/0x410 + setup_net+0x304/0xa60 + copy_net_ns+0x29b/0x4a0 + create_new_namespaces+0x4a1/0x820 + nr_base_pages: 16 ... ... echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt cat stacks_7000.txt - prep_new_page+0xa9/0x120 - get_page_from_freelist+0x7e6/0x2140 - __alloc_pages+0x18a/0x370 - alloc_pages_mpol+0xdf/0x1e0 - folio_alloc+0x14/0x50 - filemap_alloc_folio+0xb0/0x100 - page_cache_ra_unbounded+0x97/0x180 - filemap_fault+0x4b4/0x1200 - __do_fault+0x2d/0x110 - do_pte_missing+0x4b0/0xa30 - __handle_mm_fault+0x7fa/0xb70 - handle_mm_fault+0x125/0x300 - do_user_addr_fault+0x3c9/0x840 - exc_page_fault+0x68/0x150 - asm_exc_page_fault+0x22/0x30 - stack_count: 8248 + post_alloc_hook+0x177/0x1a0 + get_page_from_freelist+0xd01/0xd80 + __alloc_pages+0x39e/0x7e0 + alloc_pages_mpol+0x22e/0x490 + folio_alloc+0xd5/0x110 + filemap_alloc_folio+0x78/0x230 + page_cache_ra_order+0x287/0x6f0 + filemap_get_pages+0x517/0x1160 + filemap_read+0x304/0x9f0 + xfs_file_buffered_read+0xe6/0x1d0 [xfs] + xfs_file_read_iter+0x1f0/0x380 [xfs] + __kernel_read+0x3b9/0x730 + kernel_read_file+0x309/0x4d0 + __do_sys_finit_module+0x381/0x730 + do_syscall_64+0x8d/0x150 + entry_SYSCALL_64_after_hwframe+0x62/0x6a + nr_base_pages: 20824 ... cat /sys/kernel/debug/page_owner > page_owner_full.txt diff --git a/Documentation/networking/devlink/devlink-eswitch-attr.rst b/Documentation/networking/devlink/devlink-eswitch-attr.rst new file mode 100644 index 000000000000..08bb39ab1528 --- /dev/null +++ b/Documentation/networking/devlink/devlink-eswitch-attr.rst @@ -0,0 +1,76 @@ +.. SPDX-License-Identifier: GPL-2.0 + +========================== +Devlink E-Switch Attribute +========================== + +Devlink E-Switch supports two modes of operation: legacy and switchdev. +Legacy mode operates based on traditional MAC/VLAN steering rules. Switching +decisions are made based on MAC addresses, VLANs, etc. There is limited ability +to offload switching rules to hardware. + +On the other hand, switchdev mode allows for more advanced offloading +capabilities of the E-Switch to hardware. In switchdev mode, more switching +rules and logic can be offloaded to the hardware switch ASIC. It enables +representor netdevices that represent the slow path of virtual functions (VFs) +or scalable-functions (SFs) of the device. See more information about +:ref:`Documentation/networking/switchdev.rst ` and +:ref:`Documentation/networking/representors.rst `. + +In addition, the devlink E-Switch also comes with other attributes listed +in the following section. + +Attributes Description +====================== + +The following is a list of E-Switch attributes. + +.. list-table:: E-Switch attributes + :widths: 8 5 45 + + * - Name + - Type + - Description + * - ``mode`` + - enum + - The mode of the device. The mode can be one of the following: + + * ``legacy`` operates based on traditional MAC/VLAN steering + rules. + * ``switchdev`` allows for more advanced offloading capabilities of + the E-Switch to hardware. + * - ``inline-mode`` + - enum + - Some HWs need the VF driver to put part of the packet + headers on the TX descriptor so the e-switch can do proper + matching and steering. Support for both switchdev mode and legacy mode. + + * ``none`` none. + * ``link`` L2 mode. + * ``network`` L3 mode. + * ``transport`` L4 mode. + * - ``encap-mode`` + - enum + - The encapsulation mode of the device. Support for both switchdev mode + and legacy mode. The mode can be one of the following: + + * ``none`` Disable encapsulation support. + * ``basic`` Enable encapsulation support. + +Example Usage +============= + +.. code:: shell + + # enable switchdev mode + $ devlink dev eswitch set pci/0000:08:00.0 mode switchdev + + # set inline-mode and encap-mode + $ devlink dev eswitch set pci/0000:08:00.0 inline-mode none encap-mode basic + + # display devlink device eswitch attributes + $ devlink dev eswitch show pci/0000:08:00.0 + pci/0000:08:00.0: mode switchdev inline-mode none encap-mode basic + + # enable encap-mode with legacy mode + $ devlink dev eswitch set pci/0000:08:00.0 mode legacy inline-mode none encap-mode basic diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst index e14d7a701b72..948c8c44e233 100644 --- a/Documentation/networking/devlink/index.rst +++ b/Documentation/networking/devlink/index.rst @@ -67,6 +67,7 @@ general. devlink-selftests devlink-trap devlink-linecard + devlink-eswitch-attr Driver-specific documentation ----------------------------- diff --git a/Documentation/networking/representors.rst b/Documentation/networking/representors.rst index decb39c19b9e..5e23386f6968 100644 --- a/Documentation/networking/representors.rst +++ b/Documentation/networking/representors.rst @@ -1,4 +1,5 @@ .. SPDX-License-Identifier: GPL-2.0 +.. _representors: ============================= Network Function Representors diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index bb2100228cc7..6e9a4597bf2c 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -252,7 +252,7 @@ an involved disclosed party. The current ambassadors list: AMD Tom Lendacky Ampere Darren Hart ARM Catalin Marinas - IBM Power Anton Blanchard + IBM Power Michael Ellerman IBM Z Christian Borntraeger Intel Tony Luck Qualcomm Trilok Soni diff --git a/Documentation/rust/arch-support.rst b/Documentation/rust/arch-support.rst index 5c4fa9f5d1cd..c9137710633a 100644 --- a/Documentation/rust/arch-support.rst +++ b/Documentation/rust/arch-support.rst @@ -16,7 +16,7 @@ support corresponds to ``S`` values in the ``MAINTAINERS`` file. Architecture Level of support Constraints ============= ================ ============================================== ``arm64`` Maintained Little Endian only. -``loongarch`` Maintained - +``loongarch`` Maintained \- ``um`` Maintained ``x86_64`` only. ``x86`` Maintained ``x86_64`` only. ============= ================ ============================================== diff --git a/Documentation/timers/no_hz.rst b/Documentation/timers/no_hz.rst index f8786be15183..7fe8ef9718d8 100644 --- a/Documentation/timers/no_hz.rst +++ b/Documentation/timers/no_hz.rst @@ -129,11 +129,8 @@ adaptive-tick CPUs: At least one non-adaptive-tick CPU must remain online to handle timekeeping tasks in order to ensure that system calls like gettimeofday() returns accurate values on adaptive-tick CPUs. (This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running -user processes to observe slight drifts in clock rate.) Therefore, the -boot CPU is prohibited from entering adaptive-ticks mode. Specifying a -"nohz_full=" mask that includes the boot CPU will result in a boot-time -error message, and the boot CPU will be removed from the mask. Note that -this means that your system must have at least two CPUs in order for +user processes to observe slight drifts in clock rate.) Note that this +means that your system must have at least two CPUs in order for CONFIG_NO_HZ_FULL=y to do anything for you. Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded. diff --git a/Documentation/virt/kvm/x86/amd-memory-encryption.rst b/Documentation/virt/kvm/x86/amd-memory-encryption.rst index 995780088eb2..84335d119ff1 100644 --- a/Documentation/virt/kvm/x86/amd-memory-encryption.rst +++ b/Documentation/virt/kvm/x86/amd-memory-encryption.rst @@ -46,21 +46,16 @@ SEV hardware uses ASIDs to associate a memory encryption key with a VM. Hence, the ASID for the SEV-enabled guests must be from 1 to a maximum value defined in the CPUID 0x8000001f[ecx] field. -SEV Key Management -================== +The KVM_MEMORY_ENCRYPT_OP ioctl +=============================== -The SEV guest key management is handled by a separate processor called the AMD -Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure -key management interface to perform common hypervisor activities such as -encrypting bootstrap code, snapshot, migrating and debugging the guest. For more -information, see the SEV Key Management spec [api-spec]_ - -The main ioctl to access SEV is KVM_MEMORY_ENCRYPT_OP. If the argument -to KVM_MEMORY_ENCRYPT_OP is NULL, the ioctl returns 0 if SEV is enabled -and ``ENOTTY`` if it is disabled (on some older versions of Linux, -the ioctl runs normally even with a NULL argument, and therefore will -likely return ``EFAULT``). If non-NULL, the argument to KVM_MEMORY_ENCRYPT_OP -must be a struct kvm_sev_cmd:: +The main ioctl to access SEV is KVM_MEMORY_ENCRYPT_OP, which operates on +the VM file descriptor. If the argument to KVM_MEMORY_ENCRYPT_OP is NULL, +the ioctl returns 0 if SEV is enabled and ``ENOTTY`` if it is disabled +(on some older versions of Linux, the ioctl tries to run normally even +with a NULL argument, and therefore will likely return ``EFAULT`` instead +of zero if SEV is enabled). If non-NULL, the argument to +KVM_MEMORY_ENCRYPT_OP must be a struct kvm_sev_cmd:: struct kvm_sev_cmd { __u32 id; @@ -87,10 +82,6 @@ guests, such as launching, running, snapshotting, migrating and decommissioning. The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform context. In a typical workflow, this command should be the first command issued. -The firmware can be initialized either by using its own non-volatile storage or -the OS can manage the NV storage for the firmware using the module parameter -``init_ex_path``. If the file specified by ``init_ex_path`` does not exist or -is invalid, the OS will create or override the file with output from PSP. Returns: 0 on success, -negative on error @@ -434,6 +425,21 @@ issued by the hypervisor to make the guest ready for execution. Returns: 0 on success, -negative on error +Firmware Management +=================== + +The SEV guest key management is handled by a separate processor called the AMD +Secure Processor (AMD-SP). Firmware running inside the AMD-SP provides a secure +key management interface to perform common hypervisor activities such as +encrypting bootstrap code, snapshot, migrating and debugging the guest. For more +information, see the SEV Key Management spec [api-spec]_ + +The AMD-SP firmware can be initialized either by using its own non-volatile +storage or the OS can manage the NV storage for the firmware using +parameter ``init_ex_path`` of the ``ccp`` module. If the file specified +by ``init_ex_path`` does not exist or is invalid, the OS will create or +override the file with PSP non-volatile storage. + References ========== diff --git a/Documentation/virt/kvm/x86/msr.rst b/Documentation/virt/kvm/x86/msr.rst index 9315fc385fb0..3aecf2a70e7b 100644 --- a/Documentation/virt/kvm/x86/msr.rst +++ b/Documentation/virt/kvm/x86/msr.rst @@ -193,8 +193,8 @@ data: Asynchronous page fault (APF) control MSR. Bits 63-6 hold 64-byte aligned physical address of a 64 byte memory area - which must be in guest RAM and must be zeroed. This memory is expected - to hold a copy of the following structure:: + which must be in guest RAM. This memory is expected to hold the + following structure:: struct kvm_vcpu_pv_apf_data { /* Used for 'page not present' events delivered via #PF */ @@ -204,7 +204,6 @@ data: __u32 token; __u8 pad[56]; - __u32 enabled; }; Bits 5-4 of the MSR are reserved and should be zero. Bit 0 is set to 1 @@ -232,14 +231,14 @@ data: as regular page fault, guest must reset 'flags' to '0' before it does something that can generate normal page fault. - Bytes 5-7 of 64 byte memory location ('token') will be written to by the + Bytes 4-7 of 64 byte memory location ('token') will be written to by the hypervisor at the time of APF 'page ready' event injection. The content - of these bytes is a token which was previously delivered as 'page not - present' event. The event indicates the page in now available. Guest is - supposed to write '0' to 'token' when it is done handling 'page ready' - event and to write 1' to MSR_KVM_ASYNC_PF_ACK after clearing the location; - writing to the MSR forces KVM to re-scan its queue and deliver the next - pending notification. + of these bytes is a token which was previously delivered in CR2 as + 'page not present' event. The event indicates the page is now available. + Guest is supposed to write '0' to 'token' when it is done handling + 'page ready' event and to write '1' to MSR_KVM_ASYNC_PF_ACK after + clearing the location; writing to the MSR forces KVM to re-scan its + queue and deliver the next pending notification. Note, MSR_KVM_ASYNC_PF_INT MSR specifying the interrupt vector for 'page ready' APF delivery needs to be written to before enabling APF mechanism diff --git a/MAINTAINERS b/MAINTAINERS index 6ea4035e6b92..abd4dbe2c653 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2202,7 +2202,6 @@ N: mxs ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE M: Shawn Guo -M: Li Yang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git @@ -2719,7 +2718,7 @@ F: sound/soc/rockchip/ N: rockchip ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski R: Alim Akhtar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org @@ -3584,6 +3583,7 @@ S: Supported C: irc://irc.oftc.net/bcache T: git https://evilpiepirate.org/git/bcachefs.git F: fs/bcachefs/ +F: Documentation/filesystems/bcachefs/ BDISP ST MEDIA DRIVER M: Fabien Dessenne @@ -4880,7 +4880,6 @@ F: drivers/power/supply/cw2015_battery.c CEPH COMMON CODE (LIBCEPH) M: Ilya Dryomov M: Xiubo Li -R: Jeff Layton L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ @@ -4892,7 +4891,6 @@ F: net/ceph/ CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH) M: Xiubo Li M: Ilya Dryomov -R: Jeff Layton L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ @@ -5568,7 +5566,7 @@ F: drivers/cpuidle/cpuidle-big_little.c CPUIDLE DRIVER - ARM EXYNOS M: Daniel Lezcano M: Kukjin Kim -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski L: linux-pm@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -6764,6 +6762,14 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml F: drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c +DRM DRIVER FOR LG SW43408 PANELS +M: Sumit Semwal +M: Caleb Connolly +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml +F: drivers/gpu/drm/panel/panel-lg-sw43408.c + DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER M: Paul Kocialkowski S: Supported @@ -7843,9 +7849,8 @@ W: http://aeschi.ch.eu.org/efs/ F: fs/efs/ EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER -M: Douglas Miller L: netdev@vger.kernel.org -S: Maintained +S: Orphan F: drivers/net/ethernet/ibm/ehea/ ELM327 CAN NETWORK DRIVER @@ -8535,7 +8540,6 @@ S: Maintained F: drivers/video/fbdev/fsl-diu-fb.* FREESCALE DMA DRIVER -M: Li Yang M: Zhang Wei L: linuxppc-dev@lists.ozlabs.org S: Maintained @@ -8700,10 +8704,9 @@ F: drivers/soc/fsl/qe/tsa.h F: include/dt-bindings/soc/cpm1-fsl,tsa.h FREESCALE QUICC ENGINE UCC ETHERNET DRIVER -M: Li Yang L: netdev@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/net/ethernet/freescale/ucc_geth* FREESCALE QUICC ENGINE UCC HDLC DRIVER @@ -8720,10 +8723,9 @@ S: Maintained F: drivers/tty/serial/ucc_uart.c FREESCALE SOC DRIVERS -M: Li Yang L: linuxppc-dev@lists.ozlabs.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained +S: Orphan F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml F: Documentation/devicetree/bindings/soc/fsl/ F: drivers/soc/fsl/ @@ -8757,17 +8759,15 @@ F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml F: sound/soc/fsl/fsl_qmc_audio.c FREESCALE USB PERIPHERAL DRIVERS -M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/usb/gadget/udc/fsl* FREESCALE USB PHY DRIVER -M: Ran Wang L: linux-usb@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/usb/phy/phy-fsl-usb* FREEVXFS FILESYSTEM @@ -9012,7 +9012,7 @@ F: drivers/i2c/muxes/i2c-mux-gpio.c F: include/linux/platform_data/i2c-mux-gpio.h GENERIC GPIO RESET DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: drivers/reset/reset-gpio.c @@ -9595,7 +9595,7 @@ F: kernel/power/ HID CORE LAYER M: Jiri Kosina -M: Benjamin Tissoires +M: Benjamin Tissoires L: linux-input@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git @@ -10042,7 +10042,7 @@ F: drivers/media/platform/st/sti/hva HWPOISON MEMORY FAILURE HANDLING M: Miaohe Lin -R: Naoya Horiguchi +R: Naoya Horiguchi L: linux-mm@kvack.org S: Maintained F: mm/hwpoison-inject.c @@ -12013,7 +12013,7 @@ F: include/keys/encrypted-type.h F: security/keys/encrypted-keys/ KEYS-TRUSTED -M: James Bottomley +M: James Bottomley M: Jarkko Sakkinen M: Mimi Zohar L: linux-integrity@vger.kernel.org @@ -13307,7 +13307,7 @@ F: drivers/iio/adc/max11205.c MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS R: Iskren Chernev -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski R: Marek Szyprowski R: Matheus Castello L: linux-pm@vger.kernel.org @@ -13317,7 +13317,7 @@ F: drivers/power/supply/max17040_battery.c MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS R: Hans de Goede -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski R: Marek Szyprowski R: Sebastian Krzyszkowiak R: Purism Kernel Team @@ -13375,7 +13375,7 @@ F: Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml F: drivers/power/supply/max77976_charger.c MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-pm@vger.kernel.org S: Maintained B: mailto:linux-samsung-soc@vger.kernel.org @@ -13386,7 +13386,7 @@ F: drivers/power/supply/max77693_charger.c MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS M: Chanwoo Choi -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained B: mailto:linux-samsung-soc@vger.kernel.org @@ -14031,6 +14031,7 @@ F: drivers/net/ethernet/mellanox/mlx4/en_* MELLANOX ETHERNET DRIVER (mlx5e) M: Saeed Mahameed +M: Tariq Toukan L: netdev@vger.kernel.org S: Supported W: http://www.mellanox.com @@ -14098,6 +14099,7 @@ F: include/uapi/rdma/mlx4-abi.h MELLANOX MLX5 core VPI driver M: Saeed Mahameed M: Leon Romanovsky +M: Tariq Toukan L: netdev@vger.kernel.org L: linux-rdma@vger.kernel.org S: Supported @@ -14168,7 +14170,7 @@ F: mm/mm_init.c F: tools/testing/memblock/ MEMORY CONTROLLER DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained B: mailto:krzysztof.kozlowski@linaro.org @@ -14373,7 +14375,7 @@ F: drivers/dma/at_xdmac.c F: include/dt-bindings/dma/at91.h MICROCHIP AT91 SERIAL DRIVER -M: Richard Genoud +M: Richard Genoud S: Maintained F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml F: drivers/tty/serial/atmel_serial.c @@ -14579,6 +14581,14 @@ S: Supported F: Documentation/devicetree/bindings/pwm/atmel,at91sam-pwm.yaml F: drivers/pwm/pwm-atmel.c +MICROCHIP SAM9x7-COMPATIBLE LVDS CONTROLLER +M: Manikandan Muralidharan +M: Dharma Balasubiramani +L: dri-devel@lists.freedesktop.org +S: Supported +F: Documentation/devicetree/bindings/display/bridge/microchip,sam9x75-lvds.yaml +F: drivers/gpu/drm/bridge/microchip-lvds.c + MICROCHIP SAMA5D2-COMPATIBLE ADC DRIVER M: Eugen Hristev L: linux-iio@vger.kernel.org @@ -15549,7 +15559,7 @@ F: include/uapi/linux/nexthop.h F: net/ipv4/nexthop.c NFC SUBSYSTEM -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/nfc/ @@ -15926,7 +15936,7 @@ F: Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml F: drivers/regulator/pf8x00-regulator.c NXP PTN5150A CC LOGIC AND EXTCON DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml @@ -16537,7 +16547,7 @@ K: of_overlay_remove OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS M: Rob Herring -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Conor Dooley L: devicetree@vger.kernel.org S: Maintained @@ -16743,9 +16753,9 @@ F: include/uapi/linux/ppdev.h PARAVIRT_OPS INTERFACE M: Juergen Gross -R: Ajay Kaher -R: Alexey Makhalov -R: VMware PV-Drivers Reviewers +R: Ajay Kaher +R: Alexey Makhalov +R: Broadcom internal kernel review list L: virtualization@lists.linux.dev L: x86@kernel.org S: Supported @@ -16816,12 +16826,6 @@ S: Maintained F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h -PCA9541 I2C BUS MASTER SELECTOR DRIVER -M: Guenter Roeck -L: linux-i2c@vger.kernel.org -S: Maintained -F: drivers/i2c/muxes/i2c-mux-pca9541.c - PCI DRIVER FOR AARDVARK (Marvell Armada 3700) M: Thomas Petazzoni M: Pali Rohár @@ -16984,7 +16988,6 @@ F: drivers/pci/controller/dwc/pci-exynos.c PCI DRIVER FOR SYNOPSYS DESIGNWARE M: Jingoo Han -M: Gustavo Pimentel M: Manivannan Sadhasivam L: linux-pci@vger.kernel.org S: Maintained @@ -17495,7 +17498,7 @@ F: Documentation/devicetree/bindings/pinctrl/renesas,* F: drivers/pinctrl/renesas/ PIN CONTROLLER - SAMSUNG -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Sylwester Nawrocki R: Alim Akhtar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -17891,7 +17894,7 @@ F: Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml F: drivers/media/rc/pwm-ir-tx.c PWM SUBSYSTEM -M: Uwe Kleine-König +M: Uwe Kleine-König L: linux-pwm@vger.kernel.org S: Maintained Q: https://patchwork.ozlabs.org/project/linux-pwm/list/ @@ -19463,7 +19466,7 @@ F: Documentation/devicetree/bindings/sound/samsung* F: sound/soc/samsung/ SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -19498,7 +19501,7 @@ S: Maintained F: drivers/platform/x86/samsung-laptop.c SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -19524,7 +19527,7 @@ F: drivers/media/platform/samsung/s3c-camif/ F: include/media/drv-intf/s3c_camif.h SAMSUNG S3FWRN5 NFC DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml F: drivers/nfc/s3fwrn5 @@ -19545,7 +19548,7 @@ S: Supported F: drivers/media/i2c/s5k5baf.c SAMSUNG S5P Security SubSystem (SSS) DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Vladimir Zapolskiy L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org @@ -19567,7 +19570,7 @@ F: Documentation/devicetree/bindings/media/samsung,fimc.yaml F: drivers/media/platform/samsung/exynos4-is/ SAMSUNG SOC CLOCK DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Sylwester Nawrocki M: Chanwoo Choi R: Alim Akhtar @@ -19599,7 +19602,7 @@ F: drivers/net/ethernet/samsung/sxgbe/ SAMSUNG THERMAL DRIVER M: Bartlomiej Zolnierkiewicz -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-pm@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -19686,7 +19689,7 @@ F: drivers/scsi/sg.c F: include/scsi/sg.h SCSI SUBSYSTEM -M: "James E.J. Bottomley" +M: "James E.J. Bottomley" M: "Martin K. Petersen" L: linux-scsi@vger.kernel.org S: Maintained @@ -20195,7 +20198,6 @@ F: include/linux/platform_data/simplefb.h SIOX M: Thorsten Scherer -M: Uwe Kleine-König R: Pengutronix Kernel Team S: Supported F: drivers/gpio/gpio-siox.c @@ -22440,6 +22442,7 @@ S: Maintained W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity Q: https://patchwork.kernel.org/project/linux-integrity/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git +F: Documentation/devicetree/bindings/tpm/ F: drivers/char/tpm/ TPS546D24 DRIVER @@ -22586,6 +22589,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/ B: https://bugzilla.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git turbostat F: tools/power/x86/turbostat/ +F: tools/testing/selftests/turbostat/ TW5864 VIDEO4LINUX DRIVER M: Bluecherry Maintainers @@ -22855,7 +22859,7 @@ F: drivers/usb/host/ehci* USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) M: Jiri Kosina -M: Benjamin Tissoires +M: Benjamin Tissoires L: linux-usb@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git @@ -23664,9 +23668,9 @@ S: Supported F: drivers/misc/vmw_balloon.c VMWARE HYPERVISOR INTERFACE -M: Ajay Kaher -M: Alexey Makhalov -R: VMware PV-Drivers Reviewers +M: Ajay Kaher +M: Alexey Makhalov +R: Broadcom internal kernel review list L: virtualization@lists.linux.dev L: x86@kernel.org S: Supported @@ -23675,34 +23679,34 @@ F: arch/x86/include/asm/vmware.h F: arch/x86/kernel/cpu/vmware.c VMWARE PVRDMA DRIVER -M: Bryan Tan -M: Vishnu Dasa -R: VMware PV-Drivers Reviewers +M: Bryan Tan +M: Vishnu Dasa +R: Broadcom internal kernel review list L: linux-rdma@vger.kernel.org S: Supported F: drivers/infiniband/hw/vmw_pvrdma/ VMWARE PVSCSI DRIVER -M: Vishal Bhakta -R: VMware PV-Drivers Reviewers +M: Vishal Bhakta +R: Broadcom internal kernel review list L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/vmw_pvscsi.c F: drivers/scsi/vmw_pvscsi.h VMWARE VIRTUAL PTP CLOCK DRIVER -M: Jeff Sipek -R: Ajay Kaher -R: Alexey Makhalov -R: VMware PV-Drivers Reviewers +M: Nick Shi +R: Ajay Kaher +R: Alexey Makhalov +R: Broadcom internal kernel review list L: netdev@vger.kernel.org S: Supported F: drivers/ptp/ptp_vmw.c VMWARE VMCI DRIVER -M: Bryan Tan -M: Vishnu Dasa -R: VMware PV-Drivers Reviewers +M: Bryan Tan +M: Vishnu Dasa +R: Broadcom internal kernel review list L: linux-kernel@vger.kernel.org S: Supported F: drivers/misc/vmw_vmci/ @@ -23717,16 +23721,16 @@ F: drivers/input/mouse/vmmouse.c F: drivers/input/mouse/vmmouse.h VMWARE VMXNET3 ETHERNET DRIVER -M: Ronak Doshi -R: VMware PV-Drivers Reviewers +M: Ronak Doshi +R: Broadcom internal kernel review list L: netdev@vger.kernel.org S: Supported F: drivers/net/vmxnet3/ VMWARE VSOCK VMCI TRANSPORT DRIVER -M: Bryan Tan -M: Vishnu Dasa -R: VMware PV-Drivers Reviewers +M: Bryan Tan +M: Vishnu Dasa +R: Broadcom internal kernel review list L: linux-kernel@vger.kernel.org S: Supported F: net/vmw_vsock/vmci_transport* @@ -23794,7 +23798,7 @@ S: Orphan F: drivers/mmc/host/vub300.c W1 DALLAS'S 1-WIRE BUS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: Documentation/devicetree/bindings/w1/ F: Documentation/w1/ diff --git a/Makefile b/Makefile index 4bef6323c47d..40fb2ca6fe4c 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 9 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc6 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* diff --git a/arch/Kconfig b/arch/Kconfig index 9f066785bb71..30f7930275d8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -9,6 +9,14 @@ # source "arch/$(SRCARCH)/Kconfig" +config ARCH_CONFIGURES_CPU_MITIGATIONS + bool + +if !ARCH_CONFIGURES_CPU_MITIGATIONS +config CPU_MITIGATIONS + def_bool y +endif + menu "General architecture-dependent options" config ARCH_HAS_SUBPAGE_FAULTS @@ -1172,12 +1180,12 @@ config PAGE_SIZE_LESS_THAN_256KB config PAGE_SHIFT int - default 12 if PAGE_SIZE_4KB - default 13 if PAGE_SIZE_8KB - default 14 if PAGE_SIZE_16KB - default 15 if PAGE_SIZE_32KB - default 16 if PAGE_SIZE_64KB - default 18 if PAGE_SIZE_256KB + default 12 if PAGE_SIZE_4KB + default 13 if PAGE_SIZE_8KB + default 14 if PAGE_SIZE_16KB + default 15 if PAGE_SIZE_32KB + default 16 if PAGE_SIZE_64KB + default 18 if PAGE_SIZE_256KB # This allows to use a set of generic functions to determine mmap base # address by giving priority to top-down scheme only if the process diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 99d2845f3feb..4092bec198be 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -6,7 +6,6 @@ config ARC def_bool y select ARC_TIMERS - select ARCH_HAS_CPU_CACHE_ALIASING select ARCH_HAS_CACHE_LINE_SIZE select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DMA_PREP_COHERENT diff --git a/arch/arc/boot/Makefile b/arch/arc/boot/Makefile index 5648748c285f..5a8550124b73 100644 --- a/arch/arc/boot/Makefile +++ b/arch/arc/boot/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -# uImage build relies on mkimage being availble on your host for ARC target +# uImage build relies on mkimage being available on your host for ARC target # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage -# and make sure it's reacable from your PATH +# and make sure it's reachable from your PATH OBJCOPYFLAGS= -O binary -R .note -R .note.gnu.build-id -R .comment -S diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi index 3434c8131ecd..c0a812674ce9 100644 --- a/arch/arc/boot/dts/axc003.dtsi +++ b/arch/arc/boot/dts/axc003.dtsi @@ -119,9 +119,9 @@ mmc@15000 { /* * The DW APB ICTL intc on MB is connected to CPU intc via a * DT "invisible" DW APB GPIO block, configured to simply pass thru - * interrupts - setup accordinly in platform init (plat-axs10x/ax10x.c) + * interrupts - setup accordingly in platform init (plat-axs10x/ax10x.c) * - * So here we mimic a direct connection betwen them, ignoring the + * So here we mimic a direct connection between them, ignoring the * ABPG GPIO. Thus set "interrupts = <24>" (DW APB GPIO to core) * instead of "interrupts = <12>" (DW APB ICTL to DW APB GPIO) * diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts index 6691f4255077..41b980df862b 100644 --- a/arch/arc/boot/dts/hsdk.dts +++ b/arch/arc/boot/dts/hsdk.dts @@ -205,7 +205,6 @@ dmac_cfg_clk: dmac-gpu-cfg-clk { }; gmac: ethernet@8000 { - #interrupt-cells = <1>; compatible = "snps,dwmac"; reg = <0x8000 0x2000>; interrupts = <10>; diff --git a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi index 90a412026e64..0e0e2d337bf8 100644 --- a/arch/arc/boot/dts/vdk_axs10x_mb.dtsi +++ b/arch/arc/boot/dts/vdk_axs10x_mb.dtsi @@ -113,7 +113,7 @@ mmc@15000 { /* * Embedded Vision subsystem UIO mappings; only relevant for EV VDK * - * This node is intentionally put outside of MB above becase + * This node is intentionally put outside of MB above because * it maps areas outside of MB's 0xez-0xfz. */ uio_ev: uio@d0000000 { diff --git a/arch/arc/include/asm/cachetype.h b/arch/arc/include/asm/cachetype.h deleted file mode 100644 index 05fc7ed59712..000000000000 --- a/arch/arc/include/asm/cachetype.h +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_ARC_CACHETYPE_H -#define __ASM_ARC_CACHETYPE_H - -#include - -#define cpu_dcache_is_aliasing() true - -#endif diff --git a/arch/arc/include/asm/dsp.h b/arch/arc/include/asm/dsp.h index 202c78e56704..f496dbc4640b 100644 --- a/arch/arc/include/asm/dsp.h +++ b/arch/arc/include/asm/dsp.h @@ -12,7 +12,7 @@ /* * DSP-related saved registers - need to be saved only when you are * scheduled out. - * structure fields name must correspond to aux register defenitions for + * structure fields name must correspond to aux register definitions for * automatic offset calculation in DSP_AUX_SAVE_RESTORE macros */ struct dsp_callee_regs { diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 92c3e9f13252..00946fe04c9b 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -7,7 +7,7 @@ * Stack switching code can no longer reliably rely on the fact that * if we are NOT in user mode, stack is switched to kernel mode. * e.g. L2 IRQ interrupted a L1 ISR which had not yet completed - * it's prologue including stack switching from user mode + * its prologue including stack switching from user mode * * Vineetg: Aug 28th 2008: Bug #94984 * -Zero Overhead Loop Context shd be cleared when entering IRQ/EXcp/Trap @@ -143,7 +143,7 @@ * 2. L1 IRQ taken, ISR starts (CPU auto-switched to KERNEL mode) * 3. But before it could switch SP from USER to KERNEL stack * a L2 IRQ "Interrupts" L1 - * Thay way although L2 IRQ happened in Kernel mode, stack is still + * That way although L2 IRQ happened in Kernel mode, stack is still * not switched. * To handle this, we may need to switch stack even if in kernel mode * provided SP has values in range of USER mode stack ( < 0x7000_0000 ) @@ -173,7 +173,7 @@ GET_CURR_TASK_ON_CPU r9 - /* With current tsk in r9, get it's kernel mode stack base */ + /* With current tsk in r9, get its kernel mode stack base */ GET_TSK_STACK_BASE r9, r9 /* save U mode SP @ pt_regs->sp */ @@ -282,7 +282,7 @@ * NOTE: * * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg - * for memory load operations. If used in that way interrupts are deffered + * for memory load operations. If used in that way interrupts are deferred * by hardware and that is not good. *-------------------------------------------------------------*/ .macro EXCEPTION_EPILOGUE @@ -350,7 +350,7 @@ * NOTE: * * It is recommended that lp_count/ilink1/ilink2 not be used as a dest reg - * for memory load operations. If used in that way interrupts are deffered + * for memory load operations. If used in that way interrupts are deferred * by hardware and that is not good. *-------------------------------------------------------------*/ .macro INTERRUPT_EPILOGUE LVL diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index cf1ba376e992..38c35722cebf 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -7,7 +7,7 @@ #ifndef __ASM_ARC_ENTRY_H #define __ASM_ARC_ENTRY_H -#include /* For NR_syscalls defination */ +#include /* For NR_syscalls definition */ #include #include #include /* For VMALLOC_START */ @@ -56,7 +56,7 @@ .endm /*------------------------------------------------------------- - * given a tsk struct, get to the base of it's kernel mode stack + * given a tsk struct, get to the base of its kernel mode stack * tsk->thread_info is really a PAGE, whose bottom hoists stack * which grows upwards towards thread_info *------------------------------------------------------------*/ diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index c574712ad865..9cd79263acba 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -10,7 +10,7 @@ * ARCv2 can support 240 interrupts in the core interrupts controllers and * 128 interrupts in IDU. Thus 512 virtual IRQs must be enough for most * configurations of boards. - * This doesnt affect ARCompact, but we change it to same value + * This doesn't affect ARCompact, but we change it to same value */ #define NR_IRQS 512 diff --git a/arch/arc/include/asm/irqflags-compact.h b/arch/arc/include/asm/irqflags-compact.h index 0d63e568d64c..936a2f21f315 100644 --- a/arch/arc/include/asm/irqflags-compact.h +++ b/arch/arc/include/asm/irqflags-compact.h @@ -46,7 +46,7 @@ * IRQ Control Macros * * All of them have "memory" clobber (compiler barrier) which is needed to - * ensure that LD/ST requiring irq safetly (R-M-W when LLSC is not available) + * ensure that LD/ST requiring irq safety (R-M-W when LLSC is not available) * are redone after IRQs are re-enabled (and gcc doesn't reuse stale register) * * Noted at the time of Abilis Timer List corruption diff --git a/arch/arc/include/asm/mmu_context.h b/arch/arc/include/asm/mmu_context.h index dda471f5f05b..9963bb1a5733 100644 --- a/arch/arc/include/asm/mmu_context.h +++ b/arch/arc/include/asm/mmu_context.h @@ -165,7 +165,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, * for retiring-mm. However destroy_context( ) still needs to do that because * between mm_release( ) = >deactive_mm( ) and * mmput => .. => __mmdrop( ) => destroy_context( ) - * there is a good chance that task gets sched-out/in, making it's ASID valid + * there is a good chance that task gets sched-out/in, making its ASID valid * again (this teased me for a whole day). */ diff --git a/arch/arc/include/asm/pgtable-bits-arcv2.h b/arch/arc/include/asm/pgtable-bits-arcv2.h index f3eea3f30b2e..8ebec1b21d24 100644 --- a/arch/arc/include/asm/pgtable-bits-arcv2.h +++ b/arch/arc/include/asm/pgtable-bits-arcv2.h @@ -66,7 +66,7 @@ * Other rules which cause the divergence from 1:1 mapping * * 1. Although ARC700 can do exclusive execute/write protection (meaning R - * can be tracked independet of X/W unlike some other CPUs), still to + * can be tracked independently of X/W unlike some other CPUs), still to * keep things consistent with other archs: * -Write implies Read: W => R * -Execute implies Read: X => R diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 00b9318e551e..cf79df0b2570 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -169,7 +169,7 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } -extern int syscall_trace_entry(struct pt_regs *); +extern int syscall_trace_enter(struct pt_regs *); extern void syscall_trace_exit(struct pt_regs *); #endif /* !__ASSEMBLY__ */ diff --git a/arch/arc/include/asm/shmparam.h b/arch/arc/include/asm/shmparam.h index 8b0251464ffd..719112af0f41 100644 --- a/arch/arc/include/asm/shmparam.h +++ b/arch/arc/include/asm/shmparam.h @@ -6,7 +6,7 @@ #ifndef __ARC_ASM_SHMPARAM_H #define __ARC_ASM_SHMPARAM_H -/* Handle upto 2 cache bins */ +/* Handle up to 2 cache bins */ #define SHMLBA (2 * PAGE_SIZE) /* Enforce SHMLBA in shmat */ diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index e0913f52c2cd..990f834909f0 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h @@ -77,7 +77,7 @@ static inline const char *arc_platform_smp_cpuinfo(void) /* * ARC700 doesn't support atomic Read-Modify-Write ops. - * Originally Interrupts had to be disabled around code to gaurantee atomicity. + * Originally Interrupts had to be disabled around code to guarantee atomicity. * The LLOCK/SCOND insns allow writing interrupt-hassle-free based atomic ops * based on retry-if-irq-in-atomic (with hardware assist). * However despite these, we provide the IRQ disabling variant @@ -86,7 +86,7 @@ static inline const char *arc_platform_smp_cpuinfo(void) * support needed. * * (2) In a SMP setup, the LLOCK/SCOND atomicity across CPUs needs to be - * gaurantted by the platform (not something which core handles). + * guaranteed by the platform (not something which core handles). * Assuming a platform won't, SMP Linux needs to use spinlocks + local IRQ * disabling for atomicity. * diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h index 4c530cf131f3..12daaf3a61ea 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -38,7 +38,7 @@ struct thread_info { unsigned long flags; /* low level flags */ unsigned long ksp; /* kernel mode stack top in __switch_to */ - int preempt_count; /* 0 => preemptable, <0 => BUG */ + int preempt_count; /* 0 => preemptible, <0 => BUG */ int cpu; /* current CPU */ unsigned long thr_ptr; /* TLS ptr */ struct task_struct *task; /* main task structure */ diff --git a/arch/arc/include/uapi/asm/swab.h b/arch/arc/include/uapi/asm/swab.h index 02109cd48ee1..8d1f1ef44ba7 100644 --- a/arch/arc/include/uapi/asm/swab.h +++ b/arch/arc/include/uapi/asm/swab.h @@ -62,7 +62,7 @@ * 8051fdc4: st r2,[r1,20] ; Mem op : save result back to mem * * Joern suggested a better "C" algorithm which is great since - * (1) It is portable to any architecure + * (1) It is portable to any architecture * (2) At the same time it takes advantage of ARC ISA (rotate intrns) */ diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index 2e49c81c8086..e238b5fd3c8c 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -5,7 +5,7 @@ * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) */ -#include /* ARC_{EXTRY,EXIT} */ +#include /* ARC_{ENTRY,EXIT} */ #include /* SAVE_ALL_{INT1,INT2,TRAP...} */ #include #include @@ -31,7 +31,7 @@ VECTOR res_service ; Reset Vector VECTOR mem_service ; Mem exception VECTOR instr_service ; Instrn Error VECTOR EV_MachineCheck ; Fatal Machine check -VECTOR EV_TLBMissI ; Intruction TLB miss +VECTOR EV_TLBMissI ; Instruction TLB miss VECTOR EV_TLBMissD ; Data TLB miss VECTOR EV_TLBProtV ; Protection Violation VECTOR EV_PrivilegeV ; Privilege Violation @@ -76,11 +76,11 @@ ENTRY(handle_interrupt) # query in hard ISR path would return false (since .IE is set) which would # trips genirq interrupt handling asserts. # - # So do a "soft" disable of interrutps here. + # So do a "soft" disable of interrupts here. # # Note this disable is only for consistent book-keeping as further interrupts # will be disabled anyways even w/o this. Hardware tracks active interrupts - # seperately in AUX_IRQ_ACT.active and will not take new interrupts + # separately in AUX_IRQ_ACT.active and will not take new interrupts # unless this one returns (or higher prio becomes pending in 2-prio scheme) IRQ_DISABLE diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 089f6680518f..3c7e74aba679 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -95,7 +95,7 @@ ENTRY(EV_MachineCheck) lr r0, [efa] mov r1, sp - ; MC excpetions disable MMU + ; MC exceptions disable MMU ARC_MMU_REENABLE r3 lsr r3, r10, 8 @@ -209,7 +209,7 @@ trap_with_param: ; --------------------------------------------- ; syscall TRAP -; ABI: (r0-r7) upto 8 args, (r8) syscall number +; ABI: (r0-r7) up to 8 args, (r8) syscall number ; --------------------------------------------- ENTRY(EV_Trap) diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S index 9152782444b5..8d541f53fae3 100644 --- a/arch/arc/kernel/head.S +++ b/arch/arc/kernel/head.S @@ -165,7 +165,7 @@ ENTRY(first_lines_of_secondary) ; setup stack (fp, sp) mov fp, 0 - ; set it's stack base to tsk->thread_info bottom + ; set its stack base to tsk->thread_info bottom GET_TSK_STACK_BASE r0, sp j start_kernel_secondary diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 678898757e47..f324f0e3341a 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -56,7 +56,7 @@ void arc_init_IRQ(void) WRITE_AUX(AUX_IRQ_CTRL, ictrl); /* - * ARCv2 core intc provides multiple interrupt priorities (upto 16). + * ARCv2 core intc provides multiple interrupt priorities (up to 16). * Typical builds though have only two levels (0-high, 1-low) * Linux by default uses lower prio 1 for most irqs, reserving 0 for * NMI style interrupts in future (say perf) diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c index e71d64119d71..f8e2960832d9 100644 --- a/arch/arc/kernel/kprobes.c +++ b/arch/arc/kernel/kprobes.c @@ -190,7 +190,8 @@ static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs) } } -int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs) +static int +__kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs) { struct kprobe *p; struct kprobe_ctlblk *kcb; @@ -241,8 +242,8 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs) return 0; } -static int __kprobes arc_post_kprobe_handler(unsigned long addr, - struct pt_regs *regs) +static int +__kprobes arc_post_kprobe_handler(unsigned long addr, struct pt_regs *regs) { struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c index adff957962da..6e5a651cd75c 100644 --- a/arch/arc/kernel/perf_event.c +++ b/arch/arc/kernel/perf_event.c @@ -38,7 +38,7 @@ * (based on a specific RTL build) * Below is the static map between perf generic/arc specific event_id and * h/w condition names. - * At the time of probe, we loop thru each index and find it's name to + * At the time of probe, we loop thru each index and find its name to * complete the mapping of perf event_id to h/w index as latter is needed * to program the counter really */ diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index d08a5092c2b4..7b6a9beba9db 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -390,7 +390,7 @@ static void arc_chk_core_config(struct cpuinfo_arc *info) #ifdef CONFIG_ARC_HAS_DCCM /* * DCCM can be arbit placed in hardware. - * Make sure it's placement/sz matches what Linux is built with + * Make sure its placement/sz matches what Linux is built with */ if ((unsigned int)__arc_dccm_base != info->dccm.base) panic("Linux built with incorrect DCCM Base address\n"); diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 8f6f4a542964..fefa705a8638 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -8,15 +8,16 @@ * * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK) * -do_signal() supports TIF_RESTORE_SIGMASK - * -do_signal() no loner needs oldset, required by OLD sys_sigsuspend - * -sys_rt_sigsuspend() now comes from generic code, so discard arch implemen + * -do_signal() no longer needs oldset, required by OLD sys_sigsuspend + * -sys_rt_sigsuspend() now comes from generic code, so discard arch + * implementation * -sys_sigsuspend() no longer needs to fudge ptregs, hence that arg removed * -sys_sigsuspend() no longer loops for do_signal(), sets TIF_xxx and leaves * the job to do_signal() * * vineetg: July 2009 * -Modified Code to support the uClibc provided userland sigreturn stub - * to avoid kernel synthesing it on user stack at runtime, costing TLB + * to avoid kernel synthesizing it on user stack at runtime, costing TLB * probes and Cache line flushes. * * vineetg: July 2009 diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 9b9570b79362..a19751e824fb 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -89,7 +89,7 @@ int do_misaligned_access(unsigned long address, struct pt_regs *regs, /* * Entry point for miscll errors such as Nested Exceptions - * -Duplicate TLB entry is handled seperately though + * -Duplicate TLB entry is handled separately though */ void do_machine_check_fault(unsigned long address, struct pt_regs *regs) { diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 549c3f407918..61a1b2b96e1d 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -41,8 +41,8 @@ SECTIONS #endif /* - * The reason for having a seperate subsection .init.ramfs is to - * prevent objump from including it in kernel dumps + * The reason for having a separate subsection .init.ramfs is to + * prevent objdump from including it in kernel dumps * * Reason for having .init.ramfs above .init is to make sure that the * binary blob is tucked away to one side, reducing the displacement diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index ad702b49aeb3..cae4a7aae0ed 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -212,7 +212,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long flags; /* If range @start to @end is more than 32 TLB entries deep, - * its better to move to a new ASID rather than searching for + * it's better to move to a new ASID rather than searching for * individual entries and then shooting them down * * The calc above is rough, doesn't account for unaligned parts, @@ -408,7 +408,7 @@ static void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *p * -More importantly it makes this handler inconsistent with fast-path * TLB Refill handler which always deals with "current" * - * Lets see the use cases when current->mm != vma->mm and we land here + * Let's see the use cases when current->mm != vma->mm and we land here * 1. execve->copy_strings()->__get_user_pages->handle_mm_fault * Here VM wants to pre-install a TLB entry for user stack while * current->mm still points to pre-execve mm (hence the condition). diff --git a/arch/arc/mm/tlbex.S b/arch/arc/mm/tlbex.S index e054780a8fe0..dc65e87a531f 100644 --- a/arch/arc/mm/tlbex.S +++ b/arch/arc/mm/tlbex.S @@ -5,19 +5,19 @@ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) * * Vineetg: April 2011 : - * -MMU v1: moved out legacy code into a seperate file + * -MMU v1: moved out legacy code into a separate file * -MMU v3: PD{0,1} bits layout changed: They don't overlap anymore, * helps avoid a shift when preparing PD0 from PTE * * Vineetg: July 2009 - * -For MMU V2, we need not do heuristics at the time of commiting a D-TLB - * entry, so that it doesn't knock out it's I-TLB entry + * -For MMU V2, we need not do heuristics at the time of committing a D-TLB + * entry, so that it doesn't knock out its I-TLB entry * -Some more fine tuning: * bmsk instead of add, asl.cc instead of branch, delay slot utilise etc * * Vineetg: July 2009 * -Practically rewrote the I/D TLB Miss handlers - * Now 40 and 135 instructions a peice as compared to 131 and 449 resp. + * Now 40 and 135 instructions apiece as compared to 131 and 449 resp. * Hence Leaner by 1.5 K * Used Conditional arithmetic to replace excessive branching * Also used short instructions wherever possible diff --git a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts index 4f609e9e510e..009d2c832421 100644 --- a/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts +++ b/arch/arm/boot/dts/microchip/at91-sama7g54_curiosity.dts @@ -242,7 +242,7 @@ vddcore: VDD_CORE { regulator-state-standby { regulator-on-in-suspend; - regulator-suspend-voltage = <1150000>; + regulator-suspend-microvolt = <1150000>; regulator-mode = <4>; }; @@ -263,7 +263,7 @@ vddcpu: VDD_OTHER { regulator-state-standby { regulator-on-in-suspend; - regulator-suspend-voltage = <1050000>; + regulator-suspend-microvolt = <1050000>; regulator-mode = <4>; }; @@ -280,7 +280,7 @@ vldo1: LDO1 { regulator-always-on; regulator-state-standby { - regulator-suspend-voltage = <1800000>; + regulator-suspend-microvolt = <1800000>; regulator-on-in-suspend; }; @@ -296,7 +296,7 @@ vldo2: LDO2 { regulator-always-on; regulator-state-standby { - regulator-suspend-voltage = <3300000>; + regulator-suspend-microvolt = <3300000>; regulator-on-in-suspend; }; diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts index 217e9b96c61e..20b2497657ae 100644 --- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts +++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts @@ -293,7 +293,7 @@ vddcore: VDD_CORE { regulator-state-standby { regulator-on-in-suspend; - regulator-suspend-voltage = <1150000>; + regulator-suspend-microvolt = <1150000>; regulator-mode = <4>; }; @@ -314,7 +314,7 @@ vddcpu: VDD_OTHER { regulator-state-standby { regulator-on-in-suspend; - regulator-suspend-voltage = <1050000>; + regulator-suspend-microvolt = <1050000>; regulator-mode = <4>; }; @@ -331,7 +331,7 @@ vldo1: LDO1 { regulator-always-on; regulator-state-standby { - regulator-suspend-voltage = <1800000>; + regulator-suspend-microvolt = <1800000>; regulator-on-in-suspend; }; @@ -346,7 +346,7 @@ vldo2: LDO2 { regulator-max-microvolt = <3700000>; regulator-state-standby { - regulator-suspend-voltage = <1800000>; + regulator-suspend-microvolt = <1800000>; regulator-on-in-suspend; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi index 3fdece5bd31f..5248a058230c 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi @@ -805,6 +805,7 @@ &usbotg1 { &pinctrl_usb_pwr>; dr_mode = "host"; power-active-high; + over-current-active-low; disable-over-current; status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi index 1235a71c6abe..52869e68f833 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi @@ -666,7 +666,7 @@ &usdhc1 { bus-width = <4>; no-1-8-v; no-sdio; - no-emmc; + no-mmc; status = "okay"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts index ba7231b364bb..7bab113ca6da 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts @@ -210,6 +210,7 @@ ov2680_to_mipi: endpoint { remote-endpoint = <&mipi_from_sensor>; clock-lanes = <0>; data-lanes = <1>; + link-frequencies = /bits/ 64 <330000000>; }; }; }; diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 31755a378c73..ff2a4a4d8220 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -79,10 +79,8 @@ static struct musb_hdrc_platform_data tusb_data = { static struct gpiod_lookup_table tusb_gpio_table = { .dev_id = "musb-tusb", .table = { - GPIO_LOOKUP("gpio-0-15", 0, "enable", - GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("gpio-48-63", 10, "int", - GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-31", 0, "enable", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-32-63", 26, "int", GPIO_ACTIVE_HIGH), { } }, }; @@ -140,12 +138,11 @@ static int slot1_cover_open; static int slot2_cover_open; static struct device *mmc_device; -static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { +static struct gpiod_lookup_table nokia800_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { /* Slot switch, GPIO 96 */ - GPIO_LOOKUP("gpio-80-111", 16, - "switch", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH), { } }, }; @@ -153,12 +150,12 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { static struct gpiod_lookup_table nokia810_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { + /* Slot switch, GPIO 96 */ + GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH), /* Slot index 1, VSD power, GPIO 23 */ - GPIO_LOOKUP_IDX("gpio-16-31", 7, - "vsd", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH), /* Slot index 1, VIO power, GPIO 9 */ - GPIO_LOOKUP_IDX("gpio-0-15", 9, - "vio", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0-31", 9, "vio", 1, GPIO_ACTIVE_HIGH), { } }, }; @@ -415,8 +412,6 @@ static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; static void __init n8x0_mmc_init(void) { - gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table); - if (board_is_n810()) { mmc1_data.slots[0].name = "external"; @@ -429,6 +424,8 @@ static void __init n8x0_mmc_init(void) mmc1_data.slots[1].name = "internal"; mmc1_data.slots[1].ban_openended = 1; gpiod_add_lookup_table(&nokia810_mmc_gpio_table); + } else { + gpiod_add_lookup_table(&nokia800_mmc_gpio_table); } mmc1_data.nr_slots = 2; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi index 3c42240e78e2..4aaf5a0c1ed8 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi @@ -41,7 +41,7 @@ usbotg1: usb@5b0d0000 { interrupts = ; fsl,usbphy = <&usbphy1>; fsl,usbmisc = <&usbmisc1 0>; - clocks = <&usb2_lpcg 0>; + clocks = <&usb2_lpcg IMX_LPCG_CLK_6>; ahb-burst-config = <0x0>; tx-burst-size-dword = <0x10>; rx-burst-size-dword = <0x10>; @@ -58,7 +58,7 @@ usbmisc1: usbmisc@5b0d0200 { usbphy1: usbphy@5b100000 { compatible = "fsl,imx7ulp-usbphy"; reg = <0x5b100000 0x1000>; - clocks = <&usb2_lpcg 1>; + clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; power-domains = <&pd IMX_SC_R_USB_0_PHY>; status = "disabled"; }; @@ -67,8 +67,8 @@ usdhc1: mmc@5b010000 { interrupts = ; reg = <0x5b010000 0x10000>; clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>, - <&sdhc0_lpcg IMX_LPCG_CLK_0>, - <&sdhc0_lpcg IMX_LPCG_CLK_5>; + <&sdhc0_lpcg IMX_LPCG_CLK_5>, + <&sdhc0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_0>; status = "disabled"; @@ -78,8 +78,8 @@ usdhc2: mmc@5b020000 { interrupts = ; reg = <0x5b020000 0x10000>; clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>, - <&sdhc1_lpcg IMX_LPCG_CLK_0>, - <&sdhc1_lpcg IMX_LPCG_CLK_5>; + <&sdhc1_lpcg IMX_LPCG_CLK_5>, + <&sdhc1_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_1>; fsl,tuning-start-tap = <20>; @@ -91,8 +91,8 @@ usdhc3: mmc@5b030000 { interrupts = ; reg = <0x5b030000 0x10000>; clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>, - <&sdhc2_lpcg IMX_LPCG_CLK_0>, - <&sdhc2_lpcg IMX_LPCG_CLK_5>; + <&sdhc2_lpcg IMX_LPCG_CLK_5>, + <&sdhc2_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_2>; status = "disabled"; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index cab3468b1875..f7a91d43a0ff 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -28,8 +28,8 @@ lpspi0: spi@5a000000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi0_lpcg 0>, - <&spi0_lpcg 1>; + clocks = <&spi0_lpcg IMX_LPCG_CLK_0>, + <&spi0_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -44,8 +44,8 @@ lpspi1: spi@5a010000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi1_lpcg 0>, - <&spi1_lpcg 1>; + clocks = <&spi1_lpcg IMX_LPCG_CLK_0>, + <&spi1_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -60,8 +60,8 @@ lpspi2: spi@5a020000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi2_lpcg 0>, - <&spi2_lpcg 1>; + clocks = <&spi2_lpcg IMX_LPCG_CLK_0>, + <&spi2_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -76,8 +76,8 @@ lpspi3: spi@5a030000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi3_lpcg 0>, - <&spi3_lpcg 1>; + clocks = <&spi3_lpcg IMX_LPCG_CLK_0>, + <&spi3_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -145,8 +145,8 @@ adma_pwm: pwm@5a190000 { compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; reg = <0x5a190000 0x1000>; interrupts = ; - clocks = <&adma_pwm_lpcg 1>, - <&adma_pwm_lpcg 0>; + clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>, + <&adma_pwm_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; @@ -355,8 +355,8 @@ adc0: adc@5a880000 { reg = <0x5a880000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adc0_lpcg 0>, - <&adc0_lpcg 1>; + clocks = <&adc0_lpcg IMX_LPCG_CLK_0>, + <&adc0_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; @@ -370,8 +370,8 @@ adc1: adc@5a890000 { reg = <0x5a890000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adc1_lpcg 0>, - <&adc1_lpcg 1>; + clocks = <&adc1_lpcg IMX_LPCG_CLK_0>, + <&adc1_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; @@ -384,8 +384,8 @@ flexcan1: can@5a8d0000 { reg = <0x5a8d0000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; @@ -405,8 +405,8 @@ flexcan2: can@5a8e0000 { * CAN1 shares CAN0's clock and to enable CAN0's clock it * has to be powered on. */ - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; @@ -426,8 +426,8 @@ flexcan3: can@5a8f0000 { * CAN2 shares CAN0's clock and to enable CAN0's clock it * has to be powered on. */ - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi index 7e510b21bbac..764c1a08e3b1 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi @@ -25,8 +25,8 @@ lsio_pwm0: pwm@5d000000 { compatible = "fsl,imx27-pwm"; reg = <0x5d000000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm0_lpcg 4>, - <&pwm0_lpcg 1>; + clocks = <&pwm0_lpcg IMX_LPCG_CLK_6>, + <&pwm0_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -38,8 +38,8 @@ lsio_pwm1: pwm@5d010000 { compatible = "fsl,imx27-pwm"; reg = <0x5d010000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm1_lpcg 4>, - <&pwm1_lpcg 1>; + clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>, + <&pwm1_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -51,8 +51,8 @@ lsio_pwm2: pwm@5d020000 { compatible = "fsl,imx27-pwm"; reg = <0x5d020000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm2_lpcg 4>, - <&pwm2_lpcg 1>; + clocks = <&pwm2_lpcg IMX_LPCG_CLK_6>, + <&pwm2_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -64,8 +64,8 @@ lsio_pwm3: pwm@5d030000 { compatible = "fsl,imx27-pwm"; reg = <0x5d030000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm3_lpcg 4>, - <&pwm3_lpcg 1>; + clocks = <&pwm3_lpcg IMX_LPCG_CLK_6>, + <&pwm3_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi index 41c79d2ebdd6..f24b14744799 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi @@ -14,6 +14,7 @@ connector { pinctrl-0 = <&pinctrl_usbcon1>; type = "micro"; label = "otg"; + vbus-supply = <®_usb1_vbus>; id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; port { @@ -183,7 +184,6 @@ &usb3_0 { }; &usb3_phy0 { - vbus-supply = <®_usb1_vbus>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi index d5c400b355af..f5491a608b2f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi @@ -14,6 +14,7 @@ connector { pinctrl-0 = <&pinctrl_usbcon1>; type = "micro"; label = "otg"; + vbus-supply = <®_usb1_vbus>; id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; port { @@ -202,7 +203,6 @@ &usb3_0 { }; &usb3_phy0 { - vbus-supply = <®_usb1_vbus>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index bfc5c81a5bd4..8141926e4ef1 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -1672,7 +1672,7 @@ mipi_csi_1: csi@32e50000 { <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT>, <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; clock-names = "pclk", "wrap", "phy", "axi"; - assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM1_PIX>, + assigned-clocks = <&clk IMX8MP_CLK_MEDIA_CAM2_PIX>, <&clk IMX8MP_CLK_MEDIA_MIPI_PHY1_REF>; assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, <&clk IMX8MP_CLK_24M>; diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi index 11626fae5f97..aa9f28c4431d 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi @@ -153,15 +153,15 @@ &flexcan1 { }; &flexcan2 { - clocks = <&can1_lpcg 1>, - <&can1_lpcg 0>; + clocks = <&can1_lpcg IMX_LPCG_CLK_4>, + <&can1_lpcg IMX_LPCG_CLK_0>; assigned-clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>; fsl,clk-source = /bits/ 8 <1>; }; &flexcan3 { - clocks = <&can2_lpcg 1>, - <&can2_lpcg 0>; + clocks = <&can2_lpcg IMX_LPCG_CLK_4>, + <&can2_lpcg IMX_LPCG_CLK_0>; assigned-clocks = <&clk IMX_SC_R_CAN_2 IMX_SC_PM_CLK_PER>; fsl,clk-source = /bits/ 8 <1>; }; diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts index 0c38f7b51763..234e3b23d7a8 100644 --- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts @@ -129,7 +129,7 @@ ethernet_phy0: ethernet-phy@5 { }; &pio { - eth_default: eth_default { + eth_default: eth-default-pins { tx_pins { pinmux = , , @@ -156,7 +156,7 @@ mdio_pins { }; }; - eth_sleep: eth_sleep { + eth_sleep: eth-sleep-pins { tx_pins { pinmux = , , @@ -182,14 +182,14 @@ mdio_pins { }; }; - usb0_id_pins_float: usb0_iddig { + usb0_id_pins_float: usb0-iddig-pins { pins_iddig { pinmux = ; bias-pull-up; }; }; - usb1_id_pins_float: usb1_iddig { + usb1_id_pins_float: usb1-iddig-pins { pins_iddig { pinmux = ; bias-pull-up; diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi index 6d218caa198c..082672efba0a 100644 --- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi @@ -249,10 +249,11 @@ topckgen: syscon@10000000 { #clock-cells = <1>; }; - infracfg: syscon@10001000 { + infracfg: clock-controller@10001000 { compatible = "mediatek,mt2712-infracfg", "syscon"; reg = <0 0x10001000 0 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; }; pericfg: syscon@10003000 { diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi index 3ee9266fa8e9..917fa39a74f8 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -252,7 +252,7 @@ scpsys: power-controller@10006000 { clock-names = "hif_sel"; }; - cir: cir@10009000 { + cir: ir-receiver@10009000 { compatible = "mediatek,mt7622-cir"; reg = <0 0x10009000 0 0x1000>; interrupts = ; @@ -283,16 +283,14 @@ thermal_calibration: calib@198 { }; }; - apmixedsys: apmixedsys@10209000 { - compatible = "mediatek,mt7622-apmixedsys", - "syscon"; + apmixedsys: clock-controller@10209000 { + compatible = "mediatek,mt7622-apmixedsys"; reg = <0 0x10209000 0 0x1000>; #clock-cells = <1>; }; - topckgen: topckgen@10210000 { - compatible = "mediatek,mt7622-topckgen", - "syscon"; + topckgen: clock-controller@10210000 { + compatible = "mediatek,mt7622-topckgen"; reg = <0 0x10210000 0 0x1000>; #clock-cells = <1>; }; @@ -515,7 +513,6 @@ thermal: thermal@1100b000 { <&pericfg CLK_PERI_AUXADC_PD>; clock-names = "therm", "auxadc"; resets = <&pericfg MT7622_PERI_THERM_SW_RST>; - reset-names = "therm"; mediatek,auxadc = <&auxadc>; mediatek,apmixedsys = <&apmixedsys>; nvmem-cells = <&thermal_calibration>; @@ -734,9 +731,8 @@ wmac: wmac@18000000 { power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>; }; - ssusbsys: ssusbsys@1a000000 { - compatible = "mediatek,mt7622-ssusbsys", - "syscon"; + ssusbsys: clock-controller@1a000000 { + compatible = "mediatek,mt7622-ssusbsys"; reg = <0 0x1a000000 0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; @@ -793,9 +789,8 @@ u2port1: usb-phy@1a0c5000 { }; }; - pciesys: pciesys@1a100800 { - compatible = "mediatek,mt7622-pciesys", - "syscon"; + pciesys: clock-controller@1a100800 { + compatible = "mediatek,mt7622-pciesys"; reg = <0 0x1a100800 0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; @@ -921,12 +916,13 @@ sata_port: sata-phy@1a243000 { }; }; - hifsys: syscon@1af00000 { - compatible = "mediatek,mt7622-hifsys", "syscon"; + hifsys: clock-controller@1af00000 { + compatible = "mediatek,mt7622-hifsys"; reg = <0 0x1af00000 0 0x70>; + #clock-cells = <1>; }; - ethsys: syscon@1b000000 { + ethsys: clock-controller@1b000000 { compatible = "mediatek,mt7622-ethsys", "syscon"; reg = <0 0x1b000000 0 0x1000>; @@ -966,9 +962,7 @@ wed1: wed@1020b000 { }; eth: ethernet@1b100000 { - compatible = "mediatek,mt7622-eth", - "mediatek,mt2701-eth", - "syscon"; + compatible = "mediatek,mt7622-eth"; reg = <0 0x1b100000 0 0x20000>; interrupts = , , diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts index e04b1c0c0ebb..ed79ad1ae871 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts +++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts @@ -146,19 +146,19 @@ sfp2: sfp-2 { &cpu_thermal { cooling-maps { - cpu-active-high { + map-cpu-active-high { /* active: set fan to cooling level 2 */ cooling-device = <&fan 2 2>; trip = <&cpu_trip_active_high>; }; - cpu-active-med { + map-cpu-active-med { /* active: set fan to cooling level 1 */ cooling-device = <&fan 1 1>; trip = <&cpu_trip_active_med>; }; - cpu-active-low { + map-cpu-active-low { /* active: set fan to cooling level 0 */ cooling-device = <&fan 0 0>; trip = <&cpu_trip_active_low>; diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi index b3f416b9a7a4..559990dcd1d1 100644 --- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi @@ -332,9 +332,8 @@ thermal: thermal@1100c800 { reg = <0 0x1100c800 0 0x800>; interrupts = ; clocks = <&infracfg CLK_INFRA_THERM_CK>, - <&infracfg CLK_INFRA_ADC_26M_CK>, - <&infracfg CLK_INFRA_ADC_FRC_CK>; - clock-names = "therm", "auxadc", "adc_32k"; + <&infracfg CLK_INFRA_ADC_26M_CK>; + clock-names = "therm", "auxadc"; nvmem-cells = <&thermal_calibration>; nvmem-cell-names = "calibration-data"; #thermal-sensor-cells = <1>; @@ -492,8 +491,6 @@ ethsys: syscon@15000000 { compatible = "mediatek,mt7986-ethsys", "syscon"; reg = <0 0x15000000 0 0x1000>; - #address-cells = <1>; - #size-cells = <1>; #clock-cells = <1>; #reset-cells = <1>; }; @@ -556,7 +553,6 @@ eth: ethernet@15100000 { <&topckgen CLK_TOP_SGM_325M_SEL>; assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, <&apmixedsys CLK_APMIXED_SGMPLL>; - #reset-cells = <1>; #address-cells = <1>; #size-cells = <0>; mediatek,ethsys = <ðsys>; diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi index 6bd7424ef66c..100191c6453b 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi @@ -433,7 +433,6 @@ &mt6358regulator { }; &mt6358_vgpu_reg { - regulator-min-microvolt = <625000>; regulator-max-microvolt = <900000>; regulator-coupled-with = <&mt6358_vsram_gpu_reg>; diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi index 93dfbf130231..774ae5d9143f 100644 --- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi @@ -1637,6 +1637,7 @@ mfgcfg: syscon@13000000 { compatible = "mediatek,mt8183-mfgcfg", "syscon"; reg = <0 0x13000000 0 0x1000>; #clock-cells = <1>; + power-domains = <&spm MT8183_POWER_DOMAIN_MFG_ASYNC>; }; gpu: gpu@13040000 { diff --git a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi index 3dea28f1d806..1807e9d6cb0e 100644 --- a/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8186-corsola.dtsi @@ -1296,7 +1296,7 @@ mt6366_vgpu_reg: vgpu { * regulator coupling requirements. */ regulator-name = "ppvar_dvdd_vgpu"; - regulator-min-microvolt = <600000>; + regulator-min-microvolt = <500000>; regulator-max-microvolt = <950000>; regulator-ramp-delay = <6250>; regulator-enable-ramp-delay = <200>; diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi index 9b738f6a5d21..7a704246678f 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi @@ -1421,7 +1421,7 @@ regulators { mt6315_6_vbuck1: vbuck1 { regulator-compatible = "vbuck1"; regulator-name = "Vbcpu"; - regulator-min-microvolt = <300000>; + regulator-min-microvolt = <400000>; regulator-max-microvolt = <1193750>; regulator-enable-ramp-delay = <256>; regulator-allowed-modes = <0 1 2>; @@ -1431,7 +1431,7 @@ mt6315_6_vbuck1: vbuck1 { mt6315_6_vbuck3: vbuck3 { regulator-compatible = "vbuck3"; regulator-name = "Vlcpu"; - regulator-min-microvolt = <300000>; + regulator-min-microvolt = <400000>; regulator-max-microvolt = <1193750>; regulator-enable-ramp-delay = <256>; regulator-allowed-modes = <0 1 2>; @@ -1448,7 +1448,7 @@ regulators { mt6315_7_vbuck1: vbuck1 { regulator-compatible = "vbuck1"; regulator-name = "Vgpu"; - regulator-min-microvolt = <606250>; + regulator-min-microvolt = <400000>; regulator-max-microvolt = <800000>; regulator-enable-ramp-delay = <256>; regulator-allowed-modes = <0 1 2>; diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi index 05e401670bce..84cbdf6e9eb0 100644 --- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi @@ -1464,6 +1464,7 @@ mutex: mutex@14001000 { reg = <0 0x14001000 0 0x1000>; interrupts = ; clocks = <&mmsys CLK_MM_DISP_MUTEX0>; + mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x1000 0x1000>; mediatek,gce-events = , ; power-domains = <&spm MT8192_POWER_DOMAIN_DISP>; diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi index f94c07f8b933..4a11918da370 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi @@ -264,6 +264,38 @@ &auxadc { status = "okay"; }; +&cpu0 { + cpu-supply = <&mt6359_vcore_buck_reg>; +}; + +&cpu1 { + cpu-supply = <&mt6359_vcore_buck_reg>; +}; + +&cpu2 { + cpu-supply = <&mt6359_vcore_buck_reg>; +}; + +&cpu3 { + cpu-supply = <&mt6359_vcore_buck_reg>; +}; + +&cpu4 { + cpu-supply = <&mt6315_6_vbuck1>; +}; + +&cpu5 { + cpu-supply = <&mt6315_6_vbuck1>; +}; + +&cpu6 { + cpu-supply = <&mt6315_6_vbuck1>; +}; + +&cpu7 { + cpu-supply = <&mt6315_6_vbuck1>; +}; + &dp_intf0 { status = "okay"; @@ -1214,7 +1246,7 @@ regulators { mt6315_6_vbuck1: vbuck1 { regulator-compatible = "vbuck1"; regulator-name = "Vbcpu"; - regulator-min-microvolt = <300000>; + regulator-min-microvolt = <400000>; regulator-max-microvolt = <1193750>; regulator-enable-ramp-delay = <256>; regulator-ramp-delay = <6250>; @@ -1232,7 +1264,7 @@ regulators { mt6315_7_vbuck1: vbuck1 { regulator-compatible = "vbuck1"; regulator-name = "Vgpu"; - regulator-min-microvolt = <625000>; + regulator-min-microvolt = <400000>; regulator-max-microvolt = <1193750>; regulator-enable-ramp-delay = <256>; regulator-ramp-delay = <6250>; diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi index ea6dc220e1cc..5d8b68f86ce4 100644 --- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi @@ -2028,6 +2028,7 @@ vppsys0: syscon@14000000 { compatible = "mediatek,mt8195-vppsys0", "syscon"; reg = <0 0x14000000 0 0x1000>; #clock-cells = <1>; + mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0 0x1000>; }; dma-controller@14001000 { @@ -2251,6 +2252,7 @@ vppsys1: syscon@14f00000 { compatible = "mediatek,mt8195-vppsys1", "syscon"; reg = <0 0x14f00000 0 0x1000>; #clock-cells = <1>; + mediatek,gce-client-reg = <&gce1 SUBSYS_14f0XXXX 0 0x1000>; }; mutex@14f01000 { @@ -3080,6 +3082,7 @@ vdosys0: syscon@1c01a000 { reg = <0 0x1c01a000 0 0x1000>; mboxes = <&gce0 0 CMDQ_THR_PRIO_4>; #clock-cells = <1>; + mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xa000 0x1000>; }; @@ -3261,6 +3264,7 @@ mutex: mutex@1c016000 { interrupts = ; power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS0>; clocks = <&vdosys0 CLK_VDO0_DISP_MUTEX0>; + mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x6000 0x1000>; mediatek,gce-events = ; }; @@ -3331,6 +3335,7 @@ mutex1: mutex@1c101000 { power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>; clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>; clock-names = "vdo1_mutex"; + mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>; mediatek,gce-events = ; }; diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index f3a6da8b2890..5260c63db007 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -944,6 +944,8 @@ bluetooth: bluetooth { vddrf-supply = <&pp1300_l2c>; vddch0-supply = <&pp3300_l10c>; max-speed = <3200000>; + + qcom,local-bd-address-broken; }; }; diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi index 7e7f0f0fb41b..41f51d326111 100644 --- a/arch/arm64/boot/dts/qcom/sc7280.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi @@ -3707,7 +3707,7 @@ remoteproc_adsp: remoteproc@3700000 { compatible = "qcom,sc7280-adsp-pas"; reg = <0 0x03700000 0 0x100>; - interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, @@ -3944,7 +3944,7 @@ remoteproc_cdsp: remoteproc@a300000 { compatible = "qcom,sc7280-cdsp-pas"; reg = <0 0x0a300000 0 0x10000>; - interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>, <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>, <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi index 32afc78d5b76..053f7861c3ce 100644 --- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi +++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi @@ -2701,7 +2701,7 @@ usb_sec: usb@a8f8800 { resets = <&gcc GCC_USB30_SEC_BCR>; power-domains = <&gcc USB30_SEC_GDSC>; interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, - <&pdc 7 IRQ_TYPE_LEVEL_HIGH>, + <&pdc 40 IRQ_TYPE_LEVEL_HIGH>, <&pdc 10 IRQ_TYPE_EDGE_BOTH>, <&pdc 11 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "hs_phy_irq", "ss_phy_irq", diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi index a5b194813079..d0f82e12289e 100644 --- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi +++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi @@ -1774,6 +1774,7 @@ pcie4: pcie@1c00000 { reset-names = "pci"; power-domains = <&gcc PCIE_4_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie4_phy>; phy-names = "pciephy"; @@ -1872,6 +1873,7 @@ pcie3b: pcie@1c08000 { reset-names = "pci"; power-domains = <&gcc PCIE_3B_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie3b_phy>; phy-names = "pciephy"; @@ -1970,6 +1972,7 @@ pcie3a: pcie@1c10000 { reset-names = "pci"; power-domains = <&gcc PCIE_3A_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie3a_phy>; phy-names = "pciephy"; @@ -2071,6 +2074,7 @@ pcie2b: pcie@1c18000 { reset-names = "pci"; power-domains = <&gcc PCIE_2B_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie2b_phy>; phy-names = "pciephy"; @@ -2169,6 +2173,7 @@ pcie2a: pcie@1c20000 { reset-names = "pci"; power-domains = <&gcc PCIE_2A_GDSC>; + required-opps = <&rpmhpd_opp_nom>; phys = <&pcie2a_phy>; phy-names = "pciephy"; @@ -2641,7 +2646,7 @@ remoteproc_adsp: remoteproc@3000000 { compatible = "qcom,sc8280xp-adsp-pas"; reg = <0 0x03000000 0 0x100>; - interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, @@ -4977,7 +4982,7 @@ remoteproc_nsp0: remoteproc@1b300000 { compatible = "qcom,sc8280xp-nsp0-pas"; reg = <0 0x1b300000 0 0x100>; - interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp0_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp0_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp0_in 2 IRQ_TYPE_EDGE_RISING>, @@ -5108,7 +5113,7 @@ remoteproc_nsp1: remoteproc@21300000 { compatible = "qcom,sc8280xp-nsp1-pas"; reg = <0 0x21300000 0 0x100>; - interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp1_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp1_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_nsp1_in 2 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi index 24bcec3366ef..0be053555602 100644 --- a/arch/arm64/boot/dts/qcom/sm6350.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi @@ -1252,7 +1252,7 @@ adsp: remoteproc@3000000 { compatible = "qcom,sm6350-adsp-pas"; reg = <0 0x03000000 0 0x100>; - interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, @@ -1511,7 +1511,7 @@ cdsp: remoteproc@8300000 { compatible = "qcom,sm6350-cdsp-pas"; reg = <0 0x08300000 0 0x10000>; - interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi index 4386f8a9c636..f40509d91bbd 100644 --- a/arch/arm64/boot/dts/qcom/sm6375.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi @@ -1561,7 +1561,7 @@ remoteproc_adsp: remoteproc@a400000 { compatible = "qcom,sm6375-adsp-pas"; reg = <0 0x0a400000 0 0x100>; - interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi index 39bd8f0eba1e..7f2333c9d17d 100644 --- a/arch/arm64/boot/dts/qcom/sm8250.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi @@ -3062,7 +3062,7 @@ slpi: remoteproc@5c00000 { compatible = "qcom,sm8250-slpi-pas"; reg = <0 0x05c00000 0 0x4000>; - interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&pdc 9 IRQ_TYPE_EDGE_RISING>, <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>, @@ -3766,7 +3766,7 @@ cdsp: remoteproc@8300000 { compatible = "qcom,sm8250-cdsp-pas"; reg = <0 0x08300000 0 0x10000>; - interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>, @@ -5928,7 +5928,7 @@ adsp: remoteproc@17300000 { compatible = "qcom,sm8250-adsp-pas"; reg = <0 0x17300000 0 0x100>; - interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>, + interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>, <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>, diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi index b86be34a912b..024d2653cc30 100644 --- a/arch/arm64/boot/dts/qcom/sm8450.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi @@ -1777,12 +1777,8 @@ pcie0: pcie@1c00000 { ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>, <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>; - /* - * MSIs for BDF (1:0.0) only works with Device ID 0x5980. - * Hence, the IDs are swapped. - */ - msi-map = <0x0 &gic_its 0x5981 0x1>, - <0x100 &gic_its 0x5980 0x1>; + msi-map = <0x0 &gic_its 0x5980 0x1>, + <0x100 &gic_its 0x5981 0x1>; msi-map-mask = <0xff00>; interrupts = , , @@ -1900,12 +1896,8 @@ pcie1: pcie@1c08000 { ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>, <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>; - /* - * MSIs for BDF (1:0.0) only works with Device ID 0x5a00. - * Hence, the IDs are swapped. - */ - msi-map = <0x0 &gic_its 0x5a01 0x1>, - <0x100 &gic_its 0x5a00 0x1>; + msi-map = <0x0 &gic_its 0x5a00 0x1>, + <0x100 &gic_its 0x5a01 0x1>; msi-map-mask = <0xff00>; interrupts = , , diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi index 3904348075f6..3348bc06db48 100644 --- a/arch/arm64/boot/dts/qcom/sm8550.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi @@ -1755,9 +1755,8 @@ pcie0: pcie@1c00000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>; interconnect-names = "pcie-mem", "cpu-pcie"; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1401 0x1>, - <0x100 &gic_its 0x1400 0x1>; + msi-map = <0x0 &gic_its 0x1400 0x1>, + <0x100 &gic_its 0x1401 0x1>; iommu-map = <0x0 &apps_smmu 0x1400 0x1>, <0x100 &apps_smmu 0x1401 0x1>; @@ -1867,9 +1866,8 @@ pcie1: pcie@1c08000 { <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_1 0>; interconnect-names = "pcie-mem", "cpu-pcie"; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1481 0x1>, - <0x100 &gic_its 0x1480 0x1>; + msi-map = <0x0 &gic_its 0x1480 0x1>, + <0x100 &gic_its 0x1481 0x1>; iommu-map = <0x0 &apps_smmu 0x1480 0x1>, <0x100 &apps_smmu 0x1481 0x1>; diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi index ba72d8f38420..eb117866e59f 100644 --- a/arch/arm64/boot/dts/qcom/sm8650.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi @@ -2274,9 +2274,8 @@ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, interrupt-map-mask = <0 0 0 0x7>; #interrupt-cells = <1>; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1401 0x1>, - <0x100 &gic_its 0x1400 0x1>; + msi-map = <0x0 &gic_its 0x1400 0x1>, + <0x100 &gic_its 0x1401 0x1>; msi-map-mask = <0xff00>; linux,pci-domain = <0>; @@ -2402,9 +2401,8 @@ &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, interrupt-map-mask = <0 0 0 0x7>; #interrupt-cells = <1>; - /* Entries are reversed due to the unusual ITS DeviceID encoding */ - msi-map = <0x0 &gic_its 0x1481 0x1>, - <0x100 &gic_its 0x1480 0x1>; + msi-map = <0x0 &gic_its 0x1480 0x1>, + <0x100 &gic_its 0x1481 0x1>; msi-map-mask = <0xff00>; linux,pci-domain = <1>; diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi index 8e517f76189e..6b40082bac68 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi @@ -284,7 +284,7 @@ CLUSTER_C4: cpu-sleep-0 { domain-idle-states { CLUSTER_CL4: cluster-sleep-0 { - compatible = "arm,idle-state"; + compatible = "domain-idle-state"; idle-state-name = "l2-ret"; arm,psci-suspend-param = <0x01000044>; entry-latency-us = <350>; @@ -293,7 +293,7 @@ CLUSTER_CL4: cluster-sleep-0 { }; CLUSTER_CL5: cluster-sleep-1 { - compatible = "arm,idle-state"; + compatible = "domain-idle-state"; idle-state-name = "ret-pll-off"; arm,psci-suspend-param = <0x01000054>; entry-latency-us = <2200>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi index 5846a11f0e84..d5e035823eb5 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet.dtsi @@ -663,7 +663,7 @@ mipi_in_panel: endpoint { port@1 { reg = <1>; - mipi1_in_panel: endpoint@1 { + mipi1_in_panel: endpoint { remote-endpoint = <&mipi1_out_panel>; }; }; @@ -689,7 +689,6 @@ &pcie0 { ep-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; /* PERST# asserted in S3 */ - pcie-reset-suspend = <1>; vpcie3v3-supply = <&wlan_3v3>; vpcie1v8-supply = <&pp1800_pcie>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts index dfb2a0bdea5b..9586bb12a5d8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-kobol-helios64.dts @@ -611,7 +611,7 @@ device@4 { #size-cells = <0>; interface@0 { /* interface 0 of configuration 1 */ - compatible = "usbbda,8156.config1.0"; + compatible = "usbifbda,8156.config1.0"; reg = <0 1>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts index 054c6a4d1a45..294eb2de263d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts @@ -779,7 +779,6 @@ &pcie_phy { }; &pcie0 { - bus-scan-delay-ms = <1000>; ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>; num-lanes = <4>; pinctrl-names = "default"; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts index 2c3984a880af..f6f15946579e 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts @@ -194,6 +194,8 @@ &pcie0 { num-lanes = <4>; pinctrl-names = "default"; pinctrl-0 = <&pcie_clkreqn_cpm>; + vpcie3v3-supply = <&vcc3v3_baseboard>; + vpcie12v-supply = <&dc_12v>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi index c08e69391c01..ccbe3a7a1d2c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi @@ -79,6 +79,26 @@ vcc5v0_sys: vcc5v0-sys { regulator-max-microvolt = <5000000>; }; + vcca_0v9: vcca-0v9-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcca_0v9"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <900000>; + vin-supply = <&vcc_1v8>; + }; + + vcca_1v8: vcca-1v8-regulator { + compatible = "regulator-fixed"; + regulator-name = "vcca_1v8"; + regulator-always-on; + regulator-boot-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vin-supply = <&vcc3v3_sys>; + }; + vdd_log: vdd-log { compatible = "pwm-regulator"; pwms = <&pwm2 0 25000 1>; @@ -416,16 +436,28 @@ &io_domains { gpio1830-supply = <&vcc_1v8>; }; -&pmu_io_domains { - status = "okay"; - pmu1830-supply = <&vcc_1v8>; +&pcie0 { + /* PCIe PHY supplies */ + vpcie0v9-supply = <&vcca_0v9>; + vpcie1v8-supply = <&vcca_1v8>; }; -&pwm2 { - status = "okay"; +&pcie_clkreqn_cpm { + rockchip,pins = + <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>; }; &pinctrl { + pinctrl-names = "default"; + pinctrl-0 = <&q7_thermal_pin>; + + gpios { + q7_thermal_pin: q7-thermal-pin { + rockchip,pins = + <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>; + }; + }; + i2c8 { i2c8_xfer_a: i2c8-xfer { rockchip,pins = @@ -458,11 +490,20 @@ vcc5v0_host_en: vcc5v0-host-en { usb3 { usb3_id: usb3-id { rockchip,pins = - <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>; + <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>; }; }; }; +&pmu_io_domains { + status = "okay"; + pmu1830-supply = <&vcc_1v8>; +}; + +&pwm2 { + status = "okay"; +}; + &sdhci { /* * Signal integrity isn't great at 200MHz but 100MHz has proven stable diff --git a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts index 6ecdf5d28339..c1194d1e438d 100644 --- a/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts +++ b/arch/arm64/boot/dts/rockchip/rk3566-lubancat-1.dts @@ -447,7 +447,6 @@ rgmii_phy1: phy@0 { &pcie2x1 { reset-gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; - disable-gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_pcie>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts index 7b5f3904ef61..c87fad2c34cb 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts @@ -416,6 +416,8 @@ regulator-state-mem { vccio_sd: LDO_REG5 { regulator-name = "vccio_sd"; + regulator-always-on; + regulator-boot-on; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3300000>; @@ -525,9 +527,9 @@ &mdio0 { #address-cells = <1>; #size-cells = <0>; - switch@0 { + switch@1f { compatible = "mediatek,mt7531"; - reg = <0>; + reg = <0x1f>; ports { #address-cells = <1>; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts index a8a4cc190eb3..a3112d5df200 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-lubancat-2.dts @@ -523,7 +523,6 @@ &pcie3x2 { &pcie2x1 { reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>; - disable-gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>; vpcie3v3-supply = <&vcc3v3_mini_pcie>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi index cce1c8e83587..94ecb9b4f98f 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi @@ -216,9 +216,9 @@ &i2c7 { pinctrl-0 = <&i2c7m0_xfer>; status = "okay"; - es8316: audio-codec@11 { + es8316: audio-codec@10 { compatible = "everest,es8316"; - reg = <0x11>; + reg = <0x10>; assigned-clocks = <&cru I2S0_8CH_MCLKOUT>; assigned-clock-rates = <12288000>; clocks = <&cru I2S0_8CH_MCLKOUT>; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts index 1b606ea5b6cf..1a604429fb26 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts @@ -485,6 +485,7 @@ pmic@0 { pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; spi-max-frequency = <1000000>; + system-power-controller; vcc1-supply = <&vcc5v0_sys>; vcc2-supply = <&vcc5v0_sys>; @@ -506,7 +507,7 @@ pmic@0 { #gpio-cells = <2>; rk806_dvs1_null: dvs1-null-pins { - pins = "gpio_pwrctrl2"; + pins = "gpio_pwrctrl1"; function = "pin_fun0"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts index 67414d72e2b6..22bbfbe729c1 100644 --- a/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3588-quartzpro64.dts @@ -456,6 +456,7 @@ pmic@0 { <&rk806_dvs2_null>, <&rk806_dvs3_null>; pinctrl-names = "default"; spi-max-frequency = <1000000>; + system-power-controller; vcc1-supply = <&vcc4v0_sys>; vcc2-supply = <&vcc4v0_sys>; diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 3b0e8248e1a4..a75de2665d84 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -161,12 +161,18 @@ static inline unsigned long get_trans_granule(void) #define MAX_TLBI_RANGE_PAGES __TLBI_RANGE_PAGES(31, 3) /* - * Generate 'num' values from -1 to 30 with -1 rejected by the - * __flush_tlb_range() loop below. + * Generate 'num' values from -1 to 31 with -1 rejected by the + * __flush_tlb_range() loop below. Its return value is only + * significant for a maximum of MAX_TLBI_RANGE_PAGES pages. If + * 'pages' is more than that, you must iterate over the overall + * range. */ -#define TLBI_RANGE_MASK GENMASK_ULL(4, 0) -#define __TLBI_RANGE_NUM(pages, scale) \ - ((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1) +#define __TLBI_RANGE_NUM(pages, scale) \ + ({ \ + int __pages = min((pages), \ + __TLBI_RANGE_PAGES(31, (scale))); \ + (__pages >> (5 * (scale) + 1)) - 1; \ + }) /* * TLB Invalidation @@ -379,10 +385,6 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) * 3. If there is 1 page remaining, flush it through non-range operations. Range * operations can only span an even number of pages. We save this for last to * ensure 64KB start alignment is maintained for the LPA2 case. - * - * Note that certain ranges can be represented by either num = 31 and - * scale or num = 0 and scale + 1. The loop below favours the latter - * since num is limited to 30 by the __TLBI_RANGE_NUM() macro. */ #define __flush_tlb_range_op(op, start, pages, stride, \ asid, tlb_level, tlbi_user, lpa2) \ diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index ce08b744aaab..cb68adcabe07 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -289,8 +289,28 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) adr_l x1, __hyp_text_end adr_l x2, dcache_clean_poc blr x2 + + mov_q x0, INIT_SCTLR_EL2_MMU_OFF + pre_disable_mmu_workaround + msr sctlr_el2, x0 + isb 0: mov_q x0, HCR_HOST_NVHE_FLAGS + + /* + * Compliant CPUs advertise their VHE-onlyness with + * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be + * RES1 in that case. Publish the E2H bit early so that + * it can be picked up by the init_el2_state macro. + * + * Fruity CPUs seem to have HCR_EL2.E2H set to RAO/WI, but + * don't advertise it (they predate this relaxation). + */ + mrs_s x1, SYS_ID_AA64MMFR4_EL1 + tbz x1, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f + + orr x0, x0, #HCR_E2H +1: msr hcr_el2, x0 isb @@ -303,30 +323,16 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) mov_q x1, INIT_SCTLR_EL1_MMU_OFF - /* - * Compliant CPUs advertise their VHE-onlyness with - * ID_AA64MMFR4_EL1.E2H0 < 0. HCR_EL2.E2H can be - * RES1 in that case. - * - * Fruity CPUs seem to have HCR_EL2.E2H set to RES1, but - * don't advertise it (they predate this relaxation). - */ - mrs_s x0, SYS_ID_AA64MMFR4_EL1 - ubfx x0, x0, #ID_AA64MMFR4_EL1_E2H0_SHIFT, #ID_AA64MMFR4_EL1_E2H0_WIDTH - tbnz x0, #(ID_AA64MMFR4_EL1_E2H0_SHIFT + ID_AA64MMFR4_EL1_E2H0_WIDTH - 1), 1f - mrs x0, hcr_el2 and x0, x0, #HCR_E2H cbz x0, 2f -1: + /* Set a sane SCTLR_EL1, the VHE way */ - pre_disable_mmu_workaround msr_s SYS_SCTLR_EL12, x1 mov x2, #BOOT_CPU_FLAG_E2H b 3f 2: - pre_disable_mmu_workaround msr sctlr_el1, x1 mov x2, xzr 3: diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 162b030ab9da..0d022599eb61 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -761,7 +761,6 @@ static void sve_init_header_from_task(struct user_sve_header *header, { unsigned int vq; bool active; - bool fpsimd_only; enum vec_type task_type; memset(header, 0, sizeof(*header)); @@ -777,12 +776,10 @@ static void sve_init_header_from_task(struct user_sve_header *header, case ARM64_VEC_SVE: if (test_tsk_thread_flag(target, TIF_SVE_VL_INHERIT)) header->flags |= SVE_PT_VL_INHERIT; - fpsimd_only = !test_tsk_thread_flag(target, TIF_SVE); break; case ARM64_VEC_SME: if (test_tsk_thread_flag(target, TIF_SME_VL_INHERIT)) header->flags |= SVE_PT_VL_INHERIT; - fpsimd_only = false; break; default: WARN_ON_ONCE(1); @@ -790,7 +787,7 @@ static void sve_init_header_from_task(struct user_sve_header *header, } if (active) { - if (fpsimd_only) { + if (target->thread.fp_type == FP_STATE_FPSIMD) { header->flags |= SVE_PT_REGS_FPSIMD; } else { header->flags |= SVE_PT_REGS_SVE; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 3dee5490eea9..c4a0a35e02c7 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -2597,14 +2597,11 @@ static __init int kvm_arm_init(void) if (err) goto out_hyp; - if (is_protected_kvm_enabled()) { - kvm_info("Protected nVHE mode initialized successfully\n"); - } else if (in_hyp_mode) { - kvm_info("VHE mode initialized successfully\n"); - } else { - char mode = cpus_have_final_cap(ARM64_KVM_HVHE) ? 'h' : 'n'; - kvm_info("Hyp mode (%cVHE) initialized successfully\n", mode); - } + kvm_info("%s%sVHE mode initialized successfully\n", + in_hyp_mode ? "" : (is_protected_kvm_enabled() ? + "Protected " : "Hyp "), + in_hyp_mode ? "" : (cpus_have_final_cap(ARM64_KVM_HVHE) ? + "h" : "n")); /* * FIXME: Do something reasonable if kvm_init() fails after pKVM diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c index a60fb13e2192..2fc68da4036d 100644 --- a/arch/arm64/kvm/hyp/nvhe/tlb.c +++ b/arch/arm64/kvm/hyp/nvhe/tlb.c @@ -154,7 +154,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu, /* Switch to requested VMID */ __tlb_switch_to_guest(mmu, &cxt, false); - __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0); + __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, + TLBI_TTL_UNKNOWN); dsb(ish); __tlbi(vmalle1is); diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 3fae5830f8d2..5a59ef88b646 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -528,7 +528,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx, kvm_clear_pte(ctx->ptep); dsb(ishst); - __tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), ctx->level); + __tlbi_level(vae2is, __TLBI_VADDR(ctx->addr, 0), TLBI_TTL_UNKNOWN); } else { if (ctx->end - ctx->addr < granule) return -EINVAL; @@ -843,12 +843,15 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx, * Perform the appropriate TLB invalidation based on the * evicted pte value (if any). */ - if (kvm_pte_table(ctx->old, ctx->level)) - kvm_tlb_flush_vmid_range(mmu, ctx->addr, - kvm_granule_size(ctx->level)); - else if (kvm_pte_valid(ctx->old)) + if (kvm_pte_table(ctx->old, ctx->level)) { + u64 size = kvm_granule_size(ctx->level); + u64 addr = ALIGN_DOWN(ctx->addr, size); + + kvm_tlb_flush_vmid_range(mmu, addr, size); + } else if (kvm_pte_valid(ctx->old)) { kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level); + } } if (stage2_pte_is_counted(ctx->old)) @@ -896,9 +899,13 @@ static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx, if (kvm_pte_valid(ctx->old)) { kvm_clear_pte(ctx->ptep); - if (!stage2_unmap_defer_tlb_flush(pgt)) - kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, - ctx->addr, ctx->level); + if (kvm_pte_table(ctx->old, ctx->level)) { + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, + TLBI_TTL_UNKNOWN); + } else if (!stage2_unmap_defer_tlb_flush(pgt)) { + kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, + ctx->level); + } } mm_ops->put_page(ctx->ptep); diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c index b32e2940df7d..1a60b95381e8 100644 --- a/arch/arm64/kvm/hyp/vhe/tlb.c +++ b/arch/arm64/kvm/hyp/vhe/tlb.c @@ -171,7 +171,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu, /* Switch to requested VMID */ __tlb_switch_to_guest(mmu, &cxt); - __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0); + __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, + TLBI_TTL_UNKNOWN); dsb(ish); __tlbi(vmalle1is); diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 18680771cdb0..dc04bc767865 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1637,7 +1637,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu) fault_ipa = kvm_vcpu_get_fault_ipa(vcpu); is_iabt = kvm_vcpu_trap_is_iabt(vcpu); - if (esr_fsc_is_permission_fault(esr)) { + if (esr_fsc_is_translation_fault(esr)) { /* Beyond sanitised PARange (which is the IPA limit) */ if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) { kvm_inject_size_fault(vcpu); diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 0f0e10bb0a95..b872b003a55f 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -276,7 +276,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, pte_t *ptep = NULL; pgdp = pgd_offset(mm, addr); - p4dp = p4d_offset(pgdp, addr); + p4dp = p4d_alloc(mm, pgdp, addr); + if (!p4dp) + return NULL; + pudp = pud_alloc(mm, p4dp, addr); if (!pudp) return NULL; diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 0c4e3ecf989d..0e270a1c51e6 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -219,9 +219,6 @@ bool kernel_page_present(struct page *page) pte_t *ptep; unsigned long addr = (unsigned long)page_address(page); - if (!can_set_direct_map()) - return true; - pgdp = pgd_offset_k(addr); if (pgd_none(READ_ONCE(*pgdp))) return false; diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig index a5f300ec6f28..54ad04dacdee 100644 --- a/arch/loongarch/Kconfig +++ b/arch/loongarch/Kconfig @@ -595,7 +595,7 @@ config ARCH_SELECTS_CRASH_DUMP select RELOCATABLE config ARCH_HAS_GENERIC_CRASHKERNEL_RESERVATION - def_bool CRASH_CORE + def_bool CRASH_RESERVE config RELOCATABLE bool "Relocatable kernel" diff --git a/arch/loongarch/boot/dts/loongson-2k1000.dtsi b/arch/loongarch/boot/dts/loongson-2k1000.dtsi index 49a70f8c3cab..b6aeb1f70e2a 100644 --- a/arch/loongarch/boot/dts/loongson-2k1000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k1000.dtsi @@ -100,6 +100,13 @@ bus@10000000 { #size-cells = <2>; dma-coherent; + isa@18000000 { + compatible = "isa"; + #size-cells = <1>; + #address-cells = <2>; + ranges = <1 0x0 0x0 0x18000000 0x4000>; + }; + liointc0: interrupt-controller@1fe01400 { compatible = "loongson,liointc-2.0"; reg = <0x0 0x1fe01400 0x0 0x40>, diff --git a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts index dca91caf895e..74b99bd234cc 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts +++ b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts @@ -61,12 +61,45 @@ &xhci1 { &gmac0 { status = "okay"; + + phy-mode = "gmii"; + phy-handle = <&phy0>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <2>; + }; + }; }; &gmac1 { status = "okay"; + + phy-mode = "gmii"; + phy-handle = <&phy1>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@1 { + reg = <2>; + }; + }; }; &gmac2 { status = "okay"; + + phy-mode = "rgmii"; + phy-handle = <&phy2>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy2: ethernet-phy@2 { + reg = <0>; + }; + }; }; diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi index a231949b5f55..9eab2d02cbe8 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi @@ -51,6 +51,13 @@ bus@10000000 { #address-cells = <2>; #size-cells = <2>; + isa@18400000 { + compatible = "isa"; + #size-cells = <1>; + #address-cells = <2>; + ranges = <1 0x0 0x0 0x18400000 0x4000>; + }; + pmc: power-management@100d0000 { compatible = "loongson,ls2k2000-pmc", "loongson,ls2k0500-pmc", "syscon"; reg = <0x0 0x100d0000 0x0 0x58>; @@ -109,6 +116,8 @@ pic: interrupt-controller@10000000 { msi: msi-controller@1fe01140 { compatible = "loongson,pch-msi-1.0"; reg = <0x0 0x1fe01140 0x0 0x8>; + interrupt-controller; + #interrupt-cells = <1>; msi-controller; loongson,msi-base-vec = <64>; loongson,msi-num-vecs = <192>; @@ -140,27 +149,34 @@ pcie@1a000000 { #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + msi-parent = <&msi>; bus-range = <0x0 0xff>; - ranges = <0x01000000 0x0 0x00008000 0x0 0x18400000 0x0 0x00008000>, + ranges = <0x01000000 0x0 0x00008000 0x0 0x18408000 0x0 0x00008000>, <0x02000000 0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>; gmac0: ethernet@3,0 { reg = <0x1800 0x0 0x0 0x0 0x0>; - interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>, + <13 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; gmac1: ethernet@3,1 { reg = <0x1900 0x0 0x0 0x0 0x0>; - interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <14 IRQ_TYPE_LEVEL_HIGH>, + <15 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; gmac2: ethernet@3,2 { reg = <0x1a00 0x0 0x0 0x0 0x0>; - interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>, + <18 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; diff --git a/arch/loongarch/include/asm/addrspace.h b/arch/loongarch/include/asm/addrspace.h index b24437e28c6e..7bd47d65bf7a 100644 --- a/arch/loongarch/include/asm/addrspace.h +++ b/arch/loongarch/include/asm/addrspace.h @@ -11,6 +11,7 @@ #define _ASM_ADDRSPACE_H #include +#include #include diff --git a/arch/loongarch/include/asm/crash_core.h b/arch/loongarch/include/asm/crash_reserve.h similarity index 75% rename from arch/loongarch/include/asm/crash_core.h rename to arch/loongarch/include/asm/crash_reserve.h index 218bdbfa527b..a1d9b84b1c7d 100644 --- a/arch/loongarch/include/asm/crash_core.h +++ b/arch/loongarch/include/asm/crash_reserve.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#ifndef _LOONGARCH_CRASH_CORE_H -#define _LOONGARCH_CRASH_CORE_H +#ifndef _LOONGARCH_CRASH_RESERVE_H +#define _LOONGARCH_CRASH_RESERVE_H #define CRASH_ALIGN SZ_2M diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h index 4a8adcca329b..c2f9979b2979 100644 --- a/arch/loongarch/include/asm/io.h +++ b/arch/loongarch/include/asm/io.h @@ -14,11 +14,6 @@ #include #include -/* - * Change "struct page" to physical address. - */ -#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT) - extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size); extern void __init early_iounmap(void __iomem *addr, unsigned long size); @@ -73,6 +68,21 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t #define __io_aw() mmiowb() +#ifdef CONFIG_KFENCE +#define virt_to_phys(kaddr) \ +({ \ + (likely((unsigned long)kaddr < vm_map_base)) ? __pa((unsigned long)kaddr) : \ + page_to_phys(tlb_virt_to_page((unsigned long)kaddr)) + offset_in_page((unsigned long)kaddr);\ +}) + +#define phys_to_virt(paddr) \ +({ \ + extern char *__kfence_pool; \ + (unlikely(__kfence_pool == NULL)) ? __va((unsigned long)paddr) : \ + page_address(phys_to_page((unsigned long)paddr)) + offset_in_page((unsigned long)paddr);\ +}) +#endif + #include #define ARCH_HAS_VALID_PHYS_ADDR_RANGE diff --git a/arch/loongarch/include/asm/kfence.h b/arch/loongarch/include/asm/kfence.h index 6c82aea1c993..a6a5760da3a3 100644 --- a/arch/loongarch/include/asm/kfence.h +++ b/arch/loongarch/include/asm/kfence.h @@ -16,6 +16,7 @@ static inline bool arch_kfence_init_pool(void) { int err; + char *kaddr, *vaddr; char *kfence_pool = __kfence_pool; struct vm_struct *area; @@ -35,6 +36,14 @@ static inline bool arch_kfence_init_pool(void) return false; } + kaddr = kfence_pool; + vaddr = __kfence_pool; + while (kaddr < kfence_pool + KFENCE_POOL_SIZE) { + set_page_address(virt_to_page(kaddr), vaddr); + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return true; } diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h index 44027060c54a..e85df33f11c7 100644 --- a/arch/loongarch/include/asm/page.h +++ b/arch/loongarch/include/asm/page.h @@ -78,7 +78,26 @@ typedef struct { unsigned long pgprot; } pgprot_t; struct page *dmw_virt_to_page(unsigned long kaddr); struct page *tlb_virt_to_page(unsigned long kaddr); -#define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr)) +#define pfn_to_phys(pfn) __pfn_to_phys(pfn) +#define phys_to_pfn(paddr) __phys_to_pfn(paddr) + +#define page_to_phys(page) pfn_to_phys(page_to_pfn(page)) +#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr)) + +#ifndef CONFIG_KFENCE + +#define page_to_virt(page) __va(page_to_phys(page)) +#define virt_to_page(kaddr) phys_to_page(__pa(kaddr)) + +#else + +#define WANT_PAGE_VIRTUAL + +#define page_to_virt(page) \ +({ \ + extern char *__kfence_pool; \ + (__kfence_pool == NULL) ? __va(page_to_phys(page)) : page_address(page); \ +}) #define virt_to_page(kaddr) \ ({ \ @@ -86,6 +105,11 @@ struct page *tlb_virt_to_page(unsigned long kaddr); dmw_virt_to_page((unsigned long)kaddr) : tlb_virt_to_page((unsigned long)kaddr);\ }) +#endif + +#define pfn_to_virt(pfn) page_to_virt(pfn_to_page(pfn)) +#define virt_to_pfn(kaddr) page_to_pfn(virt_to_page(kaddr)) + extern int __virt_addr_valid(volatile void *kaddr); #define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr)) diff --git a/arch/loongarch/include/asm/perf_event.h b/arch/loongarch/include/asm/perf_event.h index 2a35a0bc2aaa..52b638059e40 100644 --- a/arch/loongarch/include/asm/perf_event.h +++ b/arch/loongarch/include/asm/perf_event.h @@ -7,6 +7,14 @@ #ifndef __LOONGARCH_PERF_EVENT_H__ #define __LOONGARCH_PERF_EVENT_H__ +#include + #define perf_arch_bpf_user_pt_regs(regs) (struct user_pt_regs *)regs +#define perf_arch_fetch_caller_regs(regs, __ip) { \ + (regs)->csr_era = (__ip); \ + (regs)->regs[3] = current_stack_pointer; \ + (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \ +} + #endif /* __LOONGARCH_PERF_EVENT_H__ */ diff --git a/arch/loongarch/include/asm/tlb.h b/arch/loongarch/include/asm/tlb.h index da7a3b5b9374..e071f5e9e858 100644 --- a/arch/loongarch/include/asm/tlb.h +++ b/arch/loongarch/include/asm/tlb.h @@ -132,8 +132,6 @@ static __always_inline void invtlb_all(u32 op, u32 info, u64 addr) ); } -#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) - static void tlb_flush(struct mmu_gather *tlb); #define tlb_flush tlb_flush diff --git a/arch/loongarch/kernel/perf_event.c b/arch/loongarch/kernel/perf_event.c index 0491bf453cd4..cac7cba81b65 100644 --- a/arch/loongarch/kernel/perf_event.c +++ b/arch/loongarch/kernel/perf_event.c @@ -884,4 +884,4 @@ static int __init init_hw_perf_events(void) return 0; } -early_initcall(init_hw_perf_events); +pure_initcall(init_hw_perf_events); diff --git a/arch/loongarch/mm/fault.c b/arch/loongarch/mm/fault.c index 1fc2f6813ea0..97b40defde06 100644 --- a/arch/loongarch/mm/fault.c +++ b/arch/loongarch/mm/fault.c @@ -202,10 +202,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, if (!(vma->vm_flags & VM_WRITE)) goto bad_area; } else { - if (!(vma->vm_flags & VM_READ) && address != exception_era(regs)) - goto bad_area; if (!(vma->vm_flags & VM_EXEC) && address == exception_era(regs)) goto bad_area; + if (!(vma->vm_flags & (VM_READ | VM_WRITE)) && address != exception_era(regs)) + goto bad_area; } /* diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c index a9630a81b38a..89af7c12e8c0 100644 --- a/arch/loongarch/mm/mmap.c +++ b/arch/loongarch/mm/mmap.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -111,6 +112,9 @@ int __virt_addr_valid(volatile void *kaddr) { unsigned long vaddr = (unsigned long)kaddr; + if (is_kfence_address((void *)kaddr)) + return 1; + if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base)) return 0; diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c index 2aae72e63871..bda018150000 100644 --- a/arch/loongarch/mm/pgtable.c +++ b/arch/loongarch/mm/pgtable.c @@ -11,13 +11,13 @@ struct page *dmw_virt_to_page(unsigned long kaddr) { - return pfn_to_page(virt_to_pfn(kaddr)); + return phys_to_page(__pa(kaddr)); } EXPORT_SYMBOL(dmw_virt_to_page); struct page *tlb_virt_to_page(unsigned long kaddr) { - return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr))); + return phys_to_page(pfn_to_phys(pte_pfn(*virt_to_kpte(kaddr)))); } EXPORT_SYMBOL(tlb_virt_to_page); diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index d14d0e37ad02..4a2b40ce39e0 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -159,7 +159,7 @@ extern unsigned long exception_ip(struct pt_regs *regs); #define exception_ip(regs) exception_ip(regs) #define profile_pc(regs) instruction_pointer(regs) -extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall); +extern asmlinkage long syscall_trace_enter(struct pt_regs *regs); extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); extern void die(const char *, struct pt_regs *) __noreturn; diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index d1b11f66f748..cb1045ebab06 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -101,6 +101,7 @@ void output_thread_info_defines(void) OFFSET(TI_CPU, thread_info, cpu); OFFSET(TI_PRE_COUNT, thread_info, preempt_count); OFFSET(TI_REGS, thread_info, regs); + OFFSET(TI_SYSCALL, thread_info, syscall); DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 59288c13b581..61503a36067e 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1317,16 +1317,13 @@ long arch_ptrace(struct task_struct *child, long request, * Notification of system call entry/exit * - triggered by current->work.syscall_trace */ -asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) +asmlinkage long syscall_trace_enter(struct pt_regs *regs) { user_exit(); - current_thread_info()->syscall = syscall; - if (test_thread_flag(TIF_SYSCALL_TRACE)) { if (ptrace_report_syscall_entry(regs)) return -1; - syscall = current_thread_info()->syscall; } #ifdef CONFIG_SECCOMP @@ -1335,7 +1332,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) struct seccomp_data sd; unsigned long args[6]; - sd.nr = syscall; + sd.nr = current_thread_info()->syscall; sd.arch = syscall_get_arch(current); syscall_get_arguments(current, regs, args); for (i = 0; i < 6; i++) @@ -1345,23 +1342,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) ret = __secure_computing(&sd); if (ret == -1) return ret; - syscall = current_thread_info()->syscall; } #endif if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_enter(regs, regs->regs[2]); - audit_syscall_entry(syscall, regs->regs[4], regs->regs[5], + audit_syscall_entry(current_thread_info()->syscall, + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); /* * Negative syscall numbers are mistaken for rejected syscalls, but * won't have had the return value set appropriately, so we do so now. */ - if (syscall < 0) + if (current_thread_info()->syscall < 0) syscall_set_return_value(current, regs, -ENOSYS, 0); - return syscall; + return current_thread_info()->syscall; } /* diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 18dc9b345056..2c604717e630 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -77,6 +77,18 @@ loads_done: PTR_WD load_a7, bad_stack_a7 .previous + /* + * syscall number is in v0 unless we called syscall(__NR_###) + * where the real syscall number is in a0 + */ + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number + b 2f +1: + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number +2: + lw t0, TI_FLAGS($28) # syscall tracing enabled? li t1, _TIF_WORK_SYSCALL_ENTRY and t0, t1 @@ -114,16 +126,7 @@ syscall_trace_entry: SAVE_STATIC move a0, sp - /* - * syscall number is in v0 unless we called syscall(__NR_###) - * where the real syscall number is in a0 - */ - move a1, v0 - subu t2, v0, __NR_O32_Linux - bnez t2, 1f /* __NR_syscall at offset 0 */ - lw a1, PT_R4(sp) - -1: jal syscall_trace_enter + jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 97456b2ca7dc..97788859238c 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting + LONG_S v0, TI_SYSCALL($28) # Store syscall number + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -72,7 +74,6 @@ syscall_common: n32_syscall_trace_entry: SAVE_STATIC move a0, sp - move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S index e6264aa62e45..be11ea5cc67e 100644 --- a/arch/mips/kernel/scall64-n64.S +++ b/arch/mips/kernel/scall64-n64.S @@ -46,6 +46,8 @@ NESTED(handle_sys64, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting + LONG_S v0, TI_SYSCALL($28) # Store syscall number + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -82,7 +84,6 @@ n64_syscall_exit: syscall_trace_entry: SAVE_STATIC move a0, sp - move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d3c2616cba22..7a5abb73e531 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -79,6 +79,22 @@ loads_done: PTR_WD load_a7, bad_stack_a7 .previous + /* + * absolute syscall number is in v0 unless we called syscall(__NR_###) + * where the real syscall number is in a0 + * note: NR_syscall is the first O32 syscall but the macro is + * only defined when compiling with -mabi=32 (CONFIG_32BIT) + * therefore __NR_O32_Linux is used (4000) + */ + + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number + b 2f +1: + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number +2: + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -113,22 +129,7 @@ trace_a_syscall: sd a7, PT_R11(sp) # For indirect syscalls move a0, sp - /* - * absolute syscall number is in v0 unless we called syscall(__NR_###) - * where the real syscall number is in a0 - * note: NR_syscall is the first O32 syscall but the macro is - * only defined when compiling with -mabi=32 (CONFIG_32BIT) - * therefore __NR_O32_Linux is used (4000) - */ - .set push - .set reorder - subu t1, v0, __NR_O32_Linux - move a1, v0 - bnez t1, 1f /* __NR_syscall at offset 0 */ - ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */ - .set pop - -1: jal syscall_trace_enter + jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/nios2/kernel/prom.c b/arch/nios2/kernel/prom.c index 8d98af5c7201..9a8393e6b4a8 100644 --- a/arch/nios2/kernel/prom.c +++ b/arch/nios2/kernel/prom.c @@ -21,7 +21,8 @@ void __init early_init_devtree(void *params) { - __be32 *dtb = (u32 *)__dtb_start; + __be32 __maybe_unused *dtb = (u32 *)__dtb_start; + #if defined(CONFIG_NIOS2_DTB_AT_PHYS_ADDR) if (be32_to_cpup((__be32 *)CONFIG_NIOS2_DTB_PHYS_ADDR) == OF_DT_HEADER) { @@ -30,8 +31,11 @@ void __init early_init_devtree(void *params) return; } #endif + +#ifdef CONFIG_NIOS2_DTB_SOURCE_BOOL if (be32_to_cpu((__be32) *dtb) == OF_DT_HEADER) params = (void *)__dtb_start; +#endif early_init_dt_scan(params); } diff --git a/arch/powerpc/crypto/chacha-p10-glue.c b/arch/powerpc/crypto/chacha-p10-glue.c index 74fb86b0d209..7c728755852e 100644 --- a/arch/powerpc/crypto/chacha-p10-glue.c +++ b/arch/powerpc/crypto/chacha-p10-glue.c @@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = { static int __init chacha_p10_init(void) { + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return 0; + static_branch_enable(&have_p10); return crypto_register_skciphers(algs, ARRAY_SIZE(algs)); @@ -204,10 +207,13 @@ static int __init chacha_p10_init(void) static void __exit chacha_p10_exit(void) { + if (!static_branch_likely(&have_p10)) + return; + crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); } -module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init); +module_init(chacha_p10_init); module_exit(chacha_p10_exit); MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)"); diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h b/arch/powerpc/include/asm/vdso/gettimeofday.h index f0a4cf01e85c..78302f6c2580 100644 --- a/arch/powerpc/include/asm/vdso/gettimeofday.h +++ b/arch/powerpc/include/asm/vdso/gettimeofday.h @@ -4,7 +4,6 @@ #ifndef __ASSEMBLY__ -#include #include #include #include @@ -95,7 +94,7 @@ const struct vdso_data *__arch_get_vdso_data(void); static __always_inline const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) { - return (void *)vd + PAGE_SIZE; + return (void *)vd + (1U << CONFIG_PAGE_SHIFT); } #endif diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 1185efebf032..29a8c8e18585 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1285,15 +1285,14 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain, struct device *dev) { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); - struct iommu_group *grp = iommu_group_get(dev); struct iommu_table_group *table_group; + struct iommu_group *grp; /* At first attach the ownership is already set */ - if (!domain) { - iommu_group_put(grp); + if (!domain) return 0; - } + grp = iommu_group_get(dev); table_group = iommu_group_get_iommudata(grp); /* * The domain being set to PLATFORM from earlier diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata index 910ba8837add..2acc7d876e1f 100644 --- a/arch/riscv/Kconfig.errata +++ b/arch/riscv/Kconfig.errata @@ -82,14 +82,14 @@ config ERRATA_THEAD Otherwise, please say "N" here to avoid unnecessary overhead. -config ERRATA_THEAD_PBMT - bool "Apply T-Head memory type errata" +config ERRATA_THEAD_MAE + bool "Apply T-Head's memory attribute extension (XTheadMae) errata" depends on ERRATA_THEAD && 64BIT && MMU select RISCV_ALTERNATIVE_EARLY default y help - This will apply the memory type errata to handle the non-standard - memory type bits in page-table-entries on T-Head SoCs. + This will apply the memory attribute extension errata to handle the + non-standard PTE utilization on T-Head SoCs (XTheadMae). If you don't know what to do here, say "Y". diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 252d63942f34..5b3115a19852 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -151,7 +151,7 @@ endif endif vdso-install-y += arch/riscv/kernel/vdso/vdso.so.dbg -vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg:../compat_vdso/compat_vdso.so +vdso-install-$(CONFIG_COMPAT) += arch/riscv/kernel/compat_vdso/compat_vdso.so.dbg ifneq ($(CONFIG_XIP_KERNEL),y) ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_ARCH_CANAAN),yy) diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c index b1c410bbc1ae..bf6a0a6318ee 100644 --- a/arch/riscv/errata/thead/errata.c +++ b/arch/riscv/errata/thead/errata.c @@ -19,20 +19,26 @@ #include #include -static bool errata_probe_pbmt(unsigned int stage, - unsigned long arch_id, unsigned long impid) +#define CSR_TH_SXSTATUS 0x5c0 +#define SXSTATUS_MAEE _AC(0x200000, UL) + +static bool errata_probe_mae(unsigned int stage, + unsigned long arch_id, unsigned long impid) { - if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT)) + if (!IS_ENABLED(CONFIG_ERRATA_THEAD_MAE)) return false; if (arch_id != 0 || impid != 0) return false; - if (stage == RISCV_ALTERNATIVES_EARLY_BOOT || - stage == RISCV_ALTERNATIVES_MODULE) - return true; + if (stage != RISCV_ALTERNATIVES_EARLY_BOOT && + stage != RISCV_ALTERNATIVES_MODULE) + return false; - return false; + if (!(csr_read(CSR_TH_SXSTATUS) & SXSTATUS_MAEE)) + return false; + + return true; } /* @@ -140,8 +146,8 @@ static u32 thead_errata_probe(unsigned int stage, { u32 cpu_req_errata = 0; - if (errata_probe_pbmt(stage, archid, impid)) - cpu_req_errata |= BIT(ERRATA_THEAD_PBMT); + if (errata_probe_mae(stage, archid, impid)) + cpu_req_errata |= BIT(ERRATA_THEAD_MAE); errata_probe_cmo(stage, archid, impid); diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h index 1f2dbfb8a8bf..efd851e1b483 100644 --- a/arch/riscv/include/asm/errata_list.h +++ b/arch/riscv/include/asm/errata_list.h @@ -23,7 +23,7 @@ #endif #ifdef CONFIG_ERRATA_THEAD -#define ERRATA_THEAD_PBMT 0 +#define ERRATA_THEAD_MAE 0 #define ERRATA_THEAD_PMU 1 #define ERRATA_THEAD_NUMBER 2 #endif @@ -53,20 +53,20 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \ * in the default case. */ #define ALT_SVPBMT_SHIFT 61 -#define ALT_THEAD_PBMT_SHIFT 59 +#define ALT_THEAD_MAE_SHIFT 59 #define ALT_SVPBMT(_val, prot) \ asm(ALTERNATIVE_2("li %0, 0\t\nnop", \ "li %0, %1\t\nslli %0,%0,%3", 0, \ RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT, \ "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, \ - ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \ + ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE) \ : "=r"(_val) \ : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \ - "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \ + "I"(prot##_THEAD >> ALT_THEAD_MAE_SHIFT), \ "I"(ALT_SVPBMT_SHIFT), \ - "I"(ALT_THEAD_PBMT_SHIFT)) + "I"(ALT_THEAD_MAE_SHIFT)) -#ifdef CONFIG_ERRATA_THEAD_PBMT +#ifdef CONFIG_ERRATA_THEAD_MAE /* * IO/NOCACHE memory types are handled together with svpbmt, * so on T-Head chips, check if no other memory type is set, @@ -83,11 +83,11 @@ asm volatile(ALTERNATIVE( \ "slli t3, t3, %3\n\t" \ "or %0, %0, t3\n\t" \ "2:", THEAD_VENDOR_ID, \ - ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \ + ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE) \ : "+r"(_val) \ - : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \ - "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), \ - "I"(ALT_THEAD_PBMT_SHIFT) \ + : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_MAE_SHIFT), \ + "I"(_PAGE_PMA_THEAD >> ALT_THEAD_MAE_SHIFT), \ + "I"(ALT_THEAD_MAE_SHIFT) \ : "t3") #else #define ALT_THEAD_PMA(_val) diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 2947423b5082..115ac98b8d72 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -89,7 +89,7 @@ typedef struct page *pgtable_t; #define PTE_FMT "%08lx" #endif -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) && defined(CONFIG_MMU) /* * We override this value as its generic definition uses __pa too early in * the boot process (before kernel_map.va_pa_offset is set). diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 97fcde30e247..6afd6bb4882e 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -593,6 +593,12 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, return ptep_test_and_clear_young(vma, address, ptep); } +#define pgprot_nx pgprot_nx +static inline pgprot_t pgprot_nx(pgprot_t _prot) +{ + return __pgprot(pgprot_val(_prot) & ~_PAGE_EXEC); +} + #define pgprot_noncached pgprot_noncached static inline pgprot_t pgprot_noncached(pgprot_t _prot) { @@ -890,7 +896,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) #define PAGE_SHARED __pgprot(0) #define PAGE_KERNEL __pgprot(0) #define swapper_pg_dir NULL -#define TASK_SIZE 0xffffffffUL +#define TASK_SIZE _AC(-1, UL) #define VMALLOC_START _AC(0, UL) #define VMALLOC_END TASK_SIZE diff --git a/arch/riscv/include/asm/syscall_wrapper.h b/arch/riscv/include/asm/syscall_wrapper.h index 980094c2e976..ac80216549ff 100644 --- a/arch/riscv/include/asm/syscall_wrapper.h +++ b/arch/riscv/include/asm/syscall_wrapper.h @@ -36,7 +36,8 @@ asmlinkage long __riscv_sys_ni_syscall(const struct pt_regs *); ulong) \ __attribute__((alias(__stringify(___se_##prefix##name)))); \ __diag_pop(); \ - static long noinline ___se_##prefix##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ + static long noinline ___se_##prefix##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ + __used; \ static long ___se_##prefix##name(__MAP(x,__SC_LONG,__VA_ARGS__)) #define SC_RISCV_REGS_TO_ARGS(x, ...) \ diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index ec0cab9fbddd..72ec1d9bd3f3 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h @@ -319,7 +319,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n) #define __get_kernel_nofault(dst, src, type, err_label) \ do { \ - long __kr_err; \ + long __kr_err = 0; \ \ __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \ if (unlikely(__kr_err)) \ @@ -328,7 +328,7 @@ do { \ #define __put_kernel_nofault(dst, src, type, err_label) \ do { \ - long __kr_err; \ + long __kr_err = 0; \ \ __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \ if (unlikely(__kr_err)) \ diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h index 10aaa83db89e..95050ebe9ad0 100644 --- a/arch/riscv/include/uapi/asm/auxvec.h +++ b/arch/riscv/include/uapi/asm/auxvec.h @@ -34,7 +34,7 @@ #define AT_L3_CACHEGEOMETRY 47 /* entries in ARCH_DLINFO */ -#define AT_VECTOR_SIZE_ARCH 9 +#define AT_VECTOR_SIZE_ARCH 10 #define AT_MINSIGSTKSZ 51 #endif /* _UAPI_ASM_RISCV_AUXVEC_H */ diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h index 9f2a8e3ff204..2902f68dc913 100644 --- a/arch/riscv/include/uapi/asm/hwprobe.h +++ b/arch/riscv/include/uapi/asm/hwprobe.h @@ -54,7 +54,7 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) #define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) #define RISCV_HWPROBE_EXT_ZVFH (1 << 30) -#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31) +#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31) #define RISCV_HWPROBE_EXT_ZFA (1ULL << 32) #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33) #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34) diff --git a/arch/riscv/kernel/compat_vdso/Makefile b/arch/riscv/kernel/compat_vdso/Makefile index 62fa393b2eb2..3df4cb788c1f 100644 --- a/arch/riscv/kernel/compat_vdso/Makefile +++ b/arch/riscv/kernel/compat_vdso/Makefile @@ -74,5 +74,5 @@ quiet_cmd_compat_vdsold = VDSOLD $@ rm $@.tmp # actual build commands -quiet_cmd_compat_vdsoas = VDSOAS $@ +quiet_cmd_compat_vdsoas = VDSOAS $@ cmd_compat_vdsoas = $(COMPAT_CC) $(a_flags) $(COMPAT_CC_FLAGS) -c -o $@ $< diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c index 37e87fdcf6a0..30e12b310cab 100644 --- a/arch/riscv/kernel/patch.c +++ b/arch/riscv/kernel/patch.c @@ -80,6 +80,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len) */ lockdep_assert_held(&text_mutex); + preempt_disable(); + if (across_pages) patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1); @@ -92,6 +94,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len) if (across_pages) patch_unmap(FIX_TEXT_POKE1); + preempt_enable(); + return 0; } NOKPROBE_SYMBOL(__patch_insn_set); @@ -122,6 +126,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len) if (!riscv_patch_in_stop_machine) lockdep_assert_held(&text_mutex); + preempt_disable(); + if (across_pages) patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1); @@ -134,6 +140,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len) if (across_pages) patch_unmap(FIX_TEXT_POKE1); + preempt_enable(); + return ret; } NOKPROBE_SYMBOL(__patch_insn_write); diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 92922dbd5b5c..e4bc61c4e58a 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -27,8 +27,6 @@ #include #include -register unsigned long gp_in_global __asm__("gp"); - #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK) #include unsigned long __stack_chk_guard __read_mostly; @@ -37,7 +35,7 @@ EXPORT_SYMBOL(__stack_chk_guard); extern asmlinkage void ret_from_fork(void); -void arch_cpu_idle(void) +void noinstr arch_cpu_idle(void) { cpu_do_idle(); } @@ -207,7 +205,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) if (unlikely(args->fn)) { /* Kernel thread */ memset(childregs, 0, sizeof(struct pt_regs)); - childregs->gp = gp_in_global; /* Supervisor/Machine, irqs on: */ childregs->status = SR_PP | SR_PIE; diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 501e66debf69..5a2edd7f027e 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -119,6 +119,13 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec) struct __sc_riscv_v_state __user *state = sc_vec; void __user *datap; + /* + * Mark the vstate as clean prior performing the actual copy, + * to avoid getting the vstate incorrectly clobbered by the + * discarded vector state. + */ + riscv_v_vstate_set_restore(current, regs); + /* Copy everything of __sc_riscv_v_state except datap. */ err = __copy_from_user(¤t->thread.vstate, &state->v_state, offsetof(struct __riscv_v_ext_state, datap)); @@ -133,13 +140,7 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec) * Copy the whole vector content from user space datap. Use * copy_from_user to prevent information leak. */ - err = copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize); - if (unlikely(err)) - return err; - - riscv_v_vstate_set_restore(current, regs); - - return err; + return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize); } #else #define save_v_state(task, regs) (0) diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 868d6280cf66..05a16b1f0aee 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -122,7 +122,7 @@ void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr) print_vma_addr(KERN_CONT " in ", instruction_pointer(regs)); pr_cont("\n"); __show_regs(regs); - dump_instr(KERN_EMERG, regs); + dump_instr(KERN_INFO, regs); } force_sig_fault(signo, code, (void __user *)addr); diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile index 9b517fe1b8a8..272c431ac5b9 100644 --- a/arch/riscv/kernel/vdso/Makefile +++ b/arch/riscv/kernel/vdso/Makefile @@ -37,6 +37,7 @@ endif # Disable -pg to prevent insert call site CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) +CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) # Disable profiling and instrumentation for VDSO code GCOV_PROFILE := n diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c index 39e72aa016a4..b467ba5ed910 100644 --- a/arch/riscv/kvm/aia_aplic.c +++ b/arch/riscv/kvm/aia_aplic.c @@ -137,11 +137,21 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending) raw_spin_lock_irqsave(&irqd->lock, flags); sm = irqd->sourcecfg & APLIC_SOURCECFG_SM_MASK; - if (!pending && - ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) || - (sm == APLIC_SOURCECFG_SM_LEVEL_LOW))) + if (sm == APLIC_SOURCECFG_SM_INACTIVE) goto skip_write_pending; + if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH || + sm == APLIC_SOURCECFG_SM_LEVEL_LOW) { + if (!pending) + goto skip_write_pending; + if ((irqd->state & APLIC_IRQ_STATE_INPUT) && + sm == APLIC_SOURCECFG_SM_LEVEL_LOW) + goto skip_write_pending; + if (!(irqd->state & APLIC_IRQ_STATE_INPUT) && + sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) + goto skip_write_pending; + } + if (pending) irqd->state |= APLIC_IRQ_STATE_PENDING; else @@ -187,16 +197,31 @@ static void aplic_write_enabled(struct aplic *aplic, u32 irq, bool enabled) static bool aplic_read_input(struct aplic *aplic, u32 irq) { - bool ret; - unsigned long flags; + u32 sourcecfg, sm, raw_input, irq_inverted; struct aplic_irq *irqd; + unsigned long flags; + bool ret = false; if (!irq || aplic->nr_irqs <= irq) return false; irqd = &aplic->irqs[irq]; raw_spin_lock_irqsave(&irqd->lock, flags); - ret = (irqd->state & APLIC_IRQ_STATE_INPUT) ? true : false; + + sourcecfg = irqd->sourcecfg; + if (sourcecfg & APLIC_SOURCECFG_D) + goto skip; + + sm = sourcecfg & APLIC_SOURCECFG_SM_MASK; + if (sm == APLIC_SOURCECFG_SM_INACTIVE) + goto skip; + + raw_input = (irqd->state & APLIC_IRQ_STATE_INPUT) ? 1 : 0; + irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW || + sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0; + ret = !!(raw_input ^ irq_inverted); + +skip: raw_spin_unlock_irqrestore(&irqd->lock, flags); return ret; diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c index f4a6124d25c9..994adc26db4b 100644 --- a/arch/riscv/kvm/vcpu_onereg.c +++ b/arch/riscv/kvm/vcpu_onereg.c @@ -986,7 +986,7 @@ static int copy_isa_ext_reg_indices(const struct kvm_vcpu *vcpu, static inline unsigned long num_isa_ext_regs(const struct kvm_vcpu *vcpu) { - return copy_isa_ext_reg_indices(vcpu, NULL);; + return copy_isa_ext_reg_indices(vcpu, NULL); } static int copy_sbi_ext_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index fe8e159394d8..968761843203 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -231,7 +231,7 @@ static void __init setup_bootmem(void) * In 64-bit, any use of __va/__pa before this point is wrong as we * did not know the start of DRAM before. */ - if (IS_ENABLED(CONFIG_64BIT)) + if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU)) kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base; /* diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 893566e004b7..07d743f87b3f 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -99,7 +99,7 @@ static void __ipi_flush_tlb_range_asid(void *info) local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid); } -static void __flush_tlb_range(struct cpumask *cmask, unsigned long asid, +static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid, unsigned long start, unsigned long size, unsigned long stride) { @@ -200,7 +200,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - __flush_tlb_range((struct cpumask *)cpu_online_mask, FLUSH_TLB_NO_ASID, + __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID, start, end - start, PAGE_SIZE); } diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 7138d189cc42..0c4cad7d5a5b 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -15,31 +15,31 @@ #include #include -static inline int arch_atomic_read(const atomic_t *v) +static __always_inline int arch_atomic_read(const atomic_t *v) { return __atomic_read(v); } #define arch_atomic_read arch_atomic_read -static inline void arch_atomic_set(atomic_t *v, int i) +static __always_inline void arch_atomic_set(atomic_t *v, int i) { __atomic_set(v, i); } #define arch_atomic_set arch_atomic_set -static inline int arch_atomic_add_return(int i, atomic_t *v) +static __always_inline int arch_atomic_add_return(int i, atomic_t *v) { return __atomic_add_barrier(i, &v->counter) + i; } #define arch_atomic_add_return arch_atomic_add_return -static inline int arch_atomic_fetch_add(int i, atomic_t *v) +static __always_inline int arch_atomic_fetch_add(int i, atomic_t *v) { return __atomic_add_barrier(i, &v->counter); } #define arch_atomic_fetch_add arch_atomic_fetch_add -static inline void arch_atomic_add(int i, atomic_t *v) +static __always_inline void arch_atomic_add(int i, atomic_t *v) { __atomic_add(i, &v->counter); } @@ -50,11 +50,11 @@ static inline void arch_atomic_add(int i, atomic_t *v) #define arch_atomic_fetch_sub(_i, _v) arch_atomic_fetch_add(-(int)(_i), _v) #define ATOMIC_OPS(op) \ -static inline void arch_atomic_##op(int i, atomic_t *v) \ +static __always_inline void arch_atomic_##op(int i, atomic_t *v) \ { \ __atomic_##op(i, &v->counter); \ } \ -static inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ +static __always_inline int arch_atomic_fetch_##op(int i, atomic_t *v) \ { \ return __atomic_##op##_barrier(i, &v->counter); \ } @@ -74,7 +74,7 @@ ATOMIC_OPS(xor) #define arch_atomic_xchg(v, new) (arch_xchg(&((v)->counter), new)) -static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) +static __always_inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) { return __atomic_cmpxchg(&v->counter, old, new); } @@ -82,31 +82,31 @@ static inline int arch_atomic_cmpxchg(atomic_t *v, int old, int new) #define ATOMIC64_INIT(i) { (i) } -static inline s64 arch_atomic64_read(const atomic64_t *v) +static __always_inline s64 arch_atomic64_read(const atomic64_t *v) { return __atomic64_read(v); } #define arch_atomic64_read arch_atomic64_read -static inline void arch_atomic64_set(atomic64_t *v, s64 i) +static __always_inline void arch_atomic64_set(atomic64_t *v, s64 i) { __atomic64_set(v, i); } #define arch_atomic64_set arch_atomic64_set -static inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v) +static __always_inline s64 arch_atomic64_add_return(s64 i, atomic64_t *v) { return __atomic64_add_barrier(i, (long *)&v->counter) + i; } #define arch_atomic64_add_return arch_atomic64_add_return -static inline s64 arch_atomic64_fetch_add(s64 i, atomic64_t *v) +static __always_inline s64 arch_atomic64_fetch_add(s64 i, atomic64_t *v) { return __atomic64_add_barrier(i, (long *)&v->counter); } #define arch_atomic64_fetch_add arch_atomic64_fetch_add -static inline void arch_atomic64_add(s64 i, atomic64_t *v) +static __always_inline void arch_atomic64_add(s64 i, atomic64_t *v) { __atomic64_add(i, (long *)&v->counter); } @@ -114,20 +114,20 @@ static inline void arch_atomic64_add(s64 i, atomic64_t *v) #define arch_atomic64_xchg(v, new) (arch_xchg(&((v)->counter), new)) -static inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new) +static __always_inline s64 arch_atomic64_cmpxchg(atomic64_t *v, s64 old, s64 new) { return __atomic64_cmpxchg((long *)&v->counter, old, new); } #define arch_atomic64_cmpxchg arch_atomic64_cmpxchg -#define ATOMIC64_OPS(op) \ -static inline void arch_atomic64_##op(s64 i, atomic64_t *v) \ -{ \ - __atomic64_##op(i, (long *)&v->counter); \ -} \ -static inline long arch_atomic64_fetch_##op(s64 i, atomic64_t *v) \ -{ \ - return __atomic64_##op##_barrier(i, (long *)&v->counter); \ +#define ATOMIC64_OPS(op) \ +static __always_inline void arch_atomic64_##op(s64 i, atomic64_t *v) \ +{ \ + __atomic64_##op(i, (long *)&v->counter); \ +} \ +static __always_inline long arch_atomic64_fetch_##op(s64 i, atomic64_t *v) \ +{ \ + return __atomic64_##op##_barrier(i, (long *)&v->counter); \ } ATOMIC64_OPS(and) diff --git a/arch/s390/include/asm/atomic_ops.h b/arch/s390/include/asm/atomic_ops.h index 50510e08b893..7fa5f96a553a 100644 --- a/arch/s390/include/asm/atomic_ops.h +++ b/arch/s390/include/asm/atomic_ops.h @@ -8,7 +8,7 @@ #ifndef __ARCH_S390_ATOMIC_OPS__ #define __ARCH_S390_ATOMIC_OPS__ -static inline int __atomic_read(const atomic_t *v) +static __always_inline int __atomic_read(const atomic_t *v) { int c; @@ -18,14 +18,14 @@ static inline int __atomic_read(const atomic_t *v) return c; } -static inline void __atomic_set(atomic_t *v, int i) +static __always_inline void __atomic_set(atomic_t *v, int i) { asm volatile( " st %1,%0\n" : "=R" (v->counter) : "d" (i)); } -static inline s64 __atomic64_read(const atomic64_t *v) +static __always_inline s64 __atomic64_read(const atomic64_t *v) { s64 c; @@ -35,7 +35,7 @@ static inline s64 __atomic64_read(const atomic64_t *v) return c; } -static inline void __atomic64_set(atomic64_t *v, s64 i) +static __always_inline void __atomic64_set(atomic64_t *v, s64 i) { asm volatile( " stg %1,%0\n" @@ -45,7 +45,7 @@ static inline void __atomic64_set(atomic64_t *v, s64 i) #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES #define __ATOMIC_OP(op_name, op_type, op_string, op_barrier) \ -static inline op_type op_name(op_type val, op_type *ptr) \ +static __always_inline op_type op_name(op_type val, op_type *ptr) \ { \ op_type old; \ \ @@ -96,7 +96,7 @@ __ATOMIC_CONST_OPS(__atomic64_add_const, long, "agsi") #else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ #define __ATOMIC_OP(op_name, op_string) \ -static inline int op_name(int val, int *ptr) \ +static __always_inline int op_name(int val, int *ptr) \ { \ int old, new; \ \ @@ -122,7 +122,7 @@ __ATOMIC_OPS(__atomic_xor, "xr") #undef __ATOMIC_OPS #define __ATOMIC64_OP(op_name, op_string) \ -static inline long op_name(long val, long *ptr) \ +static __always_inline long op_name(long val, long *ptr) \ { \ long old, new; \ \ @@ -154,7 +154,7 @@ __ATOMIC64_OPS(__atomic64_xor, "xgr") #endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ -static inline int __atomic_cmpxchg(int *ptr, int old, int new) +static __always_inline int __atomic_cmpxchg(int *ptr, int old, int new) { asm volatile( " cs %[old],%[new],%[ptr]" @@ -164,7 +164,7 @@ static inline int __atomic_cmpxchg(int *ptr, int old, int new) return old; } -static inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) +static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) { int old_expected = old; @@ -176,7 +176,7 @@ static inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new) return old == old_expected; } -static inline long __atomic64_cmpxchg(long *ptr, long old, long new) +static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new) { asm volatile( " csg %[old],%[new],%[ptr]" @@ -186,7 +186,7 @@ static inline long __atomic64_cmpxchg(long *ptr, long old, long new) return old; } -static inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) +static __always_inline bool __atomic64_cmpxchg_bool(long *ptr, long old, long new) { long old_expected = old; diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h index bf15da0fedbc..0e3da500e98c 100644 --- a/arch/s390/include/asm/preempt.h +++ b/arch/s390/include/asm/preempt.h @@ -12,12 +12,12 @@ #define PREEMPT_NEED_RESCHED 0x80000000 #define PREEMPT_ENABLED (0 + PREEMPT_NEED_RESCHED) -static inline int preempt_count(void) +static __always_inline int preempt_count(void) { return READ_ONCE(S390_lowcore.preempt_count) & ~PREEMPT_NEED_RESCHED; } -static inline void preempt_count_set(int pc) +static __always_inline void preempt_count_set(int pc) { int old, new; @@ -29,22 +29,22 @@ static inline void preempt_count_set(int pc) old, new) != old); } -static inline void set_preempt_need_resched(void) +static __always_inline void set_preempt_need_resched(void) { __atomic_and(~PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count); } -static inline void clear_preempt_need_resched(void) +static __always_inline void clear_preempt_need_resched(void) { __atomic_or(PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count); } -static inline bool test_preempt_need_resched(void) +static __always_inline bool test_preempt_need_resched(void) { return !(READ_ONCE(S390_lowcore.preempt_count) & PREEMPT_NEED_RESCHED); } -static inline void __preempt_count_add(int val) +static __always_inline void __preempt_count_add(int val) { /* * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES @@ -59,17 +59,17 @@ static inline void __preempt_count_add(int val) __atomic_add(val, &S390_lowcore.preempt_count); } -static inline void __preempt_count_sub(int val) +static __always_inline void __preempt_count_sub(int val) { __preempt_count_add(-val); } -static inline bool __preempt_count_dec_and_test(void) +static __always_inline bool __preempt_count_dec_and_test(void) { return __atomic_add(-1, &S390_lowcore.preempt_count) == 1; } -static inline bool should_resched(int preempt_offset) +static __always_inline bool should_resched(int preempt_offset) { return unlikely(READ_ONCE(S390_lowcore.preempt_count) == preempt_offset); @@ -79,45 +79,45 @@ static inline bool should_resched(int preempt_offset) #define PREEMPT_ENABLED (0) -static inline int preempt_count(void) +static __always_inline int preempt_count(void) { return READ_ONCE(S390_lowcore.preempt_count); } -static inline void preempt_count_set(int pc) +static __always_inline void preempt_count_set(int pc) { S390_lowcore.preempt_count = pc; } -static inline void set_preempt_need_resched(void) +static __always_inline void set_preempt_need_resched(void) { } -static inline void clear_preempt_need_resched(void) +static __always_inline void clear_preempt_need_resched(void) { } -static inline bool test_preempt_need_resched(void) +static __always_inline bool test_preempt_need_resched(void) { return false; } -static inline void __preempt_count_add(int val) +static __always_inline void __preempt_count_add(int val) { S390_lowcore.preempt_count += val; } -static inline void __preempt_count_sub(int val) +static __always_inline void __preempt_count_sub(int val) { S390_lowcore.preempt_count -= val; } -static inline bool __preempt_count_dec_and_test(void) +static __always_inline bool __preempt_count_dec_and_test(void) { return !--S390_lowcore.preempt_count && tif_need_resched(); } -static inline bool should_resched(int preempt_offset) +static __always_inline bool should_resched(int preempt_offset) { return unlikely(preempt_count() == preempt_offset && tif_need_resched()); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 787394978bc0..6a1e0fbbaa15 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -340,7 +340,8 @@ SYM_CODE_START(pgm_check_handler) mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK stctg %c1,%c1,__PT_CR1(%r11) #if IS_ENABLED(CONFIG_KVM) - lg %r12,__LC_GMAP + ltg %r12,__LC_GMAP + jz 5f clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11) jne 5f BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST @@ -635,6 +636,7 @@ SYM_DATA_START_LOCAL(daton_psw) SYM_DATA_END(daton_psw) .section .rodata, "a" + .balign 8 #define SYSCALL(esame,emu) .quad __s390x_ ## esame SYM_DATA_START(sys_call_table) #include "asm/syscall_table.h" diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c index 823d652e3917..4ad472d130a3 100644 --- a/arch/s390/kernel/perf_pai_crypto.c +++ b/arch/s390/kernel/perf_pai_crypto.c @@ -90,7 +90,6 @@ static void paicrypt_event_destroy(struct perf_event *event) event->cpu); struct paicrypt_map *cpump = mp->mapptr; - cpump->event = NULL; static_branch_dec(&pai_key); mutex_lock(&pai_reserve_mutex); debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d users %d" @@ -356,10 +355,15 @@ static int paicrypt_add(struct perf_event *event, int flags) static void paicrypt_stop(struct perf_event *event, int flags) { - if (!event->attr.sample_period) /* Counting */ + struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr); + struct paicrypt_map *cpump = mp->mapptr; + + if (!event->attr.sample_period) { /* Counting */ paicrypt_read(event); - else /* Sampling */ + } else { /* Sampling */ perf_sched_cb_dec(event->pmu); + cpump->event = NULL; + } event->hw.state = PERF_HES_STOPPED; } diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c index 616a25606cd6..a6da7e0cc7a6 100644 --- a/arch/s390/kernel/perf_pai_ext.c +++ b/arch/s390/kernel/perf_pai_ext.c @@ -122,7 +122,6 @@ static void paiext_event_destroy(struct perf_event *event) free_page(PAI_SAVE_AREA(event)); mutex_lock(&paiext_reserve_mutex); - cpump->event = NULL; if (refcount_dec_and_test(&cpump->refcnt)) /* Last reference gone */ paiext_free(mp); paiext_root_free(); @@ -362,10 +361,15 @@ static int paiext_add(struct perf_event *event, int flags) static void paiext_stop(struct perf_event *event, int flags) { - if (!event->attr.sample_period) /* Counting */ + struct paiext_mapptr *mp = this_cpu_ptr(paiext_root.mapptr); + struct paiext_map *cpump = mp->mapptr; + + if (!event->attr.sample_period) { /* Counting */ paiext_read(event); - else /* Sampling */ + } else { /* Sampling */ perf_sched_cb_dec(event->pmu); + cpump->event = NULL; + } event->hw.state = PERF_HES_STOPPED; } diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index c421dd44ffbe..0c66b32e0f9f 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -75,7 +75,7 @@ static enum fault_type get_fault_type(struct pt_regs *regs) if (!IS_ENABLED(CONFIG_PGSTE)) return KERNEL_FAULT; gmap = (struct gmap *)S390_lowcore.gmap; - if (regs->cr1 == gmap->asce) + if (gmap && gmap->asce == regs->cr1) return GMAP_FAULT; return KERNEL_FAULT; } diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4fff6ed46e90..928820e61cb5 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -62,6 +62,7 @@ config X86 select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU select ARCH_32BIT_OFF_T if X86_32 select ARCH_CLOCKSOURCE_INIT + select ARCH_CONFIGURES_CPU_MITIGATIONS select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64 @@ -2488,17 +2489,21 @@ config PREFIX_SYMBOLS def_bool y depends on CALL_PADDING && !CFI_CLANG -menuconfig SPECULATION_MITIGATIONS - bool "Mitigations for speculative execution vulnerabilities" +menuconfig CPU_MITIGATIONS + bool "Mitigations for CPU vulnerabilities" default y help - Say Y here to enable options which enable mitigations for - speculative execution hardware vulnerabilities. + Say Y here to enable options which enable mitigations for hardware + vulnerabilities (usually related to speculative execution). + Mitigations can be disabled or restricted to SMT systems at runtime + via the "mitigations" kernel parameter. - If you say N, all mitigations will be disabled. You really - should know what you are doing to say so. + If you say N, all mitigations will be disabled. This CANNOT be + overridden at runtime. -if SPECULATION_MITIGATIONS + Say 'Y', unless you really know what you are doing. + +if CPU_MITIGATIONS config MITIGATION_PAGE_TABLE_ISOLATION bool "Remove the kernel mapping in user mode" @@ -2633,6 +2638,16 @@ config MITIGATION_RFDS stored in floating point, vector and integer registers. See also +config MITIGATION_SPECTRE_BHI + bool "Mitigate Spectre-BHB (Branch History Injection)" + depends on CPU_SUP_INTEL + default y + help + Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks + where the branch history buffer is poisoned to speculatively steer + indirect branches. + See + endif config ARCH_HAS_ADD_PAGES diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c index d07be9d05cd0..b31ef2424d19 100644 --- a/arch/x86/coco/core.c +++ b/arch/x86/coco/core.c @@ -3,19 +3,28 @@ * Confidential Computing Platform Capability checks * * Copyright (C) 2021 Advanced Micro Devices, Inc. + * Copyright (C) 2024 Jason A. Donenfeld . All Rights Reserved. * * Author: Tom Lendacky */ #include #include +#include +#include +#include #include #include enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE; u64 cc_mask __ro_after_init; +static struct cc_attr_flags { + __u64 host_sev_snp : 1, + __resv : 63; +} cc_flags; + static bool noinstr intel_cc_platform_has(enum cc_attr attr) { switch (attr) { @@ -89,6 +98,9 @@ static bool noinstr amd_cc_platform_has(enum cc_attr attr) case CC_ATTR_GUEST_SEV_SNP: return sev_status & MSR_AMD64_SEV_SNP_ENABLED; + case CC_ATTR_HOST_SEV_SNP: + return cc_flags.host_sev_snp; + default: return false; } @@ -148,3 +160,84 @@ u64 cc_mkdec(u64 val) } } EXPORT_SYMBOL_GPL(cc_mkdec); + +static void amd_cc_platform_clear(enum cc_attr attr) +{ + switch (attr) { + case CC_ATTR_HOST_SEV_SNP: + cc_flags.host_sev_snp = 0; + break; + default: + break; + } +} + +void cc_platform_clear(enum cc_attr attr) +{ + switch (cc_vendor) { + case CC_VENDOR_AMD: + amd_cc_platform_clear(attr); + break; + default: + break; + } +} + +static void amd_cc_platform_set(enum cc_attr attr) +{ + switch (attr) { + case CC_ATTR_HOST_SEV_SNP: + cc_flags.host_sev_snp = 1; + break; + default: + break; + } +} + +void cc_platform_set(enum cc_attr attr) +{ + switch (cc_vendor) { + case CC_VENDOR_AMD: + amd_cc_platform_set(attr); + break; + default: + break; + } +} + +__init void cc_random_init(void) +{ + /* + * The seed is 32 bytes (in units of longs), which is 256 bits, which + * is the security level that the RNG is targeting. + */ + unsigned long rng_seed[32 / sizeof(long)]; + size_t i, longs; + + if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) + return; + + /* + * Since the CoCo threat model includes the host, the only reliable + * source of entropy that can be neither observed nor manipulated is + * RDRAND. Usually, RDRAND failure is considered tolerable, but since + * CoCo guests have no other unobservable source of entropy, it's + * important to at least ensure the RNG gets some initial random seeds. + */ + for (i = 0; i < ARRAY_SIZE(rng_seed); i += longs) { + longs = arch_get_random_longs(&rng_seed[i], ARRAY_SIZE(rng_seed) - i); + + /* + * A zero return value means that the guest doesn't have RDRAND + * or the CPU is physically broken, and in both cases that + * means most crypto inside of the CoCo instance will be + * broken, defeating the purpose of CoCo in the first place. So + * just panic here because it's absolutely unsafe to continue + * executing. + */ + if (longs == 0) + panic("RDRAND is defective."); + } + add_device_randomness(rng_seed, sizeof(rng_seed)); + memzero_explicit(rng_seed, sizeof(rng_seed)); +} diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 6356060caaf3..51cc9c7cb9bd 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -49,7 +49,7 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) if (likely(unr < NR_syscalls)) { unr = array_index_nospec(unr, NR_syscalls); - regs->ax = sys_call_table[unr](regs); + regs->ax = x64_sys_call(regs, unr); return true; } return false; @@ -66,7 +66,7 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr) if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) { xnr = array_index_nospec(xnr, X32_NR_syscalls); - regs->ax = x32_sys_call_table[xnr](regs); + regs->ax = x32_sys_call(regs, xnr); return true; } return false; @@ -162,7 +162,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr) if (likely(unr < IA32_NR_syscalls)) { unr = array_index_nospec(unr, IA32_NR_syscalls); - regs->ax = ia32_sys_call_table[unr](regs); + regs->ax = ia32_sys_call(regs, unr); } else if (nr != -1) { regs->ax = __ia32_sys_ni_syscall(regs); } @@ -189,7 +189,7 @@ static __always_inline bool int80_is_external(void) } /** - * int80_emulation - 32-bit legacy syscall entry + * do_int80_emulation - 32-bit legacy syscall C entry from asm * * This entry point can be used by 32-bit and 64-bit programs to perform * 32-bit system calls. Instances of INT $0x80 can be found inline in @@ -207,7 +207,7 @@ static __always_inline bool int80_is_external(void) * eax: system call number * ebx, ecx, edx, esi, edi, ebp: arg1 - arg 6 */ -DEFINE_IDTENTRY_RAW(int80_emulation) +__visible noinstr void do_int80_emulation(struct pt_regs *regs) { int nr; @@ -255,6 +255,71 @@ DEFINE_IDTENTRY_RAW(int80_emulation) instrumentation_end(); syscall_exit_to_user_mode(regs); } + +#ifdef CONFIG_X86_FRED +/* + * A FRED-specific INT80 handler is warranted for the follwing reasons: + * + * 1) As INT instructions and hardware interrupts are separate event + * types, FRED does not preclude the use of vector 0x80 for external + * interrupts. As a result, the FRED setup code does not reserve + * vector 0x80 and calling int80_is_external() is not merely + * suboptimal but actively incorrect: it could cause a system call + * to be incorrectly ignored. + * + * 2) It is called only for handling vector 0x80 of event type + * EVENT_TYPE_SWINT and will never be called to handle any external + * interrupt (event type EVENT_TYPE_EXTINT). + * + * 3) FRED has separate entry flows depending on if the event came from + * user space or kernel space, and because the kernel does not use + * INT insns, the FRED kernel entry handler fred_entry_from_kernel() + * falls through to fred_bad_type() if the event type is + * EVENT_TYPE_SWINT, i.e., INT insns. So if the kernel is handling + * an INT insn, it can only be from a user level. + * + * 4) int80_emulation() does a CLEAR_BRANCH_HISTORY. While FRED will + * likely take a different approach if it is ever needed: it + * probably belongs in either fred_intx()/ fred_other() or + * asm_fred_entrypoint_user(), depending on if this ought to be done + * for all entries from userspace or only system + * calls. + * + * 5) INT $0x80 is the fast path for 32-bit system calls under FRED. + */ +DEFINE_FREDENTRY_RAW(int80_emulation) +{ + int nr; + + enter_from_user_mode(regs); + + instrumentation_begin(); + add_random_kstack_offset(); + + /* + * FRED pushed 0 into regs::orig_ax and regs::ax contains the + * syscall number. + * + * User tracing code (ptrace or signal handlers) might assume + * that the regs::orig_ax contains a 32-bit number on invoking + * a 32-bit syscall. + * + * Establish the syscall convention by saving the 32bit truncated + * syscall number in regs::orig_ax and by invalidating regs::ax. + */ + regs->orig_ax = regs->ax & GENMASK(31, 0); + regs->ax = -ENOSYS; + + nr = syscall_32_enter(regs); + + local_irq_enable(); + nr = syscall_enter_from_user_mode_work(regs, nr); + do_syscall_32_irqs_on(regs, nr); + + instrumentation_end(); + syscall_exit_to_user_mode(regs); +} +#endif #else /* CONFIG_IA32_EMULATION */ /* Handles int $0x80 on a 32bit kernel */ diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 8af2a26b24f6..1b5be07f8669 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -116,6 +116,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL) /* clobbers %rax, make sure it is after saving the syscall nr */ IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY call do_syscall_64 /* returns with IRQs disabled */ @@ -1491,3 +1492,63 @@ SYM_CODE_START_NOALIGN(rewind_stack_and_make_dead) call make_task_dead SYM_CODE_END(rewind_stack_and_make_dead) .popsection + +/* + * This sequence executes branches in order to remove user branch information + * from the branch history tracker in the Branch Predictor, therefore removing + * user influence on subsequent BTB lookups. + * + * It should be used on parts prior to Alder Lake. Newer parts should use the + * BHI_DIS_S hardware control instead. If a pre-Alder Lake part is being + * virtualized on newer hardware the VMM should protect against BHI attacks by + * setting BHI_DIS_S for the guests. + * + * CALLs/RETs are necessary to prevent Loop Stream Detector(LSD) from engaging + * and not clearing the branch history. The call tree looks like: + * + * call 1 + * call 2 + * call 2 + * call 2 + * call 2 + * call 2 + * ret + * ret + * ret + * ret + * ret + * ret + * + * This means that the stack is non-constant and ORC can't unwind it with %rsp + * alone. Therefore we unconditionally set up the frame pointer, which allows + * ORC to unwind properly. + * + * The alignment is for performance and not for safety, and may be safely + * refactored in the future if needed. + */ +SYM_FUNC_START(clear_bhb_loop) + push %rbp + mov %rsp, %rbp + movl $5, %ecx + ANNOTATE_INTRA_FUNCTION_CALL + call 1f + jmp 5f + .align 64, 0xcc + ANNOTATE_INTRA_FUNCTION_CALL +1: call 2f + RET + .align 64, 0xcc +2: movl $5, %eax +3: jmp 4f + nop +4: sub $1, %eax + jnz 3b + sub $1, %ecx + jnz 1b + RET +5: lfence + pop %rbp + RET +SYM_FUNC_END(clear_bhb_loop) +EXPORT_SYMBOL_GPL(clear_bhb_loop) +STACK_FRAME_NON_STANDARD(clear_bhb_loop) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index eabf48c4d4b4..c779046cc3fe 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -92,6 +92,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL) IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY /* * SYSENTER doesn't filter flags, so we need to clear NT and AC @@ -206,6 +207,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL) IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY movq %rsp, %rdi call do_fast_syscall_32 @@ -276,3 +278,17 @@ SYM_INNER_LABEL(entry_SYSRETL_compat_end, SYM_L_GLOBAL) ANNOTATE_NOENDBR int3 SYM_CODE_END(entry_SYSCALL_compat) + +/* + * int 0x80 is used by 32 bit mode as a system call entry. Normally idt entries + * point to C routines, however since this is a system call interface the branch + * history needs to be scrubbed to protect against BHI attacks, and that + * scrubbing needs to take place in assembly code prior to entering any C + * routines. + */ +SYM_CODE_START(int80_emulation) + ANNOTATE_NOENDBR + UNWIND_HINT_FUNC + CLEAR_BRANCH_HISTORY + jmp do_int80_emulation +SYM_CODE_END(int80_emulation) diff --git a/arch/x86/entry/entry_fred.c b/arch/x86/entry/entry_fred.c index ac120cbdaaf2..89c1476fcdd9 100644 --- a/arch/x86/entry/entry_fred.c +++ b/arch/x86/entry/entry_fred.c @@ -28,9 +28,9 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code if (regs->fred_cs.sl > 0) { pr_emerg("PANIC: invalid or fatal FRED event; event type %u " "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n", - regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax, + regs->fred_ss.type, regs->fred_ss.vector, error_code, fred_event_data(regs), regs->cs, regs->ip); - die("invalid or fatal FRED event", regs, regs->orig_ax); + die("invalid or fatal FRED event", regs, error_code); panic("invalid or fatal FRED event"); } else { unsigned long flags = oops_begin(); @@ -38,10 +38,10 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code pr_alert("BUG: invalid or fatal FRED event; event type %u " "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n", - regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax, + regs->fred_ss.type, regs->fred_ss.vector, error_code, fred_event_data(regs), regs->cs, regs->ip); - if (__die("Invalid or fatal FRED event", regs, regs->orig_ax)) + if (__die("Invalid or fatal FRED event", regs, error_code)) sig = 0; oops_end(flags, regs, sig); @@ -66,7 +66,7 @@ static noinstr void fred_intx(struct pt_regs *regs) /* INT80 */ case IA32_SYSCALL_VECTOR: if (ia32_enabled()) - return int80_emulation(regs); + return fred_int80_emulation(regs); fallthrough; #endif diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c index 8cfc9bc73e7f..c2235bae17ef 100644 --- a/arch/x86/entry/syscall_32.c +++ b/arch/x86/entry/syscall_32.c @@ -18,8 +18,25 @@ #include #undef __SYSCALL +/* + * The sys_call_table[] is no longer used for system calls, but + * kernel/trace/trace_syscalls.c still wants to know the system + * call address. + */ +#ifdef CONFIG_X86_32 #define __SYSCALL(nr, sym) __ia32_##sym, - -__visible const sys_call_ptr_t ia32_sys_call_table[] = { +const sys_call_ptr_t sys_call_table[] = { #include }; +#undef __SYSCALL +#endif + +#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs); + +long ia32_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __ia32_sys_ni_syscall(regs); + } +}; diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index be120eec1fc9..33b3f09e6f15 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -11,8 +11,23 @@ #include #undef __SYSCALL +/* + * The sys_call_table[] is no longer used for system calls, but + * kernel/trace/trace_syscalls.c still wants to know the system + * call address. + */ #define __SYSCALL(nr, sym) __x64_##sym, - -asmlinkage const sys_call_ptr_t sys_call_table[] = { +const sys_call_ptr_t sys_call_table[] = { #include }; +#undef __SYSCALL + +#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs); + +long x64_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __x64_sys_ni_syscall(regs); + } +}; diff --git a/arch/x86/entry/syscall_x32.c b/arch/x86/entry/syscall_x32.c index bdd0e03a1265..03de4a932131 100644 --- a/arch/x86/entry/syscall_x32.c +++ b/arch/x86/entry/syscall_x32.c @@ -11,8 +11,12 @@ #include #undef __SYSCALL -#define __SYSCALL(nr, sym) __x64_##sym, +#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs); -asmlinkage const sys_call_ptr_t x32_sys_call_table[] = { -#include +long x32_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __x64_sys_ni_syscall(regs); + } }; diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 09050641ce5d..5b0dd07b1ef1 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1644,6 +1644,7 @@ static void x86_pmu_del(struct perf_event *event, int flags) while (++i < cpuc->n_events) { cpuc->event_list[i-1] = cpuc->event_list[i]; cpuc->event_constraint[i-1] = cpuc->event_constraint[i]; + cpuc->assign[i-1] = cpuc->assign[i]; } cpuc->event_constraint[i-1] = NULL; --cpuc->n_events; diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 2641ba620f12..e010bfed8417 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1237,11 +1237,11 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc, struct pmu *pmu = event->pmu; /* - * Make sure we get updated with the first PEBS - * event. It will trigger also during removal, but - * that does not hurt: + * Make sure we get updated with the first PEBS event. + * During removal, ->pebs_data_cfg is still valid for + * the last PEBS event. Don't clear it. */ - if (cpuc->n_pebs == 1) + if ((cpuc->n_pebs == 1) && add) cpuc->pebs_data_cfg = PEBS_UPDATE_DS_SW; if (needed_cb != pebs_needs_sched_cb(cpuc)) { diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 78cd5084104e..4367aa77cb8d 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1693,6 +1693,7 @@ void x86_perf_get_lbr(struct x86_pmu_lbr *lbr) lbr->from = x86_pmu.lbr_from; lbr->to = x86_pmu.lbr_to; lbr->info = x86_pmu.lbr_info; + lbr->has_callstack = x86_pmu_has_lbr_callstack(); } EXPORT_SYMBOL_GPL(x86_perf_get_lbr); diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 5fc45543e955..0569f579338b 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -105,7 +105,7 @@ static bool cpu_is_self(int cpu) * IPI implementation on Hyper-V. */ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, - bool exclude_self) + bool exclude_self) { struct hv_send_ipi_ex *ipi_arg; unsigned long flags; @@ -132,8 +132,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) { ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; - nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask, - exclude_self ? cpu_is_self : NULL); + nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask, + exclude_self ? cpu_is_self : NULL); /* * 'nr_bank <= 0' means some CPUs in cpumask can't be @@ -147,7 +147,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, } status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank, - ipi_arg, NULL); + ipi_arg, NULL); ipi_mask_ex_done: local_irq_restore(flags); @@ -155,7 +155,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, } static bool __send_ipi_mask(const struct cpumask *mask, int vector, - bool exclude_self) + bool exclude_self) { int cur_cpu, vcpu, this_cpu = smp_processor_id(); struct hv_send_ipi ipi_arg; @@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector, return false; } - if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR) return false; /* @@ -218,7 +218,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector, } status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector, - ipi_arg.cpu_mask); + ipi_arg.cpu_mask); return hv_result_success(status); do_ex_hypercall: @@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector) return false; } - if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR) return false; if (vp >= 64) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 68a0843d4750..3fa1f2ee7b0d 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -116,12 +115,11 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { - struct hv_add_logical_processor_in *input; - struct hv_add_logical_processor_out *output; + struct hv_input_add_logical_processor *input; + struct hv_output_add_logical_processor *output; u64 status; unsigned long flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* * When adding a logical processor, the hypervisor may return @@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) input->lp_index = lp_index; input->apic_id = apic_id; - input->flags = 0; - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, input, output); local_irq_restore(flags); @@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) u64 status; unsigned long irq_flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* Root VPs don't seem to need pages deposited */ if (partition_id != hv_current_partition_id) { @@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) input->vp_index = vp_index; input->flags = flags; input->subnode_type = HvSubnodeAny; - if (node != NUMA_NO_NODE) { - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; - } else { - input->proximity_domain_info.as_uint64 = 0; - } + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); local_irq_restore(irq_flags); diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index fcd20c6dc7f9..67b68d0d17d1 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -117,7 +117,7 @@ extern void callthunks_patch_builtin_calls(void); extern void callthunks_patch_module_calls(struct callthunk_sites *sites, struct module *mod); extern void *callthunks_translate_call_dest(void *dest); -extern int x86_call_depth_emit_accounting(u8 **pprog, void *func); +extern int x86_call_depth_emit_accounting(u8 **pprog, void *func, void *ip); #else static __always_inline void callthunks_patch_builtin_calls(void) {} static __always_inline void @@ -128,7 +128,7 @@ static __always_inline void *callthunks_translate_call_dest(void *dest) return dest; } static __always_inline int x86_call_depth_emit_accounting(u8 **pprog, - void *func) + void *func, void *ip) { return 0; } diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 94ce0f7c9d3a..e6ab0cf15ed5 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -13,6 +13,7 @@ #include #include #include +#include #define ARCH_APICTIMER_STOPS_ON_C3 1 @@ -98,7 +99,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v) static inline u32 native_apic_mem_read(u32 reg) { - return *((volatile u32 *)(APIC_BASE + reg)); + return readl((void __iomem *)(APIC_BASE + reg)); } static inline void native_apic_mem_eoi(void) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index fe1e7e3cc844..63bdc6b85219 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -79,6 +79,9 @@ do { \ #define __smp_mb__before_atomic() do { } while (0) #define __smp_mb__after_atomic() do { } while (0) +/* Writing to CR3 provides a full memory barrier in switch_mm(). */ +#define smp_mb__after_switch_mm() do { } while (0) + #include #endif /* _ASM_X86_BARRIER_H */ diff --git a/arch/x86/include/asm/coco.h b/arch/x86/include/asm/coco.h index fb7388bbc212..aa6c8f8ca958 100644 --- a/arch/x86/include/asm/coco.h +++ b/arch/x86/include/asm/coco.h @@ -22,8 +22,10 @@ static inline void cc_set_mask(u64 mask) u64 cc_mkenc(u64 val); u64 cc_mkdec(u64 val); +void cc_random_init(void); #else #define cc_vendor (CC_VENDOR_NONE) +static const u64 cc_mask = 0; static inline u64 cc_mkenc(u64 val) { @@ -34,6 +36,7 @@ static inline u64 cc_mkdec(u64 val) { return val; } +static inline void cc_random_init(void) { } #endif #endif /* _ASM_X86_COCO_H */ diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 42157ddcc09d..686e92d2663e 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -33,6 +33,8 @@ enum cpuid_leafs CPUID_7_EDX, CPUID_8000_001F_EAX, CPUID_8000_0021_EAX, + CPUID_LNX_5, + NR_CPUID_WORDS, }; #define X86_CAP_FMT_NUM "%d:%d" diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index a38f8f9ba657..3c7434329661 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -461,11 +461,15 @@ /* * Extended auxiliary flags: Linux defined - for features scattered in various - * CPUID levels like 0x80000022, etc. + * CPUID levels like 0x80000022, etc and Linux defined features. * * Reuse free bits when adding new feature flags! */ #define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ +#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ +#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ +#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ +#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */ /* * BUG word(s) @@ -515,4 +519,5 @@ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ +#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 16e07a2eee19..6efd1497b026 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -855,6 +855,7 @@ struct kvm_vcpu_arch { int cpuid_nent; struct kvm_cpuid_entry2 *cpuid_entries; struct kvm_hypervisor_cpuid kvm_cpuid; + bool is_amd_compatible; /* * FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 05956bd8bacf..e72c2b872957 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -61,10 +61,13 @@ #define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */ #define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */ #define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT) +#define SPEC_CTRL_BHI_DIS_S_SHIFT 10 /* Disable Branch History Injection behavior */ +#define SPEC_CTRL_BHI_DIS_S BIT(SPEC_CTRL_BHI_DIS_S_SHIFT) /* A mask for bits which the kernel toggles when controlling mitigations */ #define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \ - | SPEC_CTRL_RRSBA_DIS_S) + | SPEC_CTRL_RRSBA_DIS_S \ + | SPEC_CTRL_BHI_DIS_S) #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ @@ -163,6 +166,10 @@ * are restricted to targets in * kernel. */ +#define ARCH_CAP_BHI_NO BIT(20) /* + * CPU is not affected by Branch + * History Injection. + */ #define ARCH_CAP_PBRSB_NO BIT(24) /* * Not susceptible to Post-Barrier * Return Stack Buffer Predictions. diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 170c89ed22fc..ff5f1ecc7d1e 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -326,6 +326,19 @@ ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF .endm +#ifdef CONFIG_X86_64 +.macro CLEAR_BRANCH_HISTORY + ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP +.endm + +.macro CLEAR_BRANCH_HISTORY_VMEXIT + ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT +.endm +#else +#define CLEAR_BRANCH_HISTORY +#define CLEAR_BRANCH_HISTORY_VMEXIT +#endif + #else /* __ASSEMBLY__ */ #define ANNOTATE_RETPOLINE_SAFE \ @@ -368,6 +381,10 @@ extern void srso_alias_return_thunk(void); extern void entry_untrain_ret(void); extern void entry_ibpb(void); +#ifdef CONFIG_X86_64 +extern void clear_bhb_loop(void); +#endif + extern void (*x86_return_thunk)(void); extern void __warn_thunk(void); diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 3736b8a46c04..7f1e17250546 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -555,6 +555,7 @@ struct x86_pmu_lbr { unsigned int from; unsigned int to; unsigned int info; + bool has_callstack; }; extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap); diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 0b748ee16b3d..9abb8cc4cd47 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -148,7 +148,7 @@ #define _COMMON_PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \ _PAGE_SPECIAL | _PAGE_ACCESSED | \ _PAGE_DIRTY_BITS | _PAGE_SOFT_DIRTY | \ - _PAGE_DEVMAP | _PAGE_ENC | _PAGE_UFFD_WP) + _PAGE_DEVMAP | _PAGE_CC | _PAGE_UFFD_WP) #define _PAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PAT) #define _HPAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PSE | _PAGE_PAT_LARGE) @@ -173,6 +173,7 @@ enum page_cache_mode { }; #endif +#define _PAGE_CC (_AT(pteval_t, cc_mask)) #define _PAGE_ENC (_AT(pteval_t, sme_me_mask)) #define _PAGE_CACHE_MASK (_PAGE_PWT | _PAGE_PCD | _PAGE_PAT) diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 07e125f32528..7f57382afee4 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -228,7 +228,6 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct sn void snp_accept_memory(phys_addr_t start, phys_addr_t end); u64 snp_get_unsupported_features(u64 status); u64 sev_get_status(void); -void kdump_sev_callback(void); void sev_show_status(void); #else static inline void sev_es_ist_enter(struct pt_regs *regs) { } @@ -258,7 +257,6 @@ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *in static inline void snp_accept_memory(phys_addr_t start, phys_addr_t end) { } static inline u64 snp_get_unsupported_features(u64 status) { return 0; } static inline u64 sev_get_status(void) { return 0; } -static inline void kdump_sev_callback(void) { } static inline void sev_show_status(void) { } #endif @@ -270,6 +268,7 @@ int psmash(u64 pfn); int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 asid, bool immutable); int rmp_make_shared(u64 pfn, enum pg_level level); void snp_leak_pages(u64 pfn, unsigned int npages); +void kdump_sev_callback(void); #else static inline bool snp_probe_rmptable_info(void) { return false; } static inline int snp_lookup_rmpentry(u64 pfn, bool *assigned, int *level) { return -ENODEV; } @@ -282,6 +281,7 @@ static inline int rmp_make_private(u64 pfn, u64 gpa, enum pg_level level, u32 as } static inline int rmp_make_shared(u64 pfn, enum pg_level level) { return -ENODEV; } static inline void snp_leak_pages(u64 pfn, unsigned int npages) {} +static inline void kdump_sev_callback(void) { } #endif #endif diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index f44e2f9ab65d..2fc7bc3863ff 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -16,19 +16,17 @@ #include /* for TS_COMPAT */ #include +/* This is used purely for kernel/trace/trace_syscalls.c */ typedef long (*sys_call_ptr_t)(const struct pt_regs *); extern const sys_call_ptr_t sys_call_table[]; -#if defined(CONFIG_X86_32) -#define ia32_sys_call_table sys_call_table -#else /* * These may not exist, but still put the prototypes in so we * can use IS_ENABLED(). */ -extern const sys_call_ptr_t ia32_sys_call_table[]; -extern const sys_call_ptr_t x32_sys_call_table[]; -#endif +extern long ia32_sys_call(const struct pt_regs *, unsigned int nr); +extern long x32_sys_call(const struct pt_regs *, unsigned int nr); +extern long x64_sys_call(const struct pt_regs *, unsigned int nr); /* * Only the low 32 bits of orig_ax are meaningful, so we return int. @@ -127,6 +125,7 @@ static inline int syscall_get_arch(struct task_struct *task) } bool do_syscall_64(struct pt_regs *regs, int nr); +void do_int80_emulation(struct pt_regs *regs); #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index ad29984d5e39..ef11aa4cab42 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -694,6 +694,7 @@ enum sev_cmd_id { struct kvm_sev_cmd { __u32 id; + __u32 pad0; __u64 data; __u32 error; __u32 sev_fd; @@ -704,28 +705,35 @@ struct kvm_sev_launch_start { __u32 policy; __u64 dh_uaddr; __u32 dh_len; + __u32 pad0; __u64 session_uaddr; __u32 session_len; + __u32 pad1; }; struct kvm_sev_launch_update_data { __u64 uaddr; __u32 len; + __u32 pad0; }; struct kvm_sev_launch_secret { __u64 hdr_uaddr; __u32 hdr_len; + __u32 pad0; __u64 guest_uaddr; __u32 guest_len; + __u32 pad1; __u64 trans_uaddr; __u32 trans_len; + __u32 pad2; }; struct kvm_sev_launch_measure { __u64 uaddr; __u32 len; + __u32 pad0; }; struct kvm_sev_guest_status { @@ -738,33 +746,43 @@ struct kvm_sev_dbg { __u64 src_uaddr; __u64 dst_uaddr; __u32 len; + __u32 pad0; }; struct kvm_sev_attestation_report { __u8 mnonce[16]; __u64 uaddr; __u32 len; + __u32 pad0; }; struct kvm_sev_send_start { __u32 policy; + __u32 pad0; __u64 pdh_cert_uaddr; __u32 pdh_cert_len; + __u32 pad1; __u64 plat_certs_uaddr; __u32 plat_certs_len; + __u32 pad2; __u64 amd_certs_uaddr; __u32 amd_certs_len; + __u32 pad3; __u64 session_uaddr; __u32 session_len; + __u32 pad4; }; struct kvm_sev_send_update_data { __u64 hdr_uaddr; __u32 hdr_len; + __u32 pad0; __u64 guest_uaddr; __u32 guest_len; + __u32 pad1; __u64 trans_uaddr; __u32 trans_len; + __u32 pad2; }; struct kvm_sev_receive_start { @@ -772,17 +790,22 @@ struct kvm_sev_receive_start { __u32 policy; __u64 pdh_uaddr; __u32 pdh_len; + __u32 pad0; __u64 session_uaddr; __u32 session_len; + __u32 pad1; }; struct kvm_sev_receive_update_data { __u64 hdr_uaddr; __u32 hdr_len; + __u32 pad0; __u64 guest_uaddr; __u32 guest_len; + __u32 pad1; __u64 trans_uaddr; __u32 trans_len; + __u32 pad2; }; #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h index 6bc3456a8ebf..a1efa7907a0b 100644 --- a/arch/x86/include/uapi/asm/kvm_para.h +++ b/arch/x86/include/uapi/asm/kvm_para.h @@ -142,7 +142,6 @@ struct kvm_vcpu_pv_apf_data { __u32 token; __u8 pad[56]; - __u32 enabled; }; #define KVM_PV_EOI_BIT 0 diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a42d8a6f7149..c342c4aa9c68 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1687,11 +1687,11 @@ static int x2apic_state; static bool x2apic_hw_locked(void) { - u64 ia32_cap; + u64 x86_arch_cap_msr; u64 msr; - ia32_cap = x86_read_arch_cap_msr(); - if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) { + x86_arch_cap_msr = x86_read_arch_cap_msr(); + if (x86_arch_cap_msr & ARCH_CAP_XAPIC_DISABLE) { rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr); return (msr & LEGACY_XAPIC_DISABLED); } diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c index 30335182b6b0..e92ff0c11db8 100644 --- a/arch/x86/kernel/callthunks.c +++ b/arch/x86/kernel/callthunks.c @@ -314,7 +314,7 @@ static bool is_callthunk(void *addr) return !bcmp(pad, insn_buff, tmpl_size); } -int x86_call_depth_emit_accounting(u8 **pprog, void *func) +int x86_call_depth_emit_accounting(u8 **pprog, void *func, void *ip) { unsigned int tmpl_size = SKL_TMPL_SIZE; u8 insn_buff[MAX_PATCH_LEN]; @@ -327,7 +327,7 @@ int x86_call_depth_emit_accounting(u8 **pprog, void *func) return 0; memcpy(insn_buff, skl_call_thunk_template, tmpl_size); - apply_relocation(insn_buff, tmpl_size, *pprog, + apply_relocation(insn_buff, tmpl_size, ip, skl_call_thunk_template, tmpl_size); memcpy(*pprog, insn_buff, tmpl_size); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 6d8677e80ddb..307302af0aee 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -345,6 +345,28 @@ static void srat_detect_node(struct cpuinfo_x86 *c) #endif } +static void bsp_determine_snp(struct cpuinfo_x86 *c) +{ +#ifdef CONFIG_ARCH_HAS_CC_PLATFORM + cc_vendor = CC_VENDOR_AMD; + + if (cpu_has(c, X86_FEATURE_SEV_SNP)) { + /* + * RMP table entry format is not architectural and is defined by the + * per-processor PPR. Restrict SNP support on the known CPU models + * for which the RMP table entry format is currently defined for. + */ + if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && + c->x86 >= 0x19 && snp_probe_rmptable_info()) { + cc_platform_set(CC_ATTR_HOST_SEV_SNP); + } else { + setup_clear_cpu_cap(X86_FEATURE_SEV_SNP); + cc_platform_clear(CC_ATTR_HOST_SEV_SNP); + } + } +#endif +} + static void bsp_init_amd(struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { @@ -437,8 +459,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) case 0x1a: switch (c->x86_model) { - case 0x00 ... 0x0f: - case 0x20 ... 0x2f: + case 0x00 ... 0x2f: case 0x40 ... 0x4f: case 0x70 ... 0x7f: setup_force_cpu_cap(X86_FEATURE_ZEN5); @@ -452,21 +473,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) break; } - if (cpu_has(c, X86_FEATURE_SEV_SNP)) { - /* - * RMP table entry format is not architectural and it can vary by processor - * and is defined by the per-processor PPR. Restrict SNP support on the - * known CPU model and family for which the RMP table entry format is - * currently defined for. - */ - if (!boot_cpu_has(X86_FEATURE_ZEN3) && - !boot_cpu_has(X86_FEATURE_ZEN4) && - !boot_cpu_has(X86_FEATURE_ZEN5)) - setup_clear_cpu_cap(X86_FEATURE_SEV_SNP); - else if (!snp_probe_rmptable_info()) - setup_clear_cpu_cap(X86_FEATURE_SEV_SNP); - } - + bsp_determine_snp(c); return; warn: @@ -527,7 +534,6 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c) static void early_init_amd(struct cpuinfo_x86 *c) { - u64 value; u32 dummy; if (c->x86 >= 0xf) @@ -595,20 +601,6 @@ static void early_init_amd(struct cpuinfo_x86 *c) early_detect_mem_encrypt(c); - /* Re-enable TopologyExtensions if switched off by BIOS */ - if (c->x86 == 0x15 && - (c->x86_model >= 0x10 && c->x86_model <= 0x6f) && - !cpu_has(c, X86_FEATURE_TOPOEXT)) { - - if (msr_set_bit(0xc0011005, 54) > 0) { - rdmsrl(0xc0011005, value); - if (value & BIT_64(54)) { - set_cpu_cap(c, X86_FEATURE_TOPOEXT); - pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); - } - } - } - if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) { if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB)) setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index e7ba936d798b..ab18185894df 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -61,6 +61,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current); u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; EXPORT_SYMBOL_GPL(x86_pred_cmd); +static u64 __ro_after_init x86_arch_cap_msr; + static DEFINE_MUTEX(spec_ctrl_mutex); void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk; @@ -144,6 +146,8 @@ void __init cpu_select_mitigations(void) x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK; } + x86_arch_cap_msr = x86_read_arch_cap_msr(); + /* Select the proper CPU mitigations before patching alternatives: */ spectre_v1_select_mitigation(); spectre_v2_select_mitigation(); @@ -301,8 +305,6 @@ static const char * const taa_strings[] = { static void __init taa_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_TAA)) { taa_mitigation = TAA_MITIGATION_OFF; return; @@ -341,9 +343,8 @@ static void __init taa_select_mitigation(void) * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode * update is required. */ - ia32_cap = x86_read_arch_cap_msr(); - if ( (ia32_cap & ARCH_CAP_MDS_NO) && - !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR)) + if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) && + !(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)) taa_mitigation = TAA_MITIGATION_UCODE_NEEDED; /* @@ -401,8 +402,6 @@ static const char * const mmio_strings[] = { static void __init mmio_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) || boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) || cpu_mitigations_off()) { @@ -413,8 +412,6 @@ static void __init mmio_select_mitigation(void) if (mmio_mitigation == MMIO_MITIGATION_OFF) return; - ia32_cap = x86_read_arch_cap_msr(); - /* * Enable CPU buffer clear mitigation for host and VMM, if also affected * by MDS or TAA. Otherwise, enable mitigation for VMM only. @@ -437,7 +434,7 @@ static void __init mmio_select_mitigation(void) * be propagated to uncore buffers, clearing the Fill buffers on idle * is required irrespective of SMT state. */ - if (!(ia32_cap & ARCH_CAP_FBSDP_NO)) + if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) static_branch_enable(&mds_idle_clear); /* @@ -447,10 +444,10 @@ static void __init mmio_select_mitigation(void) * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS * affected systems. */ - if ((ia32_cap & ARCH_CAP_FB_CLEAR) || + if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) || (boot_cpu_has(X86_FEATURE_MD_CLEAR) && boot_cpu_has(X86_FEATURE_FLUSH_L1D) && - !(ia32_cap & ARCH_CAP_MDS_NO))) + !(x86_arch_cap_msr & ARCH_CAP_MDS_NO))) mmio_mitigation = MMIO_MITIGATION_VERW; else mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED; @@ -508,7 +505,7 @@ static void __init rfds_select_mitigation(void) if (rfds_mitigation == RFDS_MITIGATION_OFF) return; - if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR) setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF); else rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED; @@ -659,8 +656,6 @@ void update_srbds_msr(void) static void __init srbds_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_SRBDS)) return; @@ -669,8 +664,7 @@ static void __init srbds_select_mitigation(void) * are only exposed to SRBDS when TSX is enabled or when CPU is affected * by Processor MMIO Stale Data vulnerability. */ - ia32_cap = x86_read_arch_cap_msr(); - if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) && + if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) && !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) srbds_mitigation = SRBDS_MITIGATION_TSX_OFF; else if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) @@ -813,7 +807,7 @@ static void __init gds_select_mitigation(void) /* Will verify below that mitigation _can_ be disabled */ /* No microcode */ - if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) { + if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) { if (gds_mitigation == GDS_MITIGATION_FORCE) { /* * This only needs to be done on the boot CPU so do it @@ -1544,20 +1538,25 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void) return SPECTRE_V2_RETPOLINE; } +static bool __ro_after_init rrsba_disabled; + /* Disable in-kernel use of non-RSB RET predictors */ static void __init spec_ctrl_disable_kernel_rrsba(void) { - u64 ia32_cap; + if (rrsba_disabled) + return; + + if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) { + rrsba_disabled = true; + return; + } if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL)) return; - ia32_cap = x86_read_arch_cap_msr(); - - if (ia32_cap & ARCH_CAP_RRSBA) { - x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; - update_spec_ctrl(x86_spec_ctrl_base); - } + x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; + update_spec_ctrl(x86_spec_ctrl_base); + rrsba_disabled = true; } static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode) @@ -1607,6 +1606,74 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ dump_stack(); } +/* + * Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by + * branch history in userspace. Not needed if BHI_NO is set. + */ +static bool __init spec_ctrl_bhi_dis(void) +{ + if (!boot_cpu_has(X86_FEATURE_BHI_CTRL)) + return false; + + x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S; + update_spec_ctrl(x86_spec_ctrl_base); + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW); + + return true; +} + +enum bhi_mitigations { + BHI_MITIGATION_OFF, + BHI_MITIGATION_ON, +}; + +static enum bhi_mitigations bhi_mitigation __ro_after_init = + IS_ENABLED(CONFIG_MITIGATION_SPECTRE_BHI) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF; + +static int __init spectre_bhi_parse_cmdline(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "off")) + bhi_mitigation = BHI_MITIGATION_OFF; + else if (!strcmp(str, "on")) + bhi_mitigation = BHI_MITIGATION_ON; + else + pr_err("Ignoring unknown spectre_bhi option (%s)", str); + + return 0; +} +early_param("spectre_bhi", spectre_bhi_parse_cmdline); + +static void __init bhi_select_mitigation(void) +{ + if (bhi_mitigation == BHI_MITIGATION_OFF) + return; + + /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */ + if (boot_cpu_has(X86_FEATURE_RETPOLINE) && + !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) { + spec_ctrl_disable_kernel_rrsba(); + if (rrsba_disabled) + return; + } + + if (spec_ctrl_bhi_dis()) + return; + + if (!IS_ENABLED(CONFIG_X86_64)) + return; + + /* Mitigate KVM by default */ + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT); + pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n"); + + /* Mitigate syscalls when the mitigation is forced =on */ + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP); + pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n"); +} + static void __init spectre_v2_select_mitigation(void) { enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); @@ -1718,6 +1785,9 @@ static void __init spectre_v2_select_mitigation(void) mode == SPECTRE_V2_RETPOLINE) spec_ctrl_disable_kernel_rrsba(); + if (boot_cpu_has(X86_BUG_BHI)) + bhi_select_mitigation(); + spectre_v2_enabled = mode; pr_info("%s\n", spectre_v2_strings[mode]); @@ -1832,8 +1902,6 @@ static void update_indir_branch_cond(void) /* Update the static key controlling the MDS CPU buffer clear in idle */ static void update_mds_branch_idle(void) { - u64 ia32_cap = x86_read_arch_cap_msr(); - /* * Enable the idle clearing if SMT is active on CPUs which are * affected only by MSBDS and not any other MDS variant. @@ -1848,7 +1916,7 @@ static void update_mds_branch_idle(void) if (sched_smt_active()) { static_branch_enable(&mds_idle_clear); } else if (mmio_mitigation == MMIO_MITIGATION_OFF || - (ia32_cap & ARCH_CAP_FBSDP_NO)) { + (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) { static_branch_disable(&mds_idle_clear); } } @@ -2695,15 +2763,15 @@ static char *stibp_state(void) switch (spectre_v2_user_stibp) { case SPECTRE_V2_USER_NONE: - return ", STIBP: disabled"; + return "; STIBP: disabled"; case SPECTRE_V2_USER_STRICT: - return ", STIBP: forced"; + return "; STIBP: forced"; case SPECTRE_V2_USER_STRICT_PREFERRED: - return ", STIBP: always-on"; + return "; STIBP: always-on"; case SPECTRE_V2_USER_PRCTL: case SPECTRE_V2_USER_SECCOMP: if (static_key_enabled(&switch_to_cond_stibp)) - return ", STIBP: conditional"; + return "; STIBP: conditional"; } return ""; } @@ -2712,10 +2780,10 @@ static char *ibpb_state(void) { if (boot_cpu_has(X86_FEATURE_IBPB)) { if (static_key_enabled(&switch_mm_always_ibpb)) - return ", IBPB: always-on"; + return "; IBPB: always-on"; if (static_key_enabled(&switch_mm_cond_ibpb)) - return ", IBPB: conditional"; - return ", IBPB: disabled"; + return "; IBPB: conditional"; + return "; IBPB: disabled"; } return ""; } @@ -2725,14 +2793,32 @@ static char *pbrsb_eibrs_state(void) if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) { if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) || boot_cpu_has(X86_FEATURE_RSB_VMEXIT)) - return ", PBRSB-eIBRS: SW sequence"; + return "; PBRSB-eIBRS: SW sequence"; else - return ", PBRSB-eIBRS: Vulnerable"; + return "; PBRSB-eIBRS: Vulnerable"; } else { - return ", PBRSB-eIBRS: Not affected"; + return "; PBRSB-eIBRS: Not affected"; } } +static const char *spectre_bhi_state(void) +{ + if (!boot_cpu_has_bug(X86_BUG_BHI)) + return "; BHI: Not affected"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) + return "; BHI: BHI_DIS_S"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) + return "; BHI: SW loop, KVM: SW loop"; + else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && + !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) && + rrsba_disabled) + return "; BHI: Retpoline"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) + return "; BHI: Vulnerable, KVM: SW loop"; + + return "; BHI: Vulnerable"; +} + static ssize_t spectre_v2_show_state(char *buf) { if (spectre_v2_enabled == SPECTRE_V2_LFENCE) @@ -2745,13 +2831,15 @@ static ssize_t spectre_v2_show_state(char *buf) spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n"); - return sysfs_emit(buf, "%s%s%s%s%s%s%s\n", + return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], ibpb_state(), - boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "", stibp_state(), - boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "", + boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "", pbrsb_eibrs_state(), + spectre_bhi_state(), + /* this should always be at the end */ spectre_v2_module_string()); } diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5c1e6d6be267..605c26c009c8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1120,6 +1120,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) #define NO_SPECTRE_V2 BIT(8) #define NO_MMIO BIT(9) #define NO_EIBRS_PBRSB BIT(10) +#define NO_BHI BIT(11) #define VULNWL(vendor, family, model, whitelist) \ X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist) @@ -1182,18 +1183,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { VULNWL_INTEL(ATOM_TREMONT_D, NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB), /* AMD Family 0xf - 0x12 */ - VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), + VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */ - VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB), - VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB), + VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI), + VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI), /* Zhaoxin Family 7 */ - VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO), - VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO), + VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI), + VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI), {} }; @@ -1283,25 +1284,25 @@ static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long whi u64 x86_read_arch_cap_msr(void) { - u64 ia32_cap = 0; + u64 x86_arch_cap_msr = 0; if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) - rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap); + rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr); - return ia32_cap; + return x86_arch_cap_msr; } -static bool arch_cap_mmio_immune(u64 ia32_cap) +static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr) { - return (ia32_cap & ARCH_CAP_FBSDP_NO && - ia32_cap & ARCH_CAP_PSDP_NO && - ia32_cap & ARCH_CAP_SBDR_SSDP_NO); + return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO && + x86_arch_cap_msr & ARCH_CAP_PSDP_NO && + x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO); } -static bool __init vulnerable_to_rfds(u64 ia32_cap) +static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr) { /* The "immunity" bit trumps everything else: */ - if (ia32_cap & ARCH_CAP_RFDS_NO) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_NO) return false; /* @@ -1309,7 +1310,7 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap) * indicate that mitigation is needed because guest is running on a * vulnerable hardware or may migrate to such hardware: */ - if (ia32_cap & ARCH_CAP_RFDS_CLEAR) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR) return true; /* Only consult the blacklist when there is no enumeration: */ @@ -1318,11 +1319,11 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap) static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) { - u64 ia32_cap = x86_read_arch_cap_msr(); + u64 x86_arch_cap_msr = x86_read_arch_cap_msr(); /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */ if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) && - !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO)) + !(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO)) setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT); if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION)) @@ -1334,7 +1335,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) setup_force_cpu_bug(X86_BUG_SPECTRE_V2); if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) && - !(ia32_cap & ARCH_CAP_SSB_NO) && + !(x86_arch_cap_msr & ARCH_CAP_SSB_NO) && !cpu_has(c, X86_FEATURE_AMD_SSB_NO)) setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS); @@ -1345,17 +1346,17 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * Don't use AutoIBRS when SNP is enabled because it degrades host * userspace indirect branch performance. */ - if ((ia32_cap & ARCH_CAP_IBRS_ALL) || + if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) || (cpu_has(c, X86_FEATURE_AUTOIBRS) && !cpu_feature_enabled(X86_FEATURE_SEV_SNP))) { setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED); if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) && - !(ia32_cap & ARCH_CAP_PBRSB_NO)) + !(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO)) setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB); } if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) && - !(ia32_cap & ARCH_CAP_MDS_NO)) { + !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) { setup_force_cpu_bug(X86_BUG_MDS); if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY)) setup_force_cpu_bug(X86_BUG_MSBDS_ONLY); @@ -1374,9 +1375,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * TSX_CTRL check alone is not sufficient for cases when the microcode * update is not present or running as guest that don't get TSX_CTRL. */ - if (!(ia32_cap & ARCH_CAP_TAA_NO) && + if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) && (cpu_has(c, X86_FEATURE_RTM) || - (ia32_cap & ARCH_CAP_TSX_CTRL_MSR))) + (x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))) setup_force_cpu_bug(X86_BUG_TAA); /* @@ -1402,7 +1403,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist, * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits. */ - if (!arch_cap_mmio_immune(ia32_cap)) { + if (!arch_cap_mmio_immune(x86_arch_cap_msr)) { if (cpu_matches(cpu_vuln_blacklist, MMIO)) setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA); else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO)) @@ -1410,7 +1411,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) } if (!cpu_has(c, X86_FEATURE_BTC_NO)) { - if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA)) + if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA)) setup_force_cpu_bug(X86_BUG_RETBLEED); } @@ -1428,18 +1429,25 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * disabling AVX2. The only way to do this in HW is to clear XCR0[2], * which means that AVX will be disabled. */ - if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) && + if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) && boot_cpu_has(X86_FEATURE_AVX)) setup_force_cpu_bug(X86_BUG_GDS); - if (vulnerable_to_rfds(ia32_cap)) + if (vulnerable_to_rfds(x86_arch_cap_msr)) setup_force_cpu_bug(X86_BUG_RFDS); + /* When virtualized, eIBRS could be hidden, assume vulnerable */ + if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) && + !cpu_matches(cpu_vuln_whitelist, NO_BHI) && + (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) || + boot_cpu_has(X86_FEATURE_HYPERVISOR))) + setup_force_cpu_bug(X86_BUG_BHI); + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) return; /* Rogue Data Cache Load? No! */ - if (ia32_cap & ARCH_CAP_RDCL_NO) + if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO) return; setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c index b7174209d855..946813d816bf 100644 --- a/arch/x86/kernel/cpu/cpuid-deps.c +++ b/arch/x86/kernel/cpu/cpuid-deps.c @@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_F16C, X86_FEATURE_XMM2, }, { X86_FEATURE_AES, X86_FEATURE_XMM2 }, { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 }, + { X86_FEATURE_GFNI, X86_FEATURE_XMM2 }, { X86_FEATURE_FMA, X86_FEATURE_AVX }, + { X86_FEATURE_VAES, X86_FEATURE_AVX }, + { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX }, { X86_FEATURE_AVX2, X86_FEATURE_AVX, }, { X86_FEATURE_AVX512F, X86_FEATURE_AVX, }, { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F }, @@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL }, - { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VAES, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F }, diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index b5cc557cfc37..84d41be6d06b 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -2500,12 +2500,14 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr, return -EINVAL; b = &per_cpu(mce_banks_array, s->id)[bank]; - if (!b->init) return -ENODEV; b->ctl = new; + + mutex_lock(&mce_sysfs_mutex); mce_restart(); + mutex_unlock(&mce_sysfs_mutex); return size; } diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index 422a4ddc2ab7..7b29ebda024f 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -108,7 +108,7 @@ static inline void k8_check_syscfg_dram_mod_en(void) (boot_cpu_data.x86 >= 0x0f))) return; - if (cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return; rdmsr(MSR_AMD64_SYSCFG, lo, hi); diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h index c99f26ebe7a6..1a8687f8073a 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -78,7 +78,8 @@ cpumask_any_housekeeping(const struct cpumask *mask, int exclude_cpu) else cpu = cpumask_any_but(mask, exclude_cpu); - if (!IS_ENABLED(CONFIG_NO_HZ_FULL)) + /* Only continue if tick_nohz_full_mask has been initialized. */ + if (!tick_nohz_full_enabled()) return cpu; /* If the CPU picked isn't marked nohz_full nothing more needs doing. */ diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index a515328d9d7d..af5aa2c754c2 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -28,6 +28,7 @@ static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 }, { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 }, + { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 }, { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 }, { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 }, { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 }, diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index aaca8d235dc2..d17c9b71eb4a 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -123,7 +123,6 @@ static void topo_set_cpuids(unsigned int cpu, u32 apic_id, u32 acpi_id) early_per_cpu(x86_cpu_to_apicid, cpu) = apic_id; early_per_cpu(x86_cpu_to_acpiid, cpu) = acpi_id; #endif - set_cpu_possible(cpu, true); set_cpu_present(cpu, true); } @@ -210,7 +209,11 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present) topo_info.nr_disabled_cpus++; } - /* Register present and possible CPUs in the domain maps */ + /* + * Register present and possible CPUs in the domain + * maps. cpu_possible_map will be updated in + * topology_init_possible_cpus() after enumeration is done. + */ for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++) set_bit(topo_apicid(apic_id, dom), apic_maps[dom].map); } diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index 1a8b3ad493af..a7aa6eff4ae5 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -29,11 +29,21 @@ static bool parse_8000_0008(struct topo_scan *tscan) if (!sft) sft = get_count_order(ecx.cpu_nthreads + 1); - topology_set_dom(tscan, TOPO_SMT_DOMAIN, sft, ecx.cpu_nthreads + 1); + /* + * cpu_nthreads describes the number of threads in the package + * sft is the number of APIC ID bits per package + * + * As the number of actual threads per core is not described in + * this leaf, just set the CORE domain shift and let the later + * parsers set SMT shift. Assume one thread per core by default + * which is correct if there are no other CPUID leafs to parse. + */ + topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1); + topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1); return true; } -static void store_node(struct topo_scan *tscan, unsigned int nr_nodes, u16 node_id) +static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id) { /* * Starting with Fam 17h the DIE domain could probably be used to @@ -73,12 +83,14 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb) tscan->c->topo.initial_apicid = leaf.ext_apic_id; /* - * If leaf 0xb is available, then SMT shift is set already. If not - * take it from ecx.threads_per_core and use topo_update_dom() - - * topology_set_dom() would propagate and overwrite the already - * propagated CORE level. + * If leaf 0xb is available, then the domain shifts are set + * already and nothing to do here. */ if (!has_0xb) { + /* + * Leaf 0x80000008 set the CORE domain shift already. + * Update the SMT domain, but do not propagate it. + */ unsigned int nthreads = leaf.core_nthreads + 1; topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads); @@ -109,13 +121,13 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb) static bool parse_fam10h_node_id(struct topo_scan *tscan) { - struct { - union { + union { + struct { u64 node_id : 3, nodes_per_pkg : 3, unused : 58; - u64 msr; }; + u64 msr; } nid; if (!boot_cpu_has(X86_FEATURE_NODEID_MSR)) @@ -135,6 +147,26 @@ static void legacy_set_llc(struct topo_scan *tscan) tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN]; } +static void topoext_fixup(struct topo_scan *tscan) +{ + struct cpuinfo_x86 *c = tscan->c; + u64 msrval; + + /* Try to re-enable TopologyExtensions if switched off by BIOS */ + if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD || + c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f) + return; + + if (msr_set_bit(0xc0011005, 54) <= 0) + return; + + rdmsrl(0xc0011005, msrval); + if (msrval & BIT_64(54)) { + set_cpu_cap(c, X86_FEATURE_TOPOEXT); + pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); + } +} + static void parse_topology_amd(struct topo_scan *tscan) { bool has_0xb = false; @@ -164,6 +196,7 @@ static void parse_topology_amd(struct topo_scan *tscan) void cpu_parse_topology_amd(struct topo_scan *tscan) { tscan->amd_nodes_per_pkg = 1; + topoext_fixup(tscan); parse_topology_amd(tscan); if (tscan->amd_nodes_per_pkg > 1) diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 4cadfd606e8e..7f0732bc0ccd 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -65,6 +65,7 @@ static int __init parse_no_stealacc(char *arg) early_param("no-steal-acc", parse_no_stealacc); +static DEFINE_PER_CPU_READ_MOSTLY(bool, async_pf_enabled); static DEFINE_PER_CPU_DECRYPTED(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64); DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible; static int has_steal_clock = 0; @@ -244,7 +245,7 @@ noinstr u32 kvm_read_and_reset_apf_flags(void) { u32 flags = 0; - if (__this_cpu_read(apf_reason.enabled)) { + if (__this_cpu_read(async_pf_enabled)) { flags = __this_cpu_read(apf_reason.flags); __this_cpu_write(apf_reason.flags, 0); } @@ -295,7 +296,7 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_kvm_asyncpf_interrupt) inc_irq_stat(irq_hv_callback_count); - if (__this_cpu_read(apf_reason.enabled)) { + if (__this_cpu_read(async_pf_enabled)) { token = __this_cpu_read(apf_reason.token); kvm_async_pf_task_wake(token); __this_cpu_write(apf_reason.token, 0); @@ -362,7 +363,7 @@ static void kvm_guest_cpu_init(void) wrmsrl(MSR_KVM_ASYNC_PF_INT, HYPERVISOR_CALLBACK_VECTOR); wrmsrl(MSR_KVM_ASYNC_PF_EN, pa); - __this_cpu_write(apf_reason.enabled, 1); + __this_cpu_write(async_pf_enabled, true); pr_debug("setup async PF for cpu %d\n", smp_processor_id()); } @@ -383,11 +384,11 @@ static void kvm_guest_cpu_init(void) static void kvm_pv_disable_apf(void) { - if (!__this_cpu_read(apf_reason.enabled)) + if (!__this_cpu_read(async_pf_enabled)) return; wrmsrl(MSR_KVM_ASYNC_PF_EN, 0); - __this_cpu_write(apf_reason.enabled, 0); + __this_cpu_write(async_pf_enabled, false); pr_debug("disable async PF for cpu %d\n", smp_processor_id()); } diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 7062b84dd467..6d3d20e3e43a 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -139,7 +139,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode, log_lvl, d3, d6, d7); } - if (cpu_feature_enabled(X86_FEATURE_OSPKE)) + if (cr4 & X86_CR4_PKE) printk("%sPKRU: %08x\n", log_lvl, read_pkru()); } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 0109e6c510e0..e125e059e2c4 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -991,6 +992,7 @@ void __init setup_arch(char **cmdline_p) * memory size. */ mem_encrypt_setup_arch(); + cc_random_init(); efi_fake_memmap(); efi_find_mirror(); diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c index 8b04958da5e7..b4f8fa0f722c 100644 --- a/arch/x86/kernel/sev-shared.c +++ b/arch/x86/kernel/sev-shared.c @@ -1203,12 +1203,14 @@ static enum es_result vc_check_opcode_bytes(struct es_em_ctxt *ctxt, break; case SVM_EXIT_MONITOR: - if (opcode == 0x010f && modrm == 0xc8) + /* MONITOR and MONITORX instructions generate the same error code */ + if (opcode == 0x010f && (modrm == 0xc8 || modrm == 0xfa)) return ES_OK; break; case SVM_EXIT_MWAIT: - if (opcode == 0x010f && modrm == 0xc9) + /* MWAIT and MWAITX instructions generate the same error code */ + if (opcode == 0x010f && (modrm == 0xc9 || modrm == 0xfb)) return ES_OK; break; diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index 7e1e63cc48e6..38ad066179d8 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -2284,16 +2284,6 @@ static int __init snp_init_platform_device(void) } device_initcall(snp_init_platform_device); -void kdump_sev_callback(void) -{ - /* - * Do wbinvd() on remote CPUs when SNP is enabled in order to - * safely do SNP_SHUTDOWN on the local CPU. - */ - if (cpu_feature_enabled(X86_FEATURE_SEV_SNP)) - wbinvd(); -} - void sev_show_status(void) { int i; diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 3aaf7e86a859..0ebdd088f28b 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -122,6 +122,7 @@ config KVM_AMD_SEV default y depends on KVM_AMD && X86_64 depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m) + select ARCH_HAS_CC_PLATFORM help Provides support for launching Encrypted VMs (SEV) and Encrypted VMs with Encrypted State (SEV-ES) on AMD processors. diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index a88bb14266b6..addc44fc7187 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -3,11 +3,6 @@ ccflags-y += -I $(srctree)/arch/x86/kvm ccflags-$(CONFIG_KVM_WERROR) += -Werror -ifeq ($(CONFIG_FRAME_POINTER),y) -OBJECT_FILES_NON_STANDARD_vmx/vmenter.o := y -OBJECT_FILES_NON_STANDARD_svm/vmenter.o := y -endif - include $(srctree)/virt/kvm/Makefile.kvm kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \ diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index adba49afb5fe..77352a4abd87 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -189,15 +189,15 @@ static int kvm_cpuid_check_equal(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 return 0; } -static struct kvm_hypervisor_cpuid kvm_get_hypervisor_cpuid(struct kvm_vcpu *vcpu, - const char *sig) +static struct kvm_hypervisor_cpuid __kvm_get_hypervisor_cpuid(struct kvm_cpuid_entry2 *entries, + int nent, const char *sig) { struct kvm_hypervisor_cpuid cpuid = {}; struct kvm_cpuid_entry2 *entry; u32 base; for_each_possible_hypervisor_cpuid_base(base) { - entry = kvm_find_cpuid_entry(vcpu, base); + entry = cpuid_entry2_find(entries, nent, base, KVM_CPUID_INDEX_NOT_SIGNIFICANT); if (entry) { u32 signature[3]; @@ -217,22 +217,29 @@ static struct kvm_hypervisor_cpuid kvm_get_hypervisor_cpuid(struct kvm_vcpu *vcp return cpuid; } -static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu, - struct kvm_cpuid_entry2 *entries, int nent) +static struct kvm_hypervisor_cpuid kvm_get_hypervisor_cpuid(struct kvm_vcpu *vcpu, + const char *sig) +{ + return __kvm_get_hypervisor_cpuid(vcpu->arch.cpuid_entries, + vcpu->arch.cpuid_nent, sig); +} + +static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_cpuid_entry2 *entries, + int nent, u32 kvm_cpuid_base) +{ + return cpuid_entry2_find(entries, nent, kvm_cpuid_base | KVM_CPUID_FEATURES, + KVM_CPUID_INDEX_NOT_SIGNIFICANT); +} + +static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu) { u32 base = vcpu->arch.kvm_cpuid.base; if (!base) return NULL; - return cpuid_entry2_find(entries, nent, base | KVM_CPUID_FEATURES, - KVM_CPUID_INDEX_NOT_SIGNIFICANT); -} - -static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu) -{ - return __kvm_find_kvm_cpuid_features(vcpu, vcpu->arch.cpuid_entries, - vcpu->arch.cpuid_nent); + return __kvm_find_kvm_cpuid_features(vcpu->arch.cpuid_entries, + vcpu->arch.cpuid_nent, base); } void kvm_update_pv_runtime(struct kvm_vcpu *vcpu) @@ -266,6 +273,7 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e int nent) { struct kvm_cpuid_entry2 *best; + struct kvm_hypervisor_cpuid kvm_cpuid; best = cpuid_entry2_find(entries, nent, 1, KVM_CPUID_INDEX_NOT_SIGNIFICANT); if (best) { @@ -292,10 +300,12 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e cpuid_entry_has(best, X86_FEATURE_XSAVEC))) best->ebx = xstate_required_size(vcpu->arch.xcr0, true); - best = __kvm_find_kvm_cpuid_features(vcpu, entries, nent); - if (kvm_hlt_in_guest(vcpu->kvm) && best && - (best->eax & (1 << KVM_FEATURE_PV_UNHALT))) - best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT); + kvm_cpuid = __kvm_get_hypervisor_cpuid(entries, nent, KVM_SIGNATURE); + if (kvm_cpuid.base) { + best = __kvm_find_kvm_cpuid_features(entries, nent, kvm_cpuid.base); + if (kvm_hlt_in_guest(vcpu->kvm) && best) + best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT); + } if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)) { best = cpuid_entry2_find(entries, nent, 0x1, KVM_CPUID_INDEX_NOT_SIGNIFICANT); @@ -366,6 +376,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) kvm_update_pv_runtime(vcpu); + vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu); vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu); vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 856e3037e74f..23dbb9eb277c 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu) return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx); } +static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.is_amd_compatible; +} + +static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu) +{ + return !guest_cpuid_is_amd_compatible(vcpu); +} + static inline int guest_cpuid_family(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index cf37586f0466..ebf41023be38 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2776,7 +2776,8 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type) trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL); - if (r && lvt_type == APIC_LVTPC) + if (r && lvt_type == APIC_LVTPC && + guest_cpuid_is_intel_compatible(apic->vcpu)) kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED); return r; } diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 992e651540e8..db007a4dffa2 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4935,7 +4935,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu, context->cpu_role.base.level, is_efer_nx(context), guest_can_use(vcpu, X86_FEATURE_GBPAGES), is_cr4_pse(context), - guest_cpuid_is_amd_or_hygon(vcpu)); + guest_cpuid_is_amd_compatible(vcpu)); } static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check, @@ -5576,9 +5576,9 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu) * that problem is swept under the rug; KVM's CPUID API is horrific and * it's all but impossible to solve it without introducing a new API. */ - vcpu->arch.root_mmu.root_role.word = 0; - vcpu->arch.guest_mmu.root_role.word = 0; - vcpu->arch.nested_mmu.root_role.word = 0; + vcpu->arch.root_mmu.root_role.invalid = 1; + vcpu->arch.guest_mmu.root_role.invalid = 1; + vcpu->arch.nested_mmu.root_role.invalid = 1; vcpu->arch.root_mmu.cpu_role.ext.valid = 0; vcpu->arch.guest_mmu.cpu_role.ext.valid = 0; vcpu->arch.nested_mmu.cpu_role.ext.valid = 0; @@ -7399,7 +7399,8 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, * by the memslot, KVM can't use a hugepage due to the * misaligned address regardless of memory attributes. */ - if (gfn >= slot->base_gfn) { + if (gfn >= slot->base_gfn && + gfn + nr_pages <= slot->base_gfn + slot->npages) { if (hugepage_has_attrs(kvm, slot, gfn, level, attrs)) hugepage_clear_mixed(slot, gfn, level); else diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index d078157e62aa..04c1f0957fea 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1548,17 +1548,21 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, } } -/* - * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If - * AD bits are enabled, this will involve clearing the dirty bit on each SPTE. - * If AD bits are not enabled, this will require clearing the writable bit on - * each SPTE. Returns true if an SPTE has been changed and the TLBs need to - * be flushed. - */ +static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp) +{ + /* + * All TDP MMU shadow pages share the same role as their root, aside + * from level, so it is valid to key off any shadow page to determine if + * write protection is needed for an entire tree. + */ + return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled(); +} + static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t start, gfn_t end) { - u64 dbit = kvm_ad_enabled() ? shadow_dirty_mask : PT_WRITABLE_MASK; + const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK : + shadow_dirty_mask; struct tdp_iter iter; bool spte_set = false; @@ -1573,7 +1577,7 @@ static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) continue; - KVM_MMU_WARN_ON(kvm_ad_enabled() && + KVM_MMU_WARN_ON(dbit == shadow_dirty_mask && spte_ad_need_write_protect(iter.old_spte)); if (!(iter.old_spte & dbit)) @@ -1590,11 +1594,9 @@ static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, } /* - * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If - * AD bits are enabled, this will involve clearing the dirty bit on each SPTE. - * If AD bits are not enabled, this will require clearing the writable bit on - * each SPTE. Returns true if an SPTE has been changed and the TLBs need to - * be flushed. + * Clear the dirty status (D-bit or W-bit) of all the SPTEs mapping GFNs in the + * memslot. Returns true if an SPTE has been changed and the TLBs need to be + * flushed. */ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, const struct kvm_memory_slot *slot) @@ -1610,18 +1612,11 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, return spte_set; } -/* - * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is - * set in mask, starting at gfn. The given memslot is expected to contain all - * the GFNs represented by set bits in the mask. If AD bits are enabled, - * clearing the dirty status will involve clearing the dirty bit on each SPTE - * or, if AD bits are not enabled, clearing the writable bit on each SPTE. - */ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t gfn, unsigned long mask, bool wrprot) { - u64 dbit = (wrprot || !kvm_ad_enabled()) ? PT_WRITABLE_MASK : - shadow_dirty_mask; + const u64 dbit = (wrprot || tdp_mmu_need_write_protect(root)) ? PT_WRITABLE_MASK : + shadow_dirty_mask; struct tdp_iter iter; lockdep_assert_held_write(&kvm->mmu_lock); @@ -1633,7 +1628,7 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, if (!mask) break; - KVM_MMU_WARN_ON(kvm_ad_enabled() && + KVM_MMU_WARN_ON(dbit == shadow_dirty_mask && spte_ad_need_write_protect(iter.old_spte)); if (iter.level > PG_LEVEL_4K || @@ -1659,11 +1654,9 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, } /* - * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is - * set in mask, starting at gfn. The given memslot is expected to contain all - * the GFNs represented by set bits in the mask. If AD bits are enabled, - * clearing the dirty status will involve clearing the dirty bit on each SPTE - * or, if AD bits are not enabled, clearing the writable bit on each SPTE. + * Clear the dirty status (D-bit or W-bit) of all the 4k SPTEs mapping GFNs for + * which a bit is set in mask, starting at gfn. The given memslot is expected to + * contain all the GFNs represented by set bits in the mask. */ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index c397b28e3d1b..a593b03c9aed 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -775,8 +775,20 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu) pmu->pebs_data_cfg_mask = ~0ull; bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX); - if (vcpu->kvm->arch.enable_pmu) - static_call(kvm_x86_pmu_refresh)(vcpu); + if (!vcpu->kvm->arch.enable_pmu) + return; + + static_call(kvm_x86_pmu_refresh)(vcpu); + + /* + * At RESET, both Intel and AMD CPUs set all enable bits for general + * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that + * was written for v1 PMUs don't unknowingly leave GP counters disabled + * in the global controls). Emulate that behavior when refreshing the + * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL. + */ + if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters) + pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0); } void kvm_pmu_init(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index aadefcaa9561..2f4e155080ba 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -52,7 +52,7 @@ enum kvm_only_cpuid_leafs { #define X86_FEATURE_IPRED_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 1) #define KVM_X86_FEATURE_RRSBA_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 2) #define X86_FEATURE_DDPD_U KVM_X86_FEATURE(CPUID_7_2_EDX, 3) -#define X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4) +#define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4) #define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5) /* CPUID level 0x80000007 (EDX). */ @@ -102,10 +102,12 @@ static const struct cpuid_reg reverse_cpuid[] = { */ static __always_inline void reverse_cpuid_check(unsigned int x86_leaf) { + BUILD_BUG_ON(NR_CPUID_WORDS != NCAPINTS); BUILD_BUG_ON(x86_leaf == CPUID_LNX_1); BUILD_BUG_ON(x86_leaf == CPUID_LNX_2); BUILD_BUG_ON(x86_leaf == CPUID_LNX_3); BUILD_BUG_ON(x86_leaf == CPUID_LNX_4); + BUILD_BUG_ON(x86_leaf == CPUID_LNX_5); BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid)); BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0); } @@ -126,6 +128,7 @@ static __always_inline u32 __feature_translate(int x86_feature) KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC); KVM_X86_TRANSLATE_FEATURE(PERFMON_V2); KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL); + KVM_X86_TRANSLATE_FEATURE(BHI_CTRL); default: return x86_feature; } diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index ae0ac12382b9..759581bb2128 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -84,9 +84,10 @@ struct enc_region { }; /* Called with the sev_bitmap_lock held, or on shutdown */ -static int sev_flush_asids(int min_asid, int max_asid) +static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid) { - int ret, asid, error = 0; + int ret, error = 0; + unsigned int asid; /* Check if there are any ASIDs to reclaim before performing a flush */ asid = find_next_bit(sev_reclaim_asid_bitmap, nr_asids, min_asid); @@ -116,7 +117,7 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm) } /* Must be called with the sev_bitmap_lock held */ -static bool __sev_recycle_asids(int min_asid, int max_asid) +static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid) { if (sev_flush_asids(min_asid, max_asid)) return false; @@ -143,8 +144,20 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev) static int sev_asid_new(struct kvm_sev_info *sev) { - int asid, min_asid, max_asid, ret; + /* + * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. + * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. + * Note: min ASID can end up larger than the max if basic SEV support is + * effectively disabled by disallowing use of ASIDs for SEV guests. + */ + unsigned int min_asid = sev->es_active ? 1 : min_sev_asid; + unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; + unsigned int asid; bool retry = true; + int ret; + + if (min_asid > max_asid) + return -ENOTTY; WARN_ON(sev->misc_cg); sev->misc_cg = get_current_misc_cg(); @@ -157,12 +170,6 @@ static int sev_asid_new(struct kvm_sev_info *sev) mutex_lock(&sev_bitmap_lock); - /* - * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid. - * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1. - */ - min_asid = sev->es_active ? 1 : min_sev_asid; - max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid; again: asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid); if (asid > max_asid) { @@ -179,7 +186,8 @@ static int sev_asid_new(struct kvm_sev_info *sev) mutex_unlock(&sev_bitmap_lock); - return asid; + sev->asid = asid; + return 0; e_uncharge: sev_misc_cg_uncharge(sev); put_misc_cg(sev->misc_cg); @@ -187,7 +195,7 @@ static int sev_asid_new(struct kvm_sev_info *sev) return ret; } -static int sev_get_asid(struct kvm *kvm) +static unsigned int sev_get_asid(struct kvm *kvm) { struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; @@ -247,21 +255,19 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) { struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info; struct sev_platform_init_args init_args = {0}; - int asid, ret; + int ret; if (kvm->created_vcpus) return -EINVAL; - ret = -EBUSY; if (unlikely(sev->active)) - return ret; + return -EINVAL; sev->active = true; sev->es_active = argp->id == KVM_SEV_ES_INIT; - asid = sev_asid_new(sev); - if (asid < 0) + ret = sev_asid_new(sev); + if (ret) goto e_no_asid; - sev->asid = asid; init_args.probe = false; ret = sev_platform_init(&init_args); @@ -287,8 +293,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error) { + unsigned int asid = sev_get_asid(kvm); struct sev_data_activate activate; - int asid = sev_get_asid(kvm); int ret; /* activate ASID on the given handle */ @@ -428,7 +434,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, /* Avoid using vmalloc for smaller buffers. */ size = npages * sizeof(struct page *); if (size > PAGE_SIZE) - pages = __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_ZERO); + pages = __vmalloc(size, GFP_KERNEL_ACCOUNT); else pages = kmalloc(size, GFP_KERNEL_ACCOUNT); @@ -2240,8 +2246,10 @@ void __init sev_hardware_setup(void) goto out; } - sev_asid_count = max_sev_asid - min_sev_asid + 1; - WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); + if (min_sev_asid <= max_sev_asid) { + sev_asid_count = max_sev_asid - min_sev_asid + 1; + WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count)); + } sev_supported = true; /* SEV-ES support requested? */ @@ -2272,7 +2280,9 @@ void __init sev_hardware_setup(void) out: if (boot_cpu_has(X86_FEATURE_SEV)) pr_info("SEV %s (ASIDs %u - %u)\n", - sev_supported ? "enabled" : "disabled", + sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" : + "unusable" : + "disabled", min_sev_asid, max_sev_asid); if (boot_cpu_has(X86_FEATURE_SEV_ES)) pr_info("SEV-ES %s (ASIDs %u - %u)\n", @@ -2320,7 +2330,7 @@ int sev_cpu_init(struct svm_cpu_data *sd) */ static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va) { - int asid = to_kvm_svm(vcpu->kvm)->sev_info.asid; + unsigned int asid = sev_get_asid(vcpu->kvm); /* * Note! The address must be a kernel address, as regular page walk @@ -2638,7 +2648,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm) void pre_sev_run(struct vcpu_svm *svm, int cpu) { struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu); - int asid = sev_get_asid(svm->vcpu.kvm); + unsigned int asid = sev_get_asid(svm->vcpu.kvm); /* Assign the asid allocated with this SEV guest */ svm->asid = asid; @@ -3174,7 +3184,7 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu) unsigned long pfn; struct page *p; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); /* diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d1a9f9951635..9aaf83c8d57d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1503,6 +1503,11 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu) __free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE)); } +static struct sev_es_save_area *sev_es_host_save_area(struct svm_cpu_data *sd) +{ + return page_address(sd->save_area) + 0x400; +} + static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -1519,12 +1524,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) * or subsequent vmload of host save area. */ vmsave(sd->save_area_pa); - if (sev_es_guest(vcpu->kvm)) { - struct sev_es_save_area *hostsa; - hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400); - - sev_es_prepare_switch_to_guest(hostsa); - } + if (sev_es_guest(vcpu->kvm)) + sev_es_prepare_switch_to_guest(sev_es_host_save_area(sd)); if (tsc_scaling) __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); @@ -4101,6 +4102,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu) static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted) { + struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu); struct vcpu_svm *svm = to_svm(vcpu); guest_state_enter_irqoff(); @@ -4108,7 +4110,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in amd_clear_divider(); if (sev_es_guest(vcpu->kvm)) - __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted); + __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted, + sev_es_host_save_area(sd)); else __svm_vcpu_run(svm, spec_ctrl_intercepted); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 7f1fbd874c45..33878efdebc8 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -698,7 +698,8 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu); /* vmenter.S */ -void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); +void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted, + struct sev_es_save_area *hostsa); void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); #define DEFINE_KVM_GHCB_ACCESSORS(field) \ diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 187018c424bf..a0c8eb37d3e1 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "kvm-asm-offsets.h" @@ -67,7 +68,7 @@ "", X86_FEATURE_V_SPEC_CTRL 901: .endm -.macro RESTORE_HOST_SPEC_CTRL_BODY +.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req 900: /* Same for after vmexit. */ mov $MSR_IA32_SPEC_CTRL, %ecx @@ -76,7 +77,7 @@ * Load the value that the guest had written into MSR_IA32_SPEC_CTRL, * if it was not intercepted during guest execution. */ - cmpb $0, (%_ASM_SP) + cmpb $0, \spec_ctrl_intercepted jnz 998f rdmsr movl %eax, SVM_spec_ctrl(%_ASM_DI) @@ -99,6 +100,7 @@ */ SYM_FUNC_START(__svm_vcpu_run) push %_ASM_BP + mov %_ASM_SP, %_ASM_BP #ifdef CONFIG_X86_64 push %r15 push %r14 @@ -268,7 +270,7 @@ SYM_FUNC_START(__svm_vcpu_run) RET RESTORE_GUEST_SPEC_CTRL_BODY - RESTORE_HOST_SPEC_CTRL_BODY + RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP) 10: cmpb $0, _ASM_RIP(kvm_rebooting) jne 2b @@ -290,66 +292,68 @@ SYM_FUNC_START(__svm_vcpu_run) SYM_FUNC_END(__svm_vcpu_run) +#ifdef CONFIG_KVM_AMD_SEV + + +#ifdef CONFIG_X86_64 +#define SEV_ES_GPRS_BASE 0x300 +#define SEV_ES_RBX (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE) +#define SEV_ES_RBP (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE) +#define SEV_ES_RSI (SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE) +#define SEV_ES_RDI (SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE) +#define SEV_ES_R12 (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE) +#define SEV_ES_R13 (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE) +#define SEV_ES_R14 (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE) +#define SEV_ES_R15 (SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE) +#endif + /** * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode * @svm: struct vcpu_svm * * @spec_ctrl_intercepted: bool */ SYM_FUNC_START(__svm_sev_es_vcpu_run) - push %_ASM_BP -#ifdef CONFIG_X86_64 - push %r15 - push %r14 - push %r13 - push %r12 -#else - push %edi - push %esi -#endif - push %_ASM_BX + FRAME_BEGIN /* - * Save variables needed after vmexit on the stack, in inverse - * order compared to when they are needed. + * Save non-volatile (callee-saved) registers to the host save area. + * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not + * saved on VMRUN. */ + mov %rbp, SEV_ES_RBP (%rdx) + mov %r15, SEV_ES_R15 (%rdx) + mov %r14, SEV_ES_R14 (%rdx) + mov %r13, SEV_ES_R13 (%rdx) + mov %r12, SEV_ES_R12 (%rdx) + mov %rbx, SEV_ES_RBX (%rdx) - /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */ - push %_ASM_ARG2 - - /* Save @svm. */ - push %_ASM_ARG1 - -.ifnc _ASM_ARG1, _ASM_DI /* - * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX - * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL. + * Save volatile registers that hold arguments that are needed after + * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted). */ - mov %_ASM_ARG1, %_ASM_DI -.endif + mov %rdi, SEV_ES_RDI (%rdx) + mov %rsi, SEV_ES_RSI (%rdx) - /* Clobbers RAX, RCX, RDX. */ + /* Clobbers RAX, RCX, RDX (@hostsa). */ RESTORE_GUEST_SPEC_CTRL /* Get svm->current_vmcb->pa into RAX. */ - mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX - mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX + mov SVM_current_vmcb(%rdi), %rax + mov KVM_VMCB_pa(%rax), %rax /* Enter guest mode */ sti -1: vmrun %_ASM_AX +1: vmrun %rax 2: cli - /* Pop @svm to RDI, guest registers have been saved already. */ - pop %_ASM_DI - #ifdef CONFIG_MITIGATION_RETPOLINE /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ - FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE + FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE #endif - /* Clobbers RAX, RCX, RDX. */ + /* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */ RESTORE_HOST_SPEC_CTRL /* @@ -361,30 +365,17 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) */ UNTRAIN_RET_VM - /* "Pop" @spec_ctrl_intercepted. */ - pop %_ASM_BX - - pop %_ASM_BX - -#ifdef CONFIG_X86_64 - pop %r12 - pop %r13 - pop %r14 - pop %r15 -#else - pop %esi - pop %edi -#endif - pop %_ASM_BP + FRAME_END RET RESTORE_GUEST_SPEC_CTRL_BODY - RESTORE_HOST_SPEC_CTRL_BODY + RESTORE_HOST_SPEC_CTRL_BODY %sil -3: cmpb $0, _ASM_RIP(kvm_rebooting) +3: cmpb $0, kvm_rebooting(%rip) jne 2b ud2 _ASM_EXTABLE(1b, 3b) SYM_FUNC_END(__svm_sev_es_vcpu_run) +#endif /* CONFIG_KVM_AMD_SEV */ diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h index 88659de4d2a7..c6b4b1728006 100644 --- a/arch/x86/kvm/trace.h +++ b/arch/x86/kvm/trace.h @@ -735,13 +735,13 @@ TRACE_EVENT(kvm_nested_intr_vmexit, * Tracepoint for nested #vmexit because of interrupt pending */ TRACE_EVENT(kvm_invlpga, - TP_PROTO(__u64 rip, int asid, u64 address), + TP_PROTO(__u64 rip, unsigned int asid, u64 address), TP_ARGS(rip, asid, address), TP_STRUCT__entry( - __field( __u64, rip ) - __field( int, asid ) - __field( __u64, address ) + __field( __u64, rip ) + __field( unsigned int, asid ) + __field( __u64, address ) ), TP_fast_assign( @@ -750,7 +750,7 @@ TRACE_EVENT(kvm_invlpga, __entry->address = address; ), - TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx", + TP_printk("rip: 0x%016llx asid: %u address: 0x%016llx", __entry->rip, __entry->asid, __entry->address) ); diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 12ade343a17e..be40474de6e4 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -535,7 +535,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) perf_capabilities = vcpu_get_perf_capabilities(vcpu); if (cpuid_model_is_consistent(vcpu) && (perf_capabilities & PMU_CAP_LBR_FMT)) - x86_perf_get_lbr(&lbr_desc->records); + memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps)); else lbr_desc->records.nr = 0; diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 2bfbf758d061..f6986dee6f8c 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -275,6 +275,8 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) call vmx_spec_ctrl_restore_host + CLEAR_BRANCH_HISTORY_VMEXIT + /* Put return value in AX */ mov %_ASM_BX, %_ASM_AX diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c37a89eda90f..22411f4aff53 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -218,6 +218,8 @@ module_param(ple_window_max, uint, 0444); int __read_mostly pt_mode = PT_MODE_SYSTEM; module_param(pt_mode, int, S_IRUGO); +struct x86_pmu_lbr __ro_after_init vmx_lbr_caps; + static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond); static DEFINE_MUTEX(vmx_l1d_flush_mutex); @@ -7862,10 +7864,9 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) vmx_update_exception_bitmap(vcpu); } -static u64 vmx_get_perf_capabilities(void) +static __init u64 vmx_get_perf_capabilities(void) { u64 perf_cap = PMU_CAP_FW_WRITES; - struct x86_pmu_lbr lbr; u64 host_perf_cap = 0; if (!enable_pmu) @@ -7875,15 +7876,43 @@ static u64 vmx_get_perf_capabilities(void) rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap); if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) { - x86_perf_get_lbr(&lbr); - if (lbr.nr) + x86_perf_get_lbr(&vmx_lbr_caps); + + /* + * KVM requires LBR callstack support, as the overhead due to + * context switching LBRs without said support is too high. + * See intel_pmu_create_guest_lbr_event() for more info. + */ + if (!vmx_lbr_caps.has_callstack) + memset(&vmx_lbr_caps, 0, sizeof(vmx_lbr_caps)); + else if (vmx_lbr_caps.nr) perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT; } if (vmx_pebs_supported()) { perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK; - if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4) - perf_cap &= ~PERF_CAP_PEBS_BASELINE; + + /* + * Disallow adaptive PEBS as it is functionally broken, can be + * used by the guest to read *host* LBRs, and can be used to + * bypass userspace event filters. To correctly and safely + * support adaptive PEBS, KVM needs to: + * + * 1. Account for the ADAPTIVE flag when (re)programming fixed + * counters. + * + * 2. Gain support from perf (or take direct control of counter + * programming) to support events without adaptive PEBS + * enabled for the hardware counter. + * + * 3. Ensure LBR MSRs cannot hold host data on VM-Entry with + * adaptive PEBS enabled and MSR_PEBS_DATA_CFG.LBRS=1. + * + * 4. Document which PMU events are effectively exposed to the + * guest via adaptive PEBS, and make adaptive PEBS mutually + * exclusive with KVM_SET_PMU_EVENT_FILTER if necessary. + */ + perf_cap &= ~PERF_CAP_PEBS_BASELINE; } return perf_cap; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 65786dbe7d60..90f9e4434646 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -15,6 +15,7 @@ #include "vmx_ops.h" #include "../cpuid.h" #include "run_flags.h" +#include "../mmu.h" #define MSR_TYPE_R 1 #define MSR_TYPE_W 2 @@ -109,6 +110,8 @@ struct lbr_desc { bool msr_passthrough; }; +extern struct x86_pmu_lbr vmx_lbr_caps; + /* * The nested_vmx structure is part of vcpu_vmx, and holds information we need * for correct emulation of VMX (i.e., nested VMX) on this vcpu. @@ -719,7 +722,8 @@ static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu) if (!enable_ept) return true; - return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits; + return allow_smaller_maxphyaddr && + cpuid_maxphyaddr(vcpu) < kvm_get_shadow_phys_bits(); } static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 47d9f03b7778..91478b769af0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1621,7 +1621,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr) ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \ ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \ - ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR) + ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO) static u64 kvm_get_arch_capabilities(void) { @@ -3470,7 +3470,7 @@ static bool is_mci_status_msr(u32 msr) static bool can_set_mci_status(struct kvm_vcpu *vcpu) { /* McStatusWrEn enabled? */ - if (guest_cpuid_is_amd_or_hygon(vcpu)) + if (guest_cpuid_is_amd_compatible(vcpu)) return !!(vcpu->arch.msr_hwcr & BIT_ULL(18)); return false; diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index 02cde194a99e..391059b2c6fb 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -228,8 +228,12 @@ SYM_CODE_END(srso_return_thunk) #else /* !CONFIG_MITIGATION_SRSO */ /* Dummy for the alternative in CALL_UNTRAIN_RET. */ SYM_CODE_START(srso_alias_untrain_ret) - RET + ANNOTATE_UNRET_SAFE + ANNOTATE_NOENDBR + ret + int3 SYM_FUNC_END(srso_alias_untrain_ret) +__EXPORT_THUNK(srso_alias_untrain_ret) #define JMP_SRSO_UNTRAIN_RET "ud2" #endif /* CONFIG_MITIGATION_SRSO */ @@ -378,8 +382,15 @@ SYM_FUNC_END(call_depth_return_thunk) SYM_CODE_START(__x86_return_thunk) UNWIND_HINT_FUNC ANNOTATE_NOENDBR +#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ + defined(CONFIG_MITIGATION_SRSO) || \ + defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS +#else + ANNOTATE_UNRET_SAFE + ret +#endif int3 SYM_CODE_END(__x86_return_thunk) EXPORT_SYMBOL(__x86_return_thunk) diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 104544359d69..025fd7ea5d69 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -24,6 +24,7 @@ #include #include +#include #include "numa_internal.h" diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c index 0d72183b5dd0..36b603d0cdde 100644 --- a/arch/x86/mm/pat/memtype.c +++ b/arch/x86/mm/pat/memtype.c @@ -947,6 +947,38 @@ static void free_pfn_range(u64 paddr, unsigned long size) memtype_free(paddr, paddr + size); } +static int get_pat_info(struct vm_area_struct *vma, resource_size_t *paddr, + pgprot_t *pgprot) +{ + unsigned long prot; + + VM_WARN_ON_ONCE(!(vma->vm_flags & VM_PAT)); + + /* + * We need the starting PFN and cachemode used for track_pfn_remap() + * that covered the whole VMA. For most mappings, we can obtain that + * information from the page tables. For COW mappings, we might now + * suddenly have anon folios mapped and follow_phys() will fail. + * + * Fallback to using vma->vm_pgoff, see remap_pfn_range_notrack(), to + * detect the PFN. If we need the cachemode as well, we're out of luck + * for now and have to fail fork(). + */ + if (!follow_phys(vma, vma->vm_start, 0, &prot, paddr)) { + if (pgprot) + *pgprot = __pgprot(prot); + return 0; + } + if (is_cow_mapping(vma->vm_flags)) { + if (pgprot) + return -EINVAL; + *paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT; + return 0; + } + WARN_ON_ONCE(1); + return -EINVAL; +} + /* * track_pfn_copy is called when vma that is covering the pfnmap gets * copied through copy_page_range(). @@ -957,20 +989,13 @@ static void free_pfn_range(u64 paddr, unsigned long size) int track_pfn_copy(struct vm_area_struct *vma) { resource_size_t paddr; - unsigned long prot; unsigned long vma_size = vma->vm_end - vma->vm_start; pgprot_t pgprot; if (vma->vm_flags & VM_PAT) { - /* - * reserve the whole chunk covered by vma. We need the - * starting address and protection from pte. - */ - if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) { - WARN_ON_ONCE(1); + if (get_pat_info(vma, &paddr, &pgprot)) return -EINVAL; - } - pgprot = __pgprot(prot); + /* reserve the whole chunk covered by vma. */ return reserve_pfn_range(paddr, vma_size, &pgprot, 1); } @@ -1045,7 +1070,6 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, unsigned long size, bool mm_wr_locked) { resource_size_t paddr; - unsigned long prot; if (vma && !(vma->vm_flags & VM_PAT)) return; @@ -1053,11 +1077,8 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, /* free the chunk starting from pfn or the whole chunk */ paddr = (resource_size_t)pfn << PAGE_SHIFT; if (!paddr && !size) { - if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) { - WARN_ON_ONCE(1); + if (get_pat_info(vma, &paddr, NULL)) return; - } - size = vma->vm_end - vma->vm_start; } free_pfn_range(paddr, size); diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index a7ba8e178645..df5fac428408 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -480,7 +480,7 @@ static int emit_call(u8 **pprog, void *func, void *ip) static int emit_rsb_call(u8 **pprog, void *func, void *ip) { OPTIMIZER_HIDE_VAR(func); - x86_call_depth_emit_accounting(pprog, func); + ip += x86_call_depth_emit_accounting(pprog, func, ip); return emit_patch(pprog, func, ip, 0xE8); } @@ -1972,20 +1972,17 @@ st: if (is_imm8(insn->off)) /* call */ case BPF_JMP | BPF_CALL: { - int offs; + u8 *ip = image + addrs[i - 1]; func = (u8 *) __bpf_call_base + imm32; if (tail_call_reachable) { RESTORE_TAIL_CALL_CNT(bpf_prog->aux->stack_depth); - if (!imm32) - return -EINVAL; - offs = 7 + x86_call_depth_emit_accounting(&prog, func); - } else { - if (!imm32) - return -EINVAL; - offs = x86_call_depth_emit_accounting(&prog, func); + ip += 7; } - if (emit_call(&prog, func, image + addrs[i - 1] + offs)) + if (!imm32) + return -EINVAL; + ip += x86_call_depth_emit_accounting(&prog, func, ip); + if (emit_call(&prog, func, ip)) return -EINVAL; break; } @@ -2835,7 +2832,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im * Direct-call fentry stub, as such it needs accounting for the * __fentry__ call. */ - x86_call_depth_emit_accounting(&prog, NULL); + x86_call_depth_emit_accounting(&prog, NULL, image); } EMIT1(0x55); /* push rbp */ EMIT3(0x48, 0x89, 0xE5); /* mov rbp, rsp */ diff --git a/arch/x86/virt/svm/sev.c b/arch/x86/virt/svm/sev.c index cffe1157a90a..ab0e8448bb6e 100644 --- a/arch/x86/virt/svm/sev.c +++ b/arch/x86/virt/svm/sev.c @@ -77,7 +77,7 @@ static int __mfd_enable(unsigned int cpu) { u64 val; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return 0; rdmsrl(MSR_AMD64_SYSCFG, val); @@ -98,7 +98,7 @@ static int __snp_enable(unsigned int cpu) { u64 val; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return 0; rdmsrl(MSR_AMD64_SYSCFG, val); @@ -174,11 +174,11 @@ static int __init snp_rmptable_init(void) u64 rmptable_size; u64 val; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return 0; if (!amd_iommu_snp_en) - return 0; + goto nosnp; if (!probed_rmp_size) goto nosnp; @@ -225,7 +225,7 @@ static int __init snp_rmptable_init(void) return 0; nosnp: - setup_clear_cpu_cap(X86_FEATURE_SEV_SNP); + cc_platform_clear(CC_ATTR_HOST_SEV_SNP); return -ENOSYS; } @@ -246,7 +246,7 @@ static struct rmpentry *__snp_lookup_rmpentry(u64 pfn, int *level) { struct rmpentry *large_entry, *entry; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return ERR_PTR(-ENODEV); entry = get_rmpentry(pfn); @@ -363,7 +363,7 @@ int psmash(u64 pfn) unsigned long paddr = pfn << PAGE_SHIFT; int ret; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return -ENODEV; if (!pfn_valid(pfn)) @@ -472,7 +472,7 @@ static int rmpupdate(u64 pfn, struct rmp_state *state) unsigned long paddr = pfn << PAGE_SHIFT; int ret, level; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return -ENODEV; level = RMP_TO_PG_LEVEL(state->pagesize); @@ -558,3 +558,13 @@ void snp_leak_pages(u64 pfn, unsigned int npages) spin_unlock(&snp_leaked_pages_list_lock); } EXPORT_SYMBOL_GPL(snp_leak_pages); + +void kdump_sev_callback(void) +{ + /* + * Do wbinvd() on remote CPUs when SNP is enabled in order to + * safely do SNP_SHUTDOWN on the local CPU. + */ + if (cc_platform_has(CC_ATTR_HOST_SEV_SNP)) + wbinvd(); +} diff --git a/block/bdev.c b/block/bdev.c index 7a5f611c3d2e..da2a167a4d08 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -583,9 +583,6 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder, mutex_unlock(&bdev->bd_holder_lock); bd_clear_claiming(whole, holder); mutex_unlock(&bdev_lock); - - if (hops && hops->get_holder) - hops->get_holder(holder); } /** @@ -608,7 +605,6 @@ EXPORT_SYMBOL(bd_abort_claiming); static void bd_end_claim(struct block_device *bdev, void *holder) { struct block_device *whole = bdev_whole(bdev); - const struct blk_holder_ops *hops = bdev->bd_holder_ops; bool unblock = false; /* @@ -631,9 +627,6 @@ static void bd_end_claim(struct block_device *bdev, void *holder) whole->bd_holder = NULL; mutex_unlock(&bdev_lock); - if (hops && hops->put_holder) - hops->put_holder(holder); - /* * If this was the last claim, remove holder link and unblock evpoll if * it was a write holder. @@ -652,6 +645,14 @@ static void blkdev_flush_mapping(struct block_device *bdev) bdev_write_inode(bdev); } +static void blkdev_put_whole(struct block_device *bdev) +{ + if (atomic_dec_and_test(&bdev->bd_openers)) + blkdev_flush_mapping(bdev); + if (bdev->bd_disk->fops->release) + bdev->bd_disk->fops->release(bdev->bd_disk); +} + static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode) { struct gendisk *disk = bdev->bd_disk; @@ -670,20 +671,21 @@ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode) if (!atomic_read(&bdev->bd_openers)) set_init_blocksize(bdev); - if (test_bit(GD_NEED_PART_SCAN, &disk->state)) - bdev_disk_changed(disk, false); atomic_inc(&bdev->bd_openers); + if (test_bit(GD_NEED_PART_SCAN, &disk->state)) { + /* + * Only return scanning errors if we are called from contexts + * that explicitly want them, e.g. the BLKRRPART ioctl. + */ + ret = bdev_disk_changed(disk, false); + if (ret && (mode & BLK_OPEN_STRICT_SCAN)) { + blkdev_put_whole(bdev); + return ret; + } + } return 0; } -static void blkdev_put_whole(struct block_device *bdev) -{ - if (atomic_dec_and_test(&bdev->bd_openers)) - blkdev_flush_mapping(bdev); - if (bdev->bd_disk->fops->release) - bdev->bd_disk->fops->release(bdev->bd_disk); -} - static int blkdev_get_part(struct block_device *part, blk_mode_t mode) { struct gendisk *disk = part->bd_disk; @@ -776,17 +778,17 @@ void blkdev_put_no_open(struct block_device *bdev) static bool bdev_writes_blocked(struct block_device *bdev) { - return bdev->bd_writers == -1; + return bdev->bd_writers < 0; } static void bdev_block_writes(struct block_device *bdev) { - bdev->bd_writers = -1; + bdev->bd_writers--; } static void bdev_unblock_writes(struct block_device *bdev) { - bdev->bd_writers = 0; + bdev->bd_writers++; } static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode) @@ -813,6 +815,11 @@ static void bdev_claim_write_access(struct block_device *bdev, blk_mode_t mode) bdev->bd_writers++; } +static inline bool bdev_unclaimed(const struct file *bdev_file) +{ + return bdev_file->private_data == BDEV_I(bdev_file->f_mapping->host); +} + static void bdev_yield_write_access(struct file *bdev_file) { struct block_device *bdev; @@ -820,14 +827,15 @@ static void bdev_yield_write_access(struct file *bdev_file) if (bdev_allow_write_mounted) return; + if (bdev_unclaimed(bdev_file)) + return; + bdev = file_bdev(bdev_file); - /* Yield exclusive or shared write access. */ - if (bdev_file->f_mode & FMODE_WRITE) { - if (bdev_writes_blocked(bdev)) - bdev_unblock_writes(bdev); - else - bdev->bd_writers--; - } + + if (bdev_file->f_mode & FMODE_WRITE_RESTRICTED) + bdev_unblock_writes(bdev); + else if (bdev_file->f_mode & FMODE_WRITE) + bdev->bd_writers--; } /** @@ -874,7 +882,7 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder, goto abort_claiming; ret = -EBUSY; if (!bdev_may_open(bdev, mode)) - goto abort_claiming; + goto put_module; if (bdev_is_partition(bdev)) ret = blkdev_get_part(bdev, mode); else @@ -907,6 +915,8 @@ int bdev_open(struct block_device *bdev, blk_mode_t mode, void *holder, bdev_file->f_mode |= FMODE_BUF_RASYNC | FMODE_CAN_ODIRECT; if (bdev_nowait(bdev)) bdev_file->f_mode |= FMODE_NOWAIT; + if (mode & BLK_OPEN_RESTRICT_WRITES) + bdev_file->f_mode |= FMODE_WRITE_RESTRICTED; bdev_file->f_mapping = bdev->bd_inode->i_mapping; bdev_file->f_wb_err = filemap_sample_wb_err(bdev_file->f_mapping); bdev_file->private_data = holder; @@ -1012,6 +1022,20 @@ struct file *bdev_file_open_by_path(const char *path, blk_mode_t mode, } EXPORT_SYMBOL(bdev_file_open_by_path); +static inline void bd_yield_claim(struct file *bdev_file) +{ + struct block_device *bdev = file_bdev(bdev_file); + void *holder = bdev_file->private_data; + + lockdep_assert_held(&bdev->bd_disk->open_mutex); + + if (WARN_ON_ONCE(IS_ERR_OR_NULL(holder))) + return; + + if (!bdev_unclaimed(bdev_file)) + bd_end_claim(bdev, holder); +} + void bdev_release(struct file *bdev_file) { struct block_device *bdev = file_bdev(bdev_file); @@ -1036,7 +1060,7 @@ void bdev_release(struct file *bdev_file) bdev_yield_write_access(bdev_file); if (holder) - bd_end_claim(bdev, holder); + bd_yield_claim(bdev_file); /* * Trigger event checking and tell drivers to flush MEDIA_CHANGE @@ -1056,6 +1080,39 @@ void bdev_release(struct file *bdev_file) blkdev_put_no_open(bdev); } +/** + * bdev_fput - yield claim to the block device and put the file + * @bdev_file: open block device + * + * Yield claim on the block device and put the file. Ensure that the + * block device can be reclaimed before the file is closed which is a + * deferred operation. + */ +void bdev_fput(struct file *bdev_file) +{ + if (WARN_ON_ONCE(bdev_file->f_op != &def_blk_fops)) + return; + + if (bdev_file->private_data) { + struct block_device *bdev = file_bdev(bdev_file); + struct gendisk *disk = bdev->bd_disk; + + mutex_lock(&disk->open_mutex); + bdev_yield_write_access(bdev_file); + bd_yield_claim(bdev_file); + /* + * Tell release we already gave up our hold on the + * device and if write restrictions are available that + * we already gave up write access to the device. + */ + bdev_file->private_data = BDEV_I(bdev_file->f_mapping->host); + mutex_unlock(&disk->open_mutex); + } + + fput(bdev_file); +} +EXPORT_SYMBOL(bdev_fput); + /** * lookup_bdev() - Look up a struct block_device by name. * @pathname: Name of the block device in the filesystem. diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index bdbb557feb5a..059467086b13 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1409,6 +1409,12 @@ static int blkcg_css_online(struct cgroup_subsys_state *css) return 0; } +void blkg_init_queue(struct request_queue *q) +{ + INIT_LIST_HEAD(&q->blkg_list); + mutex_init(&q->blkcg_mutex); +} + int blkcg_init_disk(struct gendisk *disk) { struct request_queue *q = disk->queue; @@ -1416,9 +1422,6 @@ int blkcg_init_disk(struct gendisk *disk) bool preloaded; int ret; - INIT_LIST_HEAD(&q->blkg_list); - mutex_init(&q->blkcg_mutex); - new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL); if (!new_blkg) return -ENOMEM; diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 78b74106bf10..90b3959d88cf 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -189,6 +189,7 @@ struct blkcg_policy { extern struct blkcg blkcg_root; extern bool blkcg_debug_stats; +void blkg_init_queue(struct request_queue *q); int blkcg_init_disk(struct gendisk *disk); void blkcg_exit_disk(struct gendisk *disk); @@ -482,6 +483,7 @@ struct blkcg { }; static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; } +static inline void blkg_init_queue(struct request_queue *q) { } static inline int blkcg_init_disk(struct gendisk *disk) { return 0; } static inline void blkcg_exit_disk(struct gendisk *disk) { } static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; } diff --git a/block/blk-core.c b/block/blk-core.c index a16b5abdbbf5..b795ac177281 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -442,6 +442,8 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id) init_waitqueue_head(&q->mq_freeze_wq); mutex_init(&q->mq_freeze_lock); + blkg_init_queue(q); + /* * Init percpu_ref in atomic mode so that it's faster to shutdown. * See blk_register_queue() for details. @@ -1195,6 +1197,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule) if (unlikely(!rq_list_empty(plug->cached_rq))) blk_mq_free_plug_rqs(plug); + plug->cur_ktime = 0; current->flags &= ~PF_BLOCK_TS; } diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 9a85bfbbc45a..690ca99dfaca 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) { struct ioc *ioc = iocg->ioc; struct blkcg_gq *blkg = iocg_to_blkg(iocg); - u64 tdelta, delay, new_delay; + u64 tdelta, delay, new_delay, shift; s64 vover, vover_pct; u32 hwa; @@ -1362,8 +1362,9 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) /* calculate the current delay in effect - 1/2 every second */ tdelta = now->now - iocg->delay_at; - if (iocg->delay) - delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC); + shift = div64_u64(tdelta, USEC_PER_SEC); + if (iocg->delay && shift < BITS_PER_LONG) + delay = iocg->delay >> shift; else delay = 0; @@ -1438,8 +1439,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay, lockdep_assert_held(&iocg->ioc->lock); lockdep_assert_held(&iocg->waitq.lock); - /* make sure that nobody messed with @iocg */ - WARN_ON_ONCE(list_empty(&iocg->active_list)); + /* + * make sure that nobody messed with @iocg. Check iocg->pd.online + * to avoid warn when removing blkcg or disk. + */ + WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online); WARN_ON_ONCE(iocg->inuse > 1); iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt); diff --git a/block/blk-settings.c b/block/blk-settings.c index cdbaef159c4b..d2731843f2fc 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -182,17 +182,13 @@ static int blk_validate_limits(struct queue_limits *lim) return -EINVAL; /* - * Devices that require a virtual boundary do not support scatter/gather - * I/O natively, but instead require a descriptor list entry for each - * page (which might not be identical to the Linux PAGE_SIZE). Because - * of that they are not limited by our notion of "segment size". + * Stacking device may have both virtual boundary and max segment + * size limit, so allow this setting now, and long-term the two + * might need to move out of stacking limits since we have immutable + * bvec and lower layer bio splitting is supposed to handle the two + * correctly. */ - if (lim->virt_boundary_mask) { - if (WARN_ON_ONCE(lim->max_segment_size && - lim->max_segment_size != UINT_MAX)) - return -EINVAL; - lim->max_segment_size = UINT_MAX; - } else { + if (!lim->virt_boundary_mask) { /* * The maximum segment size has an odd historic 64k default that * drivers probably should override. Just like the I/O size we diff --git a/block/ioctl.c b/block/ioctl.c index 0c76137adcaa..f505f9c341eb 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -96,7 +96,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, unsigned long arg) { uint64_t range[2]; - uint64_t start, len; + uint64_t start, len, end; struct inode *inode = bdev->bd_inode; int err; @@ -117,7 +117,8 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode, if (len & 511) return -EINVAL; - if (start + len > bdev_nr_bytes(bdev)) + if (check_add_overflow(start, len, &end) || + end > bdev_nr_bytes(bdev)) return -EINVAL; filemap_invalidate_lock(inode->i_mapping); @@ -562,7 +563,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode, return -EACCES; if (bdev_is_partition(bdev)) return -EINVAL; - return disk_scan_partitions(bdev->bd_disk, mode); + return disk_scan_partitions(bdev->bd_disk, + mode | BLK_OPEN_STRICT_SCAN); case BLKTRACESTART: case BLKTRACESTOP: case BLKTRACETEARDOWN: diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c index d09d29775b3f..e07e447d08d1 100644 --- a/drivers/accel/ivpu/ivpu_debugfs.c +++ b/drivers/accel/ivpu/ivpu_debugfs.c @@ -3,6 +3,8 @@ * Copyright (C) 2020-2023 Intel Corporation */ +#include + #include #include #include diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 39f6d1b98fd6..51d3f1a55d02 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -131,22 +131,6 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param return 0; } -static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate) -{ - int ret; - - ret = ivpu_rpm_get_if_active(vdev); - if (ret < 0) - return ret; - - *clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0; - - if (ret) - ivpu_rpm_put(vdev); - - return 0; -} - static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct ivpu_file_priv *file_priv = file->driver_priv; @@ -170,7 +154,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f args->value = vdev->platform; break; case DRM_IVPU_PARAM_CORE_CLOCK_RATE: - ret = ivpu_get_core_clock_rate(vdev, &args->value); + args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio); break; case DRM_IVPU_PARAM_NUM_CONTEXTS: args->value = ivpu_get_context_count(vdev); @@ -387,12 +371,15 @@ int ivpu_shutdown(struct ivpu_device *vdev) { int ret; - ivpu_prepare_for_reset(vdev); + /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */ + pci_save_state(to_pci_dev(vdev->drm.dev)); ret = ivpu_hw_power_down(vdev); if (ret) ivpu_warn(vdev, "Failed to power down HW: %d\n", ret); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); + return ret; } @@ -530,7 +517,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev) vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID; vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID; atomic64_set(&vdev->unique_id_counter, 0); - xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC); + xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1); xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1); lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); @@ -560,11 +547,11 @@ static int ivpu_dev_init(struct ivpu_device *vdev) /* Power up early so the rest of init code can access VPU registers */ ret = ivpu_hw_power_up(vdev); if (ret) - goto err_power_down; + goto err_shutdown; ret = ivpu_mmu_global_context_init(vdev); if (ret) - goto err_power_down; + goto err_shutdown; ret = ivpu_mmu_init(vdev); if (ret) @@ -601,10 +588,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev) ivpu_mmu_reserved_context_fini(vdev); err_mmu_gctx_fini: ivpu_mmu_global_context_fini(vdev); -err_power_down: - ivpu_hw_power_down(vdev); - if (IVPU_WA(d3hot_after_power_off)) - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); +err_shutdown: + ivpu_shutdown(vdev); err_xa_destroy: xa_destroy(&vdev->db_xa); xa_destroy(&vdev->submitted_jobs_xa); @@ -628,9 +613,8 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev) static void ivpu_dev_fini(struct ivpu_device *vdev) { ivpu_pm_disable(vdev); + ivpu_prepare_for_reset(vdev); ivpu_shutdown(vdev); - if (IVPU_WA(d3hot_after_power_off)) - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); ivpu_jobs_abort_all(vdev); ivpu_job_done_consumer_fini(vdev); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 7be0500d9bb8..bb4374d0eaec 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_DRV_H__ @@ -90,7 +90,6 @@ struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; - bool d3hot_after_power_off; bool interrupt_clear_with_0; bool disable_clock_relinquish; bool disable_d0i3_msg; diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index b2909168a0a6..094c659d2800 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -21,6 +21,7 @@ struct ivpu_hw_ops { u32 (*profiling_freq_get)(struct ivpu_device *vdev); void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable); u32 (*reg_pll_freq_get)(struct ivpu_device *vdev); + u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio); u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev); u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev); u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev); @@ -130,6 +131,11 @@ static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev) return vdev->hw->ops->reg_pll_freq_get(vdev); }; +static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) +{ + return vdev->hw->ops->ratio_to_freq(vdev, ratio); +} + static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev) { return vdev->hw->ops->reg_telemetry_offset_get(vdev); diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 9a0c9498baba..bd25e2d9fb0f 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include "ivpu_drv.h" @@ -75,7 +75,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) { vdev->wa.punit_disabled = false; vdev->wa.clear_runtime_mem = false; - vdev->wa.d3hot_after_power_off = true; REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK); if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) { @@ -86,7 +85,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) IVPU_PRINT_WA(punit_disabled); IVPU_PRINT_WA(clear_runtime_mem); - IVPU_PRINT_WA(d3hot_after_power_off); IVPU_PRINT_WA(interrupt_clear_with_0); } @@ -805,12 +803,12 @@ static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool ena /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */ } -static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config) +static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) { u32 pll_clock = PLL_REF_CLK_FREQ * ratio; u32 cpu_clock; - if ((config & 0xff) == PLL_RATIO_4_3) + if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3) cpu_clock = pll_clock * 2 / 4; else cpu_clock = pll_clock * 2 / 5; @@ -829,7 +827,7 @@ static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev) if (!ivpu_is_silicon(vdev)) return PLL_SIMULATION_FREQ; - return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config); + return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio); } static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev) @@ -1052,6 +1050,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = { .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get, .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive, .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get, + .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq, .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get, .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get, .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get, diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index e4eddbf5d11c..b0b88d4c8926 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -980,6 +980,11 @@ static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev) return PLL_RATIO_TO_FREQ(pll_curr_ratio); } +static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) +{ + return PLL_RATIO_TO_FREQ(ratio); +} + static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev) { return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET); @@ -1230,6 +1235,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = { .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get, .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive, .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get, + .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq, .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get, .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get, .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get, diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 04ac4b9840fb..56ff067f63e2 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -501,7 +501,11 @@ int ivpu_ipc_init(struct ivpu_device *vdev) spin_lock_init(&ipc->cons_lock); INIT_LIST_HEAD(&ipc->cons_list); INIT_LIST_HEAD(&ipc->cb_msg_list); - drmm_mutex_init(&vdev->drm, &ipc->lock); + ret = drmm_mutex_init(&vdev->drm, &ipc->lock); + if (ret) { + ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret); + goto err_free_rx; + } ivpu_ipc_reset(vdev); return 0; diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 91bd640655ab..2e46b322c450 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -278,7 +278,7 @@ static const char *ivpu_mmu_event_to_str(u32 cmd) case IVPU_MMU_EVT_F_VMS_FETCH: return "Fetch of VMS caused external abort"; default: - return "Unknown CMDQ command"; + return "Unknown event"; } } @@ -286,15 +286,15 @@ static const char *ivpu_mmu_cmdq_err_to_str(u32 err) { switch (err) { case IVPU_MMU_CERROR_NONE: - return "No CMDQ Error"; + return "No error"; case IVPU_MMU_CERROR_ILL: return "Illegal command"; case IVPU_MMU_CERROR_ABT: - return "External abort on CMDQ read"; + return "External abort on command queue read"; case IVPU_MMU_CERROR_ATC_INV_SYNC: return "Sync failed to complete ATS invalidation"; default: - return "Unknown CMDQ Error"; + return "Unknown error"; } } diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 7cce1c928a7f..4f5ea466731f 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -58,14 +58,11 @@ static int ivpu_suspend(struct ivpu_device *vdev) { int ret; - /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */ - pci_save_state(to_pci_dev(vdev->drm.dev)); + ivpu_prepare_for_reset(vdev); ret = ivpu_shutdown(vdev); if (ret) - ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret); - - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); + ivpu_err(vdev, "Failed to shutdown NPU: %d\n", ret); return ret; } @@ -74,10 +71,10 @@ static int ivpu_resume(struct ivpu_device *vdev) { int ret; - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0); - pci_restore_state(to_pci_dev(vdev->drm.dev)); - retry: + pci_restore_state(to_pci_dev(vdev->drm.dev)); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0); + ret = ivpu_hw_power_up(vdev); if (ret) { ivpu_err(vdev, "Failed to power up HW: %d\n", ret); @@ -100,6 +97,7 @@ static int ivpu_resume(struct ivpu_device *vdev) ivpu_mmu_disable(vdev); err_power_down: ivpu_hw_power_down(vdev); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); if (!ivpu_fw_is_cold_boot(vdev)) { ivpu_pm_prepare_cold_boot(vdev); diff --git a/drivers/accel/qaic/Makefile b/drivers/accel/qaic/Makefile index 2cadcc1baa0e..35e883515629 100644 --- a/drivers/accel/qaic/Makefile +++ b/drivers/accel/qaic/Makefile @@ -10,6 +10,7 @@ qaic-y := \ qaic_control.o \ qaic_data.o \ qaic_drv.o \ - qaic_timesync.o + qaic_timesync.o \ + sahara.o qaic-$(CONFIG_DEBUG_FS) += qaic_debugfs.o diff --git a/drivers/accel/qaic/qaic_debugfs.h b/drivers/accel/qaic/qaic_debugfs.h index ea3fd1a88405..05e74f84cf9f 100644 --- a/drivers/accel/qaic/qaic_debugfs.h +++ b/drivers/accel/qaic/qaic_debugfs.h @@ -13,8 +13,8 @@ int qaic_bootlog_register(void); void qaic_bootlog_unregister(void); void qaic_debugfs_init(struct qaic_drm_device *qddev); #else -int qaic_bootlog_register(void) { return 0; } -void qaic_bootlog_unregister(void) {} -void qaic_debugfs_init(struct qaic_drm_device *qddev) {} +static inline int qaic_bootlog_register(void) { return 0; } +static inline void qaic_bootlog_unregister(void) {} +static inline void qaic_debugfs_init(struct qaic_drm_device *qddev) {} #endif /* CONFIG_DEBUG_FS */ #endif /* __QAIC_DEBUGFS_H__ */ diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index f072edb74f22..580b29ed1902 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -30,6 +30,7 @@ #include "qaic.h" #include "qaic_debugfs.h" #include "qaic_timesync.h" +#include "sahara.h" MODULE_IMPORT_NS(DMA_BUF); @@ -644,6 +645,12 @@ static int __init qaic_init(void) goto free_pci; } + ret = sahara_register(); + if (ret) { + pr_debug("qaic: sahara_register failed %d\n", ret); + goto free_mhi; + } + ret = qaic_timesync_init(); if (ret) pr_debug("qaic: qaic_timesync_init failed %d\n", ret); @@ -654,6 +661,8 @@ static int __init qaic_init(void) return 0; +free_mhi: + mhi_driver_unregister(&qaic_mhi_driver); free_pci: pci_unregister_driver(&qaic_pci_driver); return ret; @@ -679,6 +688,7 @@ static void __exit qaic_exit(void) link_up = true; qaic_bootlog_unregister(); qaic_timesync_deinit(); + sahara_unregister(); mhi_driver_unregister(&qaic_mhi_driver); pci_unregister_driver(&qaic_pci_driver); } diff --git a/drivers/accel/qaic/sahara.c b/drivers/accel/qaic/sahara.c new file mode 100644 index 000000000000..bf94bbab6be5 --- /dev/null +++ b/drivers/accel/qaic/sahara.c @@ -0,0 +1,449 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sahara.h" + +#define SAHARA_HELLO_CMD 0x1 /* Min protocol version 1.0 */ +#define SAHARA_HELLO_RESP_CMD 0x2 /* Min protocol version 1.0 */ +#define SAHARA_READ_DATA_CMD 0x3 /* Min protocol version 1.0 */ +#define SAHARA_END_OF_IMAGE_CMD 0x4 /* Min protocol version 1.0 */ +#define SAHARA_DONE_CMD 0x5 /* Min protocol version 1.0 */ +#define SAHARA_DONE_RESP_CMD 0x6 /* Min protocol version 1.0 */ +#define SAHARA_RESET_CMD 0x7 /* Min protocol version 1.0 */ +#define SAHARA_RESET_RESP_CMD 0x8 /* Min protocol version 1.0 */ +#define SAHARA_MEM_DEBUG_CMD 0x9 /* Min protocol version 2.0 */ +#define SAHARA_MEM_READ_CMD 0xa /* Min protocol version 2.0 */ +#define SAHARA_CMD_READY_CMD 0xb /* Min protocol version 2.1 */ +#define SAHARA_SWITCH_MODE_CMD 0xc /* Min protocol version 2.1 */ +#define SAHARA_EXECUTE_CMD 0xd /* Min protocol version 2.1 */ +#define SAHARA_EXECUTE_RESP_CMD 0xe /* Min protocol version 2.1 */ +#define SAHARA_EXECUTE_DATA_CMD 0xf /* Min protocol version 2.1 */ +#define SAHARA_MEM_DEBUG64_CMD 0x10 /* Min protocol version 2.5 */ +#define SAHARA_MEM_READ64_CMD 0x11 /* Min protocol version 2.5 */ +#define SAHARA_READ_DATA64_CMD 0x12 /* Min protocol version 2.8 */ +#define SAHARA_RESET_STATE_CMD 0x13 /* Min protocol version 2.9 */ +#define SAHARA_WRITE_DATA_CMD 0x14 /* Min protocol version 3.0 */ + +#define SAHARA_PACKET_MAX_SIZE 0xffffU /* MHI_MAX_MTU */ +#define SAHARA_TRANSFER_MAX_SIZE 0x80000 +#define SAHARA_NUM_TX_BUF DIV_ROUND_UP(SAHARA_TRANSFER_MAX_SIZE,\ + SAHARA_PACKET_MAX_SIZE) +#define SAHARA_IMAGE_ID_NONE U32_MAX + +#define SAHARA_VERSION 2 +#define SAHARA_SUCCESS 0 + +#define SAHARA_MODE_IMAGE_TX_PENDING 0x0 +#define SAHARA_MODE_IMAGE_TX_COMPLETE 0x1 +#define SAHARA_MODE_MEMORY_DEBUG 0x2 +#define SAHARA_MODE_COMMAND 0x3 + +#define SAHARA_HELLO_LENGTH 0x30 +#define SAHARA_READ_DATA_LENGTH 0x14 +#define SAHARA_END_OF_IMAGE_LENGTH 0x10 +#define SAHARA_DONE_LENGTH 0x8 +#define SAHARA_RESET_LENGTH 0x8 + +struct sahara_packet { + __le32 cmd; + __le32 length; + + union { + struct { + __le32 version; + __le32 version_compat; + __le32 max_length; + __le32 mode; + } hello; + struct { + __le32 version; + __le32 version_compat; + __le32 status; + __le32 mode; + } hello_resp; + struct { + __le32 image; + __le32 offset; + __le32 length; + } read_data; + struct { + __le32 image; + __le32 status; + } end_of_image; + }; +}; + +struct sahara_context { + struct sahara_packet *tx[SAHARA_NUM_TX_BUF]; + struct sahara_packet *rx; + struct work_struct work; + struct mhi_device *mhi_dev; + const char **image_table; + u32 table_size; + u32 active_image_id; + const struct firmware *firmware; +}; + +static const char *aic100_image_table[] = { + [1] = "qcom/aic100/fw1.bin", + [2] = "qcom/aic100/fw2.bin", + [4] = "qcom/aic100/fw4.bin", + [5] = "qcom/aic100/fw5.bin", + [6] = "qcom/aic100/fw6.bin", + [8] = "qcom/aic100/fw8.bin", + [9] = "qcom/aic100/fw9.bin", + [10] = "qcom/aic100/fw10.bin", +}; + +static int sahara_find_image(struct sahara_context *context, u32 image_id) +{ + int ret; + + if (image_id == context->active_image_id) + return 0; + + if (context->active_image_id != SAHARA_IMAGE_ID_NONE) { + dev_err(&context->mhi_dev->dev, "image id %d is not valid as %d is active\n", + image_id, context->active_image_id); + return -EINVAL; + } + + if (image_id >= context->table_size || !context->image_table[image_id]) { + dev_err(&context->mhi_dev->dev, "request for unknown image: %d\n", image_id); + return -EINVAL; + } + + /* + * This image might be optional. The device may continue without it. + * Only the device knows. Suppress error messages that could suggest an + * a problem when we were actually able to continue. + */ + ret = firmware_request_nowarn(&context->firmware, + context->image_table[image_id], + &context->mhi_dev->dev); + if (ret) { + dev_dbg(&context->mhi_dev->dev, "request for image id %d / file %s failed %d\n", + image_id, context->image_table[image_id], ret); + return ret; + } + + context->active_image_id = image_id; + + return 0; +} + +static void sahara_release_image(struct sahara_context *context) +{ + if (context->active_image_id != SAHARA_IMAGE_ID_NONE) + release_firmware(context->firmware); + context->active_image_id = SAHARA_IMAGE_ID_NONE; +} + +static void sahara_send_reset(struct sahara_context *context) +{ + int ret; + + context->tx[0]->cmd = cpu_to_le32(SAHARA_RESET_CMD); + context->tx[0]->length = cpu_to_le32(SAHARA_RESET_LENGTH); + + ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0], + SAHARA_RESET_LENGTH, MHI_EOT); + if (ret) + dev_err(&context->mhi_dev->dev, "Unable to send reset response %d\n", ret); +} + +static void sahara_hello(struct sahara_context *context) +{ + int ret; + + dev_dbg(&context->mhi_dev->dev, + "HELLO cmd received. length:%d version:%d version_compat:%d max_length:%d mode:%d\n", + le32_to_cpu(context->rx->length), + le32_to_cpu(context->rx->hello.version), + le32_to_cpu(context->rx->hello.version_compat), + le32_to_cpu(context->rx->hello.max_length), + le32_to_cpu(context->rx->hello.mode)); + + if (le32_to_cpu(context->rx->length) != SAHARA_HELLO_LENGTH) { + dev_err(&context->mhi_dev->dev, "Malformed hello packet - length %d\n", + le32_to_cpu(context->rx->length)); + return; + } + if (le32_to_cpu(context->rx->hello.version) != SAHARA_VERSION) { + dev_err(&context->mhi_dev->dev, "Unsupported hello packet - version %d\n", + le32_to_cpu(context->rx->hello.version)); + return; + } + + if (le32_to_cpu(context->rx->hello.mode) != SAHARA_MODE_IMAGE_TX_PENDING && + le32_to_cpu(context->rx->hello.mode) != SAHARA_MODE_IMAGE_TX_COMPLETE) { + dev_err(&context->mhi_dev->dev, "Unsupported hello packet - mode %d\n", + le32_to_cpu(context->rx->hello.mode)); + return; + } + + context->tx[0]->cmd = cpu_to_le32(SAHARA_HELLO_RESP_CMD); + context->tx[0]->length = cpu_to_le32(SAHARA_HELLO_LENGTH); + context->tx[0]->hello_resp.version = cpu_to_le32(SAHARA_VERSION); + context->tx[0]->hello_resp.version_compat = cpu_to_le32(SAHARA_VERSION); + context->tx[0]->hello_resp.status = cpu_to_le32(SAHARA_SUCCESS); + context->tx[0]->hello_resp.mode = context->rx->hello_resp.mode; + + ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0], + SAHARA_HELLO_LENGTH, MHI_EOT); + if (ret) + dev_err(&context->mhi_dev->dev, "Unable to send hello response %d\n", ret); +} + +static void sahara_read_data(struct sahara_context *context) +{ + u32 image_id, data_offset, data_len, pkt_data_len; + int ret; + int i; + + dev_dbg(&context->mhi_dev->dev, + "READ_DATA cmd received. length:%d image:%d offset:%d data_length:%d\n", + le32_to_cpu(context->rx->length), + le32_to_cpu(context->rx->read_data.image), + le32_to_cpu(context->rx->read_data.offset), + le32_to_cpu(context->rx->read_data.length)); + + if (le32_to_cpu(context->rx->length) != SAHARA_READ_DATA_LENGTH) { + dev_err(&context->mhi_dev->dev, "Malformed read_data packet - length %d\n", + le32_to_cpu(context->rx->length)); + return; + } + + image_id = le32_to_cpu(context->rx->read_data.image); + data_offset = le32_to_cpu(context->rx->read_data.offset); + data_len = le32_to_cpu(context->rx->read_data.length); + + ret = sahara_find_image(context, image_id); + if (ret) { + sahara_send_reset(context); + return; + } + + /* + * Image is released when the device is done with it via + * SAHARA_END_OF_IMAGE_CMD. sahara_send_reset() will either cause the + * device to retry the operation with a modification, or decide to be + * done with the image and trigger SAHARA_END_OF_IMAGE_CMD. + * release_image() is called from SAHARA_END_OF_IMAGE_CMD. processing + * and is not needed here on error. + */ + + if (data_len > SAHARA_TRANSFER_MAX_SIZE) { + dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data len %d exceeds max xfer size %d\n", + data_len, SAHARA_TRANSFER_MAX_SIZE); + sahara_send_reset(context); + return; + } + + if (data_offset >= context->firmware->size) { + dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data offset %d exceeds file size %zu\n", + data_offset, context->firmware->size); + sahara_send_reset(context); + return; + } + + if (size_add(data_offset, data_len) > context->firmware->size) { + dev_err(&context->mhi_dev->dev, "Malformed read_data packet - data offset %d and length %d exceeds file size %zu\n", + data_offset, data_len, context->firmware->size); + sahara_send_reset(context); + return; + } + + for (i = 0; i < SAHARA_NUM_TX_BUF && data_len; ++i) { + pkt_data_len = min(data_len, SAHARA_PACKET_MAX_SIZE); + + memcpy(context->tx[i], &context->firmware->data[data_offset], pkt_data_len); + + data_offset += pkt_data_len; + data_len -= pkt_data_len; + + ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, + context->tx[i], pkt_data_len, + !data_len ? MHI_EOT : MHI_CHAIN); + if (ret) { + dev_err(&context->mhi_dev->dev, "Unable to send read_data response %d\n", + ret); + return; + } + } +} + +static void sahara_end_of_image(struct sahara_context *context) +{ + int ret; + + dev_dbg(&context->mhi_dev->dev, + "END_OF_IMAGE cmd received. length:%d image:%d status:%d\n", + le32_to_cpu(context->rx->length), + le32_to_cpu(context->rx->end_of_image.image), + le32_to_cpu(context->rx->end_of_image.status)); + + if (le32_to_cpu(context->rx->length) != SAHARA_END_OF_IMAGE_LENGTH) { + dev_err(&context->mhi_dev->dev, "Malformed end_of_image packet - length %d\n", + le32_to_cpu(context->rx->length)); + return; + } + + if (context->active_image_id != SAHARA_IMAGE_ID_NONE && + le32_to_cpu(context->rx->end_of_image.image) != context->active_image_id) { + dev_err(&context->mhi_dev->dev, "Malformed end_of_image packet - image %d is not the active image\n", + le32_to_cpu(context->rx->end_of_image.image)); + return; + } + + sahara_release_image(context); + + if (le32_to_cpu(context->rx->end_of_image.status)) + return; + + context->tx[0]->cmd = cpu_to_le32(SAHARA_DONE_CMD); + context->tx[0]->length = cpu_to_le32(SAHARA_DONE_LENGTH); + + ret = mhi_queue_buf(context->mhi_dev, DMA_TO_DEVICE, context->tx[0], + SAHARA_DONE_LENGTH, MHI_EOT); + if (ret) + dev_dbg(&context->mhi_dev->dev, "Unable to send done response %d\n", ret); +} + +static void sahara_processing(struct work_struct *work) +{ + struct sahara_context *context = container_of(work, struct sahara_context, work); + int ret; + + switch (le32_to_cpu(context->rx->cmd)) { + case SAHARA_HELLO_CMD: + sahara_hello(context); + break; + case SAHARA_READ_DATA_CMD: + sahara_read_data(context); + break; + case SAHARA_END_OF_IMAGE_CMD: + sahara_end_of_image(context); + break; + case SAHARA_DONE_RESP_CMD: + /* Intentional do nothing as we don't need to exit an app */ + break; + default: + dev_err(&context->mhi_dev->dev, "Unknown command %d\n", + le32_to_cpu(context->rx->cmd)); + break; + } + + ret = mhi_queue_buf(context->mhi_dev, DMA_FROM_DEVICE, context->rx, + SAHARA_PACKET_MAX_SIZE, MHI_EOT); + if (ret) + dev_err(&context->mhi_dev->dev, "Unable to requeue rx buf %d\n", ret); +} + +static int sahara_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) +{ + struct sahara_context *context; + int ret; + int i; + + context = devm_kzalloc(&mhi_dev->dev, sizeof(*context), GFP_KERNEL); + if (!context) + return -ENOMEM; + + context->rx = devm_kzalloc(&mhi_dev->dev, SAHARA_PACKET_MAX_SIZE, GFP_KERNEL); + if (!context->rx) + return -ENOMEM; + + /* + * AIC100 defines SAHARA_TRANSFER_MAX_SIZE as the largest value it + * will request for READ_DATA. This is larger than + * SAHARA_PACKET_MAX_SIZE, and we need 9x SAHARA_PACKET_MAX_SIZE to + * cover SAHARA_TRANSFER_MAX_SIZE. When the remote side issues a + * READ_DATA, it requires a transfer of the exact size requested. We + * can use MHI_CHAIN to link multiple buffers into a single transfer + * but the remote side will not consume the buffers until it sees an + * EOT, thus we need to allocate enough buffers to put in the tx fifo + * to cover an entire READ_DATA request of the max size. + */ + for (i = 0; i < SAHARA_NUM_TX_BUF; ++i) { + context->tx[i] = devm_kzalloc(&mhi_dev->dev, SAHARA_PACKET_MAX_SIZE, GFP_KERNEL); + if (!context->tx[i]) + return -ENOMEM; + } + + context->mhi_dev = mhi_dev; + INIT_WORK(&context->work, sahara_processing); + context->image_table = aic100_image_table; + context->table_size = ARRAY_SIZE(aic100_image_table); + context->active_image_id = SAHARA_IMAGE_ID_NONE; + dev_set_drvdata(&mhi_dev->dev, context); + + ret = mhi_prepare_for_transfer(mhi_dev); + if (ret) + return ret; + + ret = mhi_queue_buf(mhi_dev, DMA_FROM_DEVICE, context->rx, SAHARA_PACKET_MAX_SIZE, MHI_EOT); + if (ret) { + mhi_unprepare_from_transfer(mhi_dev); + return ret; + } + + return 0; +} + +static void sahara_mhi_remove(struct mhi_device *mhi_dev) +{ + struct sahara_context *context = dev_get_drvdata(&mhi_dev->dev); + + cancel_work_sync(&context->work); + sahara_release_image(context); + mhi_unprepare_from_transfer(mhi_dev); +} + +static void sahara_mhi_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) +{ +} + +static void sahara_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result) +{ + struct sahara_context *context = dev_get_drvdata(&mhi_dev->dev); + + if (!mhi_result->transaction_status) + schedule_work(&context->work); +} + +static const struct mhi_device_id sahara_mhi_match_table[] = { + { .chan = "QAIC_SAHARA", }, + {}, +}; + +static struct mhi_driver sahara_mhi_driver = { + .id_table = sahara_mhi_match_table, + .remove = sahara_mhi_remove, + .probe = sahara_mhi_probe, + .ul_xfer_cb = sahara_mhi_ul_xfer_cb, + .dl_xfer_cb = sahara_mhi_dl_xfer_cb, + .driver = { + .name = "sahara", + }, +}; + +int sahara_register(void) +{ + return mhi_driver_register(&sahara_mhi_driver); +} + +void sahara_unregister(void) +{ + mhi_driver_unregister(&sahara_mhi_driver); +} diff --git a/drivers/accel/qaic/sahara.h b/drivers/accel/qaic/sahara.h new file mode 100644 index 000000000000..640208acc0d1 --- /dev/null +++ b/drivers/accel/qaic/sahara.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. */ + +#ifndef __SAHARA_H__ +#define __SAHARA_H__ + +int sahara_register(void); +void sahara_unregister(void); +#endif /* __SAHARA_H__ */ diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index 1fbc9b921c4f..736c2eb8c0f3 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc) } attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); buf[cnt++] = attr_ch; - while (tmpx < vc->vc_cols - 1) { + while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) { tmp_pos += 2; tmpx++; ch = get_char(vc, (u_short *)tmp_pos, &temp); diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 4bfbe55553f4..a40b6f3946ef 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -170,8 +170,8 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time); #define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width) /* Shift and apply the mask for CPC reads/writes */ -#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset & \ - GENMASK(((reg)->bit_width), 0))) +#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) & \ + GENMASK(((reg)->bit_width) - 1, 0)) static ssize_t show_feedback_ctrs(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -1002,14 +1002,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) } *val = 0; + size = GET_BIT_WIDTH(reg); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - u32 width = GET_BIT_WIDTH(reg); u32 val_u32; acpi_status status; status = acpi_os_read_port((acpi_io_address)reg->address, - &val_u32, width); + &val_u32, size); if (ACPI_FAILURE(status)) { pr_debug("Error: Failed to read SystemIO port %llx\n", reg->address); @@ -1018,17 +1018,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) *val = val_u32; return 0; - } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) { + /* + * For registers in PCC space, the register size is determined + * by the bit width field; the access size is used to indicate + * the PCC subspace id. + */ + size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) return cpc_read_ffh(cpu, reg, val); else return acpi_os_read_memory((acpi_physical_address)reg->address, - val, reg->bit_width); - - size = GET_BIT_WIDTH(reg); + val, size); switch (size) { case 8: @@ -1044,8 +1049,13 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) *val = readq_relaxed(vaddr); break; default: - pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n", - reg->bit_width, pcc_ss_id); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n", + size, reg->address); + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n", + size, pcc_ss_id); + } return -EFAULT; } @@ -1063,12 +1073,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); struct cpc_reg *reg = ®_res->cpc_entry.reg; + size = GET_BIT_WIDTH(reg); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - u32 width = GET_BIT_WIDTH(reg); acpi_status status; status = acpi_os_write_port((acpi_io_address)reg->address, - (u32)val, width); + (u32)val, size); if (ACPI_FAILURE(status)) { pr_debug("Error: Failed to write SystemIO port %llx\n", reg->address); @@ -1076,17 +1087,22 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) } return 0; - } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) { + /* + * For registers in PCC space, the register size is determined + * by the bit width field; the access size is used to indicate + * the PCC subspace id. + */ + size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) return cpc_write_ffh(cpu, reg, val); else return acpi_os_write_memory((acpi_physical_address)reg->address, - val, reg->bit_width); - - size = GET_BIT_WIDTH(reg); + val, size); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) val = MASK_VAL(reg, val); @@ -1105,8 +1121,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) writeq_relaxed(val, vaddr); break; default: - pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n", - reg->bit_width, pcc_ss_id); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n", + size, reg->address); + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n", + size, pcc_ss_id); + } ret_val = -EFAULT; break; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7c157bf92695..d1464324de95 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1843,7 +1843,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev) if (dep->honor_dep) adev->flags.honor_deps = 1; - adev->dep_unmet++; + if (!dep->met) + adev->dep_unmet++; } } } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 302dce0b2b50..d67881b50bca 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -662,14 +662,15 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz, { int result; - tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz", - trip_table, - trip_count, - tz, - &acpi_thermal_zone_ops, - NULL, - passive_delay, - tz->polling_frequency * 100); + if (trip_count) + tz->thermal_zone = thermal_zone_device_register_with_trips( + "acpitz", trip_table, trip_count, tz, + &acpi_thermal_zone_ops, NULL, passive_delay, + tz->polling_frequency * 100); + else + tz->thermal_zone = thermal_tripless_zone_device_register( + "acpitz", tz, &acpi_thermal_zone_ops, NULL); + if (IS_ERR(tz->thermal_zone)) return PTR_ERR(tz->thermal_zone); @@ -901,11 +902,8 @@ static int acpi_thermal_add(struct acpi_device *device) trip++; } - if (trip == trip_table) { + if (trip == trip_table) pr_warn(FW_BUG "No valid trip points!\n"); - result = -ENODEV; - goto free_memory; - } result = acpi_thermal_register_thermal_zone(tz, trip_table, trip - trip_table, diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index cd84af23f7ea..dd0b40b9bbe8 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -492,16 +492,14 @@ static int lps0_device_attach(struct acpi_device *adev, unsigned int func_mask; /* - * Avoid evaluating the same _DSM function for two - * different UUIDs and prioritize the MSFT one. + * Log a message if the _DSM function sets for two + * different UUIDs overlap. */ func_mask = lps0_dsm_func_mask & lps0_dsm_func_mask_microsoft; - if (func_mask) { + if (func_mask) acpi_handle_info(adev->handle, "Duplicate LPS0 _DSM functions (mask: 0x%x)\n", func_mask); - lps0_dsm_func_mask &= ~func_mask; - } } } diff --git a/drivers/android/binder.c b/drivers/android/binder.c index bad28cf42010..dd6923d37931 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1708,8 +1708,10 @@ static size_t binder_get_object(struct binder_proc *proc, size_t object_size = 0; read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); - if (offset > buffer->data_size || read_size < sizeof(*hdr)) + if (offset > buffer->data_size || read_size < sizeof(*hdr) || + !IS_ALIGNED(offset, sizeof(u32))) return 0; + if (u) { if (copy_from_user(object, u + offset, read_size)) return 0; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 562302e2e57c..6548f10e61d9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -666,6 +666,87 @@ static int mobile_lpm_policy = -1; module_param(mobile_lpm_policy, int, 0644); MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); +static char *ahci_mask_port_map; +module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444); +MODULE_PARM_DESC(mask_port_map, + "32-bits port map masks to ignore controllers ports. " + "Valid values are: " + "\"\" to apply the same mask to all AHCI controller " + "devices, and \"=,=,...\" to " + "specify different masks for the controllers specified, " + "where is the PCI ID of an AHCI controller in the " + "form \"domain:bus:dev.func\""); + +static void ahci_apply_port_map_mask(struct device *dev, + struct ahci_host_priv *hpriv, char *mask_s) +{ + unsigned int mask; + + if (kstrtouint(mask_s, 0, &mask)) { + dev_err(dev, "Invalid port map mask\n"); + return; + } + + hpriv->mask_port_map = mask; +} + +static void ahci_get_port_map_mask(struct device *dev, + struct ahci_host_priv *hpriv) +{ + char *param, *end, *str, *mask_s; + char *name; + + if (!strlen(ahci_mask_port_map)) + return; + + str = kstrdup(ahci_mask_port_map, GFP_KERNEL); + if (!str) + return; + + /* Handle single mask case */ + if (!strchr(str, '=')) { + ahci_apply_port_map_mask(dev, hpriv, str); + goto free; + } + + /* + * Mask list case: parse the parameter to apply the mask only if + * the device name matches. + */ + param = str; + end = param + strlen(param); + while (param && param < end && *param) { + name = param; + param = strchr(name, '='); + if (!param) + break; + + *param = '\0'; + param++; + if (param >= end) + break; + + if (strcmp(dev_name(dev), name) != 0) { + param = strchr(param, ','); + if (param) + param++; + continue; + } + + mask_s = param; + param = strchr(mask_s, ','); + if (param) { + *param = '\0'; + param++; + } + + ahci_apply_port_map_mask(dev, hpriv, mask_s); + } + +free: + kfree(str); +} + static void ahci_pci_save_initial_config(struct pci_dev *pdev, struct ahci_host_priv *hpriv) { @@ -688,6 +769,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); } + /* Handle port map masks passed as module parameter. */ + if (ahci_mask_port_map) + ahci_get_port_map_mask(&pdev->dev, hpriv); + ahci_save_initial_config(&pdev->dev, hpriv); } diff --git a/drivers/ata/ahci_st.c b/drivers/ata/ahci_st.c index d4a626f87963..79a8b0aa37bf 100644 --- a/drivers/ata/ahci_st.c +++ b/drivers/ata/ahci_st.c @@ -30,7 +30,6 @@ #define ST_AHCI_OOBR_CIMAX_SHIFT 0 struct st_ahci_drv_data { - struct platform_device *ahci; struct reset_control *pwr; struct reset_control *sw_rst; struct reset_control *pwr_rst; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index be3412cdb22e..c449d60d9bb9 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev) bool cdl_enabled; u64 val; - if (ata_id_major_version(dev->id) < 12) + if (ata_id_major_version(dev->id) < 11) goto not_supported; if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) || diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2f4c58837641..e954976891a9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work) * bail out. */ if (ap->pflags & ATA_PFLAG_SUSPENDED) - goto unlock; + goto unlock_ap; if (!sdev) continue; @@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work) if (do_resume) { ret = scsi_resume_device(sdev); if (ret == -EWOULDBLOCK) - goto unlock; + goto unlock_scan; dev->flags &= ~ATA_DFLAG_RESUMING; } ret = scsi_rescan_device(sdev); @@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work) spin_lock_irqsave(ap->lock, flags); if (ret) - goto unlock; + goto unlock_ap; } } -unlock: +unlock_ap: spin_unlock_irqrestore(ap->lock, flags); +unlock_scan: mutex_unlock(&ap->scsi_scan_mutex); /* Reschedule with a delay if scsi_rescan_device() returned an error */ diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index 4ac854f6b057..88b2e9817f49 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c @@ -1371,9 +1371,6 @@ static struct pci_driver pata_macio_pci_driver = { .suspend = pata_macio_pci_suspend, .resume = pata_macio_pci_resume, #endif - .driver = { - .owner = THIS_MODULE, - }, }; MODULE_DEVICE_TABLE(pci, pata_macio_pci_match); diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c index 400b22ee99c3..4c270999ba3c 100644 --- a/drivers/ata/sata_gemini.c +++ b/drivers/ata/sata_gemini.c @@ -200,7 +200,10 @@ int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge) pclk = sg->sata0_pclk; else pclk = sg->sata1_pclk; - clk_enable(pclk); + ret = clk_enable(pclk); + if (ret) + return ret; + msleep(10); /* Do not keep clocking a bridge that is not online */ diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index e82786c63fbd..9bec0aee92e0 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -787,37 +787,6 @@ static const struct ata_port_info mv_port_info[] = { }, }; -static const struct pci_device_id mv_pci_tbl[] = { - { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, - { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, - { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, - { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, - /* RocketRAID 1720/174x have different identifiers */ - { PCI_VDEVICE(TTI, 0x1720), chip_6042 }, - { PCI_VDEVICE(TTI, 0x1740), chip_6042 }, - { PCI_VDEVICE(TTI, 0x1742), chip_6042 }, - - { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, - { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, - { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, - { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, - { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, - - { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, - - /* Adaptec 1430SA */ - { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, - - /* Marvell 7042 support */ - { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, - - /* Highpoint RocketRAID PCIe series */ - { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, - { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, - - { } /* terminate list */ -}; - static const struct mv_hw_ops mv5xxx_ops = { .phy_errata = mv5_phy_errata, .enable_leds = mv5_enable_leds, @@ -4303,6 +4272,36 @@ static int mv_pci_init_one(struct pci_dev *pdev, static int mv_pci_device_resume(struct pci_dev *pdev); #endif +static const struct pci_device_id mv_pci_tbl[] = { + { PCI_VDEVICE(MARVELL, 0x5040), chip_504x }, + { PCI_VDEVICE(MARVELL, 0x5041), chip_504x }, + { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 }, + { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, + /* RocketRAID 1720/174x have different identifiers */ + { PCI_VDEVICE(TTI, 0x1720), chip_6042 }, + { PCI_VDEVICE(TTI, 0x1740), chip_6042 }, + { PCI_VDEVICE(TTI, 0x1742), chip_6042 }, + + { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, + { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, + { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 }, + { PCI_VDEVICE(MARVELL, 0x6080), chip_608x }, + { PCI_VDEVICE(MARVELL, 0x6081), chip_608x }, + + { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x }, + + /* Adaptec 1430SA */ + { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 }, + + /* Marvell 7042 support */ + { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 }, + + /* Highpoint RocketRAID PCIe series */ + { PCI_VDEVICE(TTI, 0x2300), chip_7042 }, + { PCI_VDEVICE(TTI, 0x2310), chip_7042 }, + + { } /* terminate list */ +}; static struct pci_driver mv_pci_driver = { .name = DRV_NAME, @@ -4315,6 +4314,7 @@ static struct pci_driver mv_pci_driver = { #endif }; +MODULE_DEVICE_TABLE(pci, mv_pci_tbl); /** * mv_print_info - Dump key info to kernel log for perusal. @@ -4487,7 +4487,6 @@ static void __exit mv_exit(void) MODULE_AUTHOR("Brett Russ"); MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers"); MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index b51d7a9d0d90..a482741eb181 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -957,8 +957,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource, offset -= (idx * window_size); idx++; - dist = ((long) (window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); + dist = min(size, window_size - offset); memcpy_fromio(psource, dimm_mmio + offset / 4, dist); psource += dist; @@ -1005,8 +1004,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource, readl(mmio + PDC_DIMM_WINDOW_CTLR); offset -= (idx * window_size); idx++; - dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size : - (long) (window_size - offset); + dist = min(size, window_size - offset); memcpy_toio(dimm_mmio + offset / 4, psource, dist); writel(0x01, mmio + PDC_GENERAL_CTLR); readl(mmio + PDC_GENERAL_CTLR); diff --git a/drivers/base/core.c b/drivers/base/core.c index b93f3c5716ae..5f4e03336e68 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -44,6 +44,7 @@ static bool fw_devlink_is_permissive(void); static void __fw_devlink_link_to_consumers(struct device *dev); static bool fw_devlink_drv_reg_done; static bool fw_devlink_best_effort; +static struct workqueue_struct *device_link_wq; /** * __fwnode_link_add - Create a link between two fwnode_handles. @@ -533,12 +534,26 @@ static void devlink_dev_release(struct device *dev) /* * It may take a while to complete this work because of the SRCU * synchronization in device_link_release_fn() and if the consumer or - * supplier devices get deleted when it runs, so put it into the "long" - * workqueue. + * supplier devices get deleted when it runs, so put it into the + * dedicated workqueue. */ - queue_work(system_long_wq, &link->rm_work); + queue_work(device_link_wq, &link->rm_work); } +/** + * device_link_wait_removal - Wait for ongoing devlink removal jobs to terminate + */ +void device_link_wait_removal(void) +{ + /* + * devlink removal jobs are queued in the dedicated work queue. + * To be sure that all removal jobs are terminated, ensure that any + * scheduled work has run to completion. + */ + flush_workqueue(device_link_wq); +} +EXPORT_SYMBOL_GPL(device_link_wait_removal); + static struct class devlink_class = { .name = "devlink", .dev_groups = devlink_groups, @@ -4164,9 +4179,14 @@ int __init devices_init(void) sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); if (!sysfs_dev_char_kobj) goto char_kobj_err; + device_link_wq = alloc_workqueue("device_link_wq", 0, 0); + if (!device_link_wq) + goto wq_err; return 0; + wq_err: + kobject_put(sysfs_dev_char_kobj); char_kobj_err: kobject_put(sysfs_dev_block_kobj); block_kobj_err: diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index 41edd6a430eb..55999a50ccc0 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -112,7 +112,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, unsigned long *entry, *lower, *upper; unsigned long lower_index, lower_last; unsigned long upper_index, upper_last; - int ret; + int ret = 0; lower = NULL; upper = NULL; @@ -145,7 +145,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, upper_index = max + 1; upper_last = mas.last; - upper = kmemdup(&entry[max + 1], + upper = kmemdup(&entry[max - mas.index + 1], ((mas.last - max) * sizeof(unsigned long)), map->alloc_flags); @@ -244,7 +244,7 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min, unsigned long lmin = min; unsigned long lmax = max; unsigned int r, v, sync_start; - int ret; + int ret = 0; bool sync_needed = false; map->cache_bypass = true; diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index 71c39bcd872c..ed33cf7192d2 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1965,10 +1965,10 @@ static int null_add_dev(struct nullb_device *dev) out_ida_free: ida_free(&nullb_indexes, nullb->index); -out_cleanup_zone: - null_free_zoned_dev(dev); out_cleanup_disk: put_disk(nullb->disk); +out_cleanup_zone: + null_free_zoned_dev(dev); out_cleanup_tags: if (nullb->tag_set == &nullb->__tag_set) blk_mq_free_tag_set(nullb->tag_set); diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index ac8ebccd3507..812fd2a8f853 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) switch (data->cd_info.state) { case HCI_DEVCOREDUMP_IDLE: err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE); - if (err < 0) + if (err < 0) { + kfree_skb(skb); break; + } data->cd_info.cnt = 0; /* It is supposed coredump can be done within 5 seconds */ @@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) break; } - if (err < 0) - kfree_skb(skb); - return err; } EXPORT_SYMBOL_GPL(btmtk_process_coredump); diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index b40b32fa7f1c..216826c31ee3 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -15,6 +15,8 @@ #define VERSION "0.1" +#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }}) + int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver, enum qca_btsoc_type soc_type) { @@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) } EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); +static int qca_check_bdaddr(struct hci_dev *hdev) +{ + struct hci_rp_read_bd_addr *bda; + struct sk_buff *skb; + int err; + + if (bacmp(&hdev->public_addr, BDADDR_ANY)) + return 0; + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Failed to read device address (%d)", err); + return err; + } + + if (skb->len != sizeof(*bda)) { + bt_dev_err(hdev, "Device address length mismatch"); + kfree_skb(skb); + return -EIO; + } + + bda = (struct hci_rp_read_bd_addr *)skb->data; + if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT)) + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + + kfree_skb(skb); + + return 0; +} + static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size, struct qca_btsoc_version ver, u8 rom_ver, u16 bid) { @@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, break; } + err = qca_check_bdaddr(hdev); + if (err) + return err; + bt_dev_info(hdev, "QCA setup on UART is completed"); return 0; @@ -826,11 +864,15 @@ EXPORT_SYMBOL_GPL(qca_uart_setup); int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) { + bdaddr_t bdaddr_swapped; struct sk_buff *skb; int err; - skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr, - HCI_EV_VENDOR, HCI_INIT_TIMEOUT); + baswap(&bdaddr_swapped, bdaddr); + + skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, + &bdaddr_swapped, HCI_EV_VENDOR, + HCI_INIT_TIMEOUT); if (IS_ERR(skb)) { err = PTR_ERR(skb); bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 06e915b57283..e3946f7b736e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = { /* Realtek 8852BE Bluetooth devices */ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK | @@ -3480,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb) static void btusb_coredump_qca(struct hci_dev *hdev) { + int err; static const u8 param[] = { 0x26 }; - struct sk_buff *skb; - skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT); - if (IS_ERR(skb)) - bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb)); - kfree_skb(skb); + err = __hci_cmd_send(hdev, 0xfc0c, 1, param); + if (err < 0) + bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err); } /* diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 8a60ad7acd70..0c9c9ee56592 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -7,7 +7,6 @@ * * Copyright (C) 2007 Texas Instruments, Inc. * Copyright (c) 2010, 2012, 2018 The Linux Foundation. All rights reserved. - * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * * Acknowledgements: * This file is based on hci_ll.c, which was... @@ -226,6 +225,7 @@ struct qca_serdev { struct qca_power *bt_power; u32 init_speed; u32 oper_speed; + bool bdaddr_property_broken; const char *firmware_name; }; @@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev) struct hci_uart *hu = hci_get_drvdata(hdev); bool wakeup; + if (!hu->serdev) + return true; + /* BT SoC attached through the serial bus is handled by the serdev driver. * So we need to use the device handle of the serdev driver to get the * status of device may wakeup. @@ -1843,6 +1846,7 @@ static int qca_setup(struct hci_uart *hu) const char *firmware_name = qca_get_firmware_name(hu); int ret; struct qca_btsoc_version ver; + struct qca_serdev *qcadev; const char *soc_name; ret = qca_check_speeds(hu); @@ -1904,16 +1908,9 @@ static int qca_setup(struct hci_uart *hu) case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - - /* Set BDA quirk bit for reading BDA value from fwnode property - * only if that property exist in DT. - */ - if (fwnode_property_present(dev_fwnode(hdev->dev.parent), "local-bd-address")) { - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); - bt_dev_info(hdev, "setting quirk bit to read BDA from fwnode later"); - } else { - bt_dev_dbg(hdev, "local-bd-address` is not present in the devicetree so not setting quirk bit for BDA"); - } + qcadev = serdev_device_get_drvdata(hu->serdev); + if (qcadev->bdaddr_property_broken) + set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); hci_set_aosp_capable(hdev); @@ -1961,8 +1958,10 @@ static int qca_setup(struct hci_uart *hu) qca_debugfs_init(hdev); hu->hdev->hw_error = qca_hw_error; hu->hdev->cmd_timeout = qca_cmd_timeout; - if (device_can_wakeup(hu->serdev->ctrl->dev.parent)) - hu->hdev->wakeup = qca_wakeup; + if (hu->serdev) { + if (device_can_wakeup(hu->serdev->ctrl->dev.parent)) + hu->hdev->wakeup = qca_wakeup; + } } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ set_bit(QCA_ROM_FW, &qca->flags); @@ -2295,6 +2294,9 @@ static int qca_serdev_probe(struct serdev_device *serdev) if (!qcadev->oper_speed) BT_DBG("UART will pick default operating speed"); + qcadev->bdaddr_property_broken = device_property_read_bool(&serdev->dev, + "qcom,local-bd-address-broken"); + if (data) qcadev->btsoc_type = data->soc_type; else @@ -2330,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev) (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855)) { dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); - power_ctrl_enabled = false; + return PTR_ERR(qcadev->bt_en); } + if (!qcadev->bt_en) + power_ctrl_enabled = false; + qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); if (IS_ERR(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || - data->soc_type == QCA_WCN7850)) - dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); + data->soc_type == QCA_WCN7850)) { + dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); + return PTR_ERR(qcadev->sw_ctrl); + } qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); if (IS_ERR(qcadev->susclk)) { @@ -2358,10 +2365,13 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(qcadev->bt_en)) { - dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); - power_ctrl_enabled = false; + dev_err(&serdev->dev, "failed to acquire enable gpio\n"); + return PTR_ERR(qcadev->bt_en); } + if (!qcadev->bt_en) + power_ctrl_enabled = false; + qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); if (IS_ERR(qcadev->susclk)) { dev_warn(&serdev->dev, "failed to acquire clk\n"); diff --git a/drivers/cache/sifive_ccache.c b/drivers/cache/sifive_ccache.c index 89ed6cd6b059..e9cc8b4786fb 100644 --- a/drivers/cache/sifive_ccache.c +++ b/drivers/cache/sifive_ccache.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -247,13 +249,49 @@ static irqreturn_t ccache_int_handler(int irq, void *device) return IRQ_HANDLED; } +static int sifive_ccache_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + unsigned long quirks; + int intr_num, rc; + + quirks = (unsigned long)device_get_match_data(dev); + + intr_num = platform_irq_count(pdev); + if (!intr_num) + return dev_err_probe(dev, -ENODEV, "No interrupts property\n"); + + for (int i = 0; i < intr_num; i++) { + if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR)) + continue; + + g_irq[i] = platform_get_irq(pdev, i); + if (g_irq[i] < 0) + return g_irq[i]; + + rc = devm_request_irq(dev, g_irq[i], ccache_int_handler, 0, "ccache_ecc", NULL); + if (rc) + return dev_err_probe(dev, rc, "Could not request IRQ %d\n", g_irq[i]); + } + + return 0; +} + +static struct platform_driver sifive_ccache_driver = { + .probe = sifive_ccache_probe, + .driver = { + .name = "sifive_ccache", + .of_match_table = sifive_ccache_ids, + }, +}; + static int __init sifive_ccache_init(void) { struct device_node *np; struct resource res; - int i, rc, intr_num; const struct of_device_id *match; unsigned long quirks; + int rc; np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); if (!np) @@ -277,28 +315,6 @@ static int __init sifive_ccache_init(void) goto err_unmap; } - intr_num = of_property_count_u32_elems(np, "interrupts"); - if (!intr_num) { - pr_err("No interrupts property\n"); - rc = -ENODEV; - goto err_unmap; - } - - for (i = 0; i < intr_num; i++) { - g_irq[i] = irq_of_parse_and_map(np, i); - - if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR)) - continue; - - rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc", - NULL); - if (rc) { - pr_err("Could not request IRQ %d\n", g_irq[i]); - goto err_free_irq; - } - } - of_node_put(np); - #ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) { riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; @@ -315,11 +331,15 @@ static int __init sifive_ccache_init(void) #ifdef CONFIG_DEBUG_FS setup_sifive_debug(); #endif + + rc = platform_driver_register(&sifive_ccache_driver); + if (rc) + goto err_unmap; + + of_node_put(np); + return 0; -err_free_irq: - while (--i >= 0) - free_irq(g_irq[i], NULL); err_unmap: iounmap(ccache_base); err_node_put: diff --git a/drivers/char/random.c b/drivers/char/random.c index 456be28ba67c..2597cb43f438 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len) static void __cold _credit_init_bits(size_t bits) { - static struct execute_work set_ready; + static DECLARE_WORK(set_ready, crng_set_ready); unsigned int new, orig, add; unsigned long flags; @@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits) if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) { crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */ - if (static_key_initialized) - execute_in_process_context(crng_set_ready, &set_ready); + if (static_key_initialized && system_unbound_wq) + queue_work(system_unbound_wq, &set_ready); atomic_notifier_call_chain(&random_ready_notifier, 0, NULL); wake_up_interruptible(&crng_init_wait); kill_fasync(&fasync, SIGIO, POLL_IN); @@ -890,8 +890,8 @@ void __init random_init(void) /* * If we were initialized by the cpu or bootloader before jump labels - * are initialized, then we should enable the static branch here, where - * it's guaranteed that jump labels have been initialized. + * or workqueues are initialized, then we should enable the static + * branch here, where it's guaranteed that these have been initialized. */ if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY) crng_set_ready(NULL); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 25371c91a58f..8cca52be993f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list); static HLIST_HEAD(clk_orphan_list); static LIST_HEAD(clk_notifier_list); +/* List of registered clks that use runtime PM */ +static HLIST_HEAD(clk_rpm_list); +static DEFINE_MUTEX(clk_rpm_list_lock); + static const struct hlist_head *all_lists[] = { &clk_root_list, &clk_orphan_list, @@ -59,6 +63,7 @@ struct clk_core { struct clk_hw *hw; struct module *owner; struct device *dev; + struct hlist_node rpm_node; struct device_node *of_node; struct clk_core *parent; struct clk_parent_map *parents; @@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core) pm_runtime_put_sync(core->dev); } +/** + * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices + * + * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so + * that disabling unused clks avoids a deadlock where a device is runtime PM + * resuming/suspending and the runtime PM callback is trying to grab the + * prepare_lock for something like clk_prepare_enable() while + * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime + * PM resume/suspend the device as well. + * + * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on + * success. Otherwise the lock is released on failure. + * + * Return: 0 on success, negative errno otherwise. + */ +static int clk_pm_runtime_get_all(void) +{ + int ret; + struct clk_core *core, *failed; + + /* + * Grab the list lock to prevent any new clks from being registered + * or unregistered until clk_pm_runtime_put_all(). + */ + mutex_lock(&clk_rpm_list_lock); + + /* + * Runtime PM "get" all the devices that are needed for the clks + * currently registered. Do this without holding the prepare_lock, to + * avoid the deadlock. + */ + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) { + ret = clk_pm_runtime_get(core); + if (ret) { + failed = core; + pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n", + dev_name(failed->dev), failed->name); + goto err; + } + } + + return 0; + +err: + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) { + if (core == failed) + break; + + clk_pm_runtime_put(core); + } + mutex_unlock(&clk_rpm_list_lock); + + return ret; +} + +/** + * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices + * + * Put the runtime PM references taken in clk_pm_runtime_get_all() and release + * the 'clk_rpm_list_lock'. + */ +static void clk_pm_runtime_put_all(void) +{ + struct clk_core *core; + + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) + clk_pm_runtime_put(core); + mutex_unlock(&clk_rpm_list_lock); +} + +static void clk_pm_runtime_init(struct clk_core *core) +{ + struct device *dev = core->dev; + + if (dev && pm_runtime_enabled(dev)) { + core->rpm_enabled = true; + + mutex_lock(&clk_rpm_list_lock); + hlist_add_head(&core->rpm_node, &clk_rpm_list); + mutex_unlock(&clk_rpm_list_lock); + } +} + /*** locking ***/ static void clk_prepare_lock(void) { @@ -1381,9 +1469,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core) if (core->flags & CLK_IGNORE_UNUSED) return; - if (clk_pm_runtime_get(core)) - return; - if (clk_core_is_prepared(core)) { trace_clk_unprepare(core); if (core->ops->unprepare_unused) @@ -1392,8 +1477,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core) core->ops->unprepare(core->hw); trace_clk_unprepare_complete(core); } - - clk_pm_runtime_put(core); } static void __init clk_disable_unused_subtree(struct clk_core *core) @@ -1409,9 +1492,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core) if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_prepare_enable(core->parent); - if (clk_pm_runtime_get(core)) - goto unprepare_out; - flags = clk_enable_lock(); if (core->enable_count) @@ -1436,8 +1516,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core) unlock_out: clk_enable_unlock(flags); - clk_pm_runtime_put(core); -unprepare_out: if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_disable_unprepare(core->parent); } @@ -1453,6 +1531,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup); static int __init clk_disable_unused(void) { struct clk_core *core; + int ret; if (clk_ignore_unused) { pr_warn("clk: Not disabling unused clocks\n"); @@ -1461,6 +1540,13 @@ static int __init clk_disable_unused(void) pr_info("clk: Disabling unused clocks\n"); + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; + /* + * Grab the prepare lock to keep the clk topology stable while iterating + * over clks. + */ clk_prepare_lock(); hlist_for_each_entry(core, &clk_root_list, child_node) @@ -1477,6 +1563,8 @@ static int __init clk_disable_unused(void) clk_prepare_unlock(); + clk_pm_runtime_put_all(); + return 0; } late_initcall_sync(clk_disable_unused); @@ -3252,9 +3340,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, { struct clk_core *child; - clk_pm_runtime_get(c); clk_summary_show_one(s, c, level); - clk_pm_runtime_put(c); hlist_for_each_entry(child, &c->children, child_node) clk_summary_show_subtree(s, child, level + 1); @@ -3264,11 +3350,15 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk_core *c; struct hlist_head **lists = s->private; + int ret; seq_puts(s, " enable prepare protect duty hardware connection\n"); seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n"); seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n"); + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; clk_prepare_lock(); @@ -3277,6 +3367,7 @@ static int clk_summary_show(struct seq_file *s, void *data) clk_summary_show_subtree(s, c, 0); clk_prepare_unlock(); + clk_pm_runtime_put_all(); return 0; } @@ -3324,8 +3415,14 @@ static int clk_dump_show(struct seq_file *s, void *data) struct clk_core *c; bool first_node = true; struct hlist_head **lists = s->private; + int ret; + + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; seq_putc(s, '{'); + clk_prepare_lock(); for (; *lists; lists++) { @@ -3338,6 +3435,7 @@ static int clk_dump_show(struct seq_file *s, void *data) } clk_prepare_unlock(); + clk_pm_runtime_put_all(); seq_puts(s, "}\n"); return 0; @@ -3981,8 +4079,6 @@ static int __clk_core_init(struct clk_core *core) } clk_core_reparent_orphans_nolock(); - - kref_init(&core->ref); out: clk_pm_runtime_put(core); unlock: @@ -4211,6 +4307,22 @@ static void clk_core_free_parent_map(struct clk_core *core) kfree(core->parents); } +/* Free memory allocated for a struct clk_core */ +static void __clk_release(struct kref *ref) +{ + struct clk_core *core = container_of(ref, struct clk_core, ref); + + if (core->rpm_enabled) { + mutex_lock(&clk_rpm_list_lock); + hlist_del(&core->rpm_node); + mutex_unlock(&clk_rpm_list_lock); + } + + clk_core_free_parent_map(core); + kfree_const(core->name); + kfree(core); +} + static struct clk * __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) { @@ -4231,6 +4343,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) goto fail_out; } + kref_init(&core->ref); + core->name = kstrdup_const(init->name, GFP_KERNEL); if (!core->name) { ret = -ENOMEM; @@ -4243,9 +4357,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) } core->ops = init->ops; - if (dev && pm_runtime_enabled(dev)) - core->rpm_enabled = true; core->dev = dev; + clk_pm_runtime_init(core); core->of_node = np; if (dev && dev->driver) core->owner = dev->driver->owner; @@ -4285,12 +4398,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) hw->clk = NULL; fail_create_clk: - clk_core_free_parent_map(core); fail_parents: fail_ops: - kfree_const(core->name); fail_name: - kfree(core); + kref_put(&core->ref, __clk_release); fail_out: return ERR_PTR(ret); } @@ -4370,18 +4481,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(of_clk_hw_register); -/* Free memory allocated for a clock. */ -static void __clk_release(struct kref *ref) -{ - struct clk_core *core = container_of(ref, struct clk_core, ref); - - lockdep_assert_held(&prepare_lock); - - clk_core_free_parent_map(core); - kfree_const(core->name); - kfree(core); -} - /* * Empty clk_ops for unregistered clocks. These are used temporarily * after clk_unregister() was called on a clock and until last clock @@ -4472,7 +4571,8 @@ void clk_unregister(struct clk *clk) if (ops == &clk_nodrv_ops) { pr_err("%s: unregistered clock: %s\n", __func__, clk->core->name); - goto unlock; + clk_prepare_unlock(); + return; } /* * Assign empty clock ops for consumers that might still hold @@ -4506,11 +4606,10 @@ void clk_unregister(struct clk *clk) if (clk->core->protect_count) pr_warn("%s: unregistering protected clock: %s\n", __func__, clk->core->name); + clk_prepare_unlock(); kref_put(&clk->core->ref, __clk_release); free_clk(clk); -unlock: - clk_prepare_unlock(); } EXPORT_SYMBOL_GPL(clk_unregister); @@ -4669,13 +4768,11 @@ void __clk_put(struct clk *clk) if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX) clk_set_rate_range_nolock(clk, 0, ULONG_MAX); - owner = clk->core->owner; - kref_put(&clk->core->ref, __clk_release); - clk_prepare_unlock(); + owner = clk->core->owner; + kref_put(&clk->core->ref, __clk_release); module_put(owner); - free_clk(clk); } diff --git a/drivers/clk/mediatek/clk-mt7988-infracfg.c b/drivers/clk/mediatek/clk-mt7988-infracfg.c index 449041f8abbc..c8c023afe3e5 100644 --- a/drivers/clk/mediatek/clk-mt7988-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c @@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[] = { GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, "infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8), GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, "infra_pcie_peri_ck_26m_ck_p2", - "csw_infra_f26m_sel", 9), + "infra_pcie_peri_ck_26m_ck_p3", 9), GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10), /* INFRA1 */ diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 2e55368dc4d8..bd37ab4d1a9b 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "clk-mtk.h" @@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM; } + + devm_pm_runtime_enable(&pdev->dev); + /* + * Do a pm_runtime_resume_and_get() to workaround a possible + * deadlock between clk_register() and the genpd framework. + */ + r = pm_runtime_resume_and_get(&pdev->dev); + if (r) + return r; + /* Calculate how many clk_hw_onecell_data entries to allocate */ num_clks = mcd->num_clks + mcd->num_composite_clks; num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; @@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, goto unregister_clks; } + pm_runtime_put(&pdev->dev); + return r; unregister_clks: @@ -604,6 +617,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, free_base: if (mcd->shared_io && base) iounmap(base); + + pm_runtime_put(&pdev->dev); return r; } diff --git a/drivers/comedi/drivers/vmk80xx.c b/drivers/comedi/drivers/vmk80xx.c index 4536ed43f65b..84dce5184a77 100644 --- a/drivers/comedi/drivers/vmk80xx.c +++ b/drivers/comedi/drivers/vmk80xx.c @@ -641,32 +641,21 @@ static int vmk80xx_find_usb_endpoints(struct comedi_device *dev) struct vmk80xx_private *devpriv = dev->private; struct usb_interface *intf = comedi_to_usb_interface(dev); struct usb_host_interface *iface_desc = intf->cur_altsetting; - struct usb_endpoint_descriptor *ep_desc; - int i; + struct usb_endpoint_descriptor *ep_rx_desc, *ep_tx_desc; + int ret; - if (iface_desc->desc.bNumEndpoints != 2) + if (devpriv->model == VMK8061_MODEL) + ret = usb_find_common_endpoints(iface_desc, &ep_rx_desc, + &ep_tx_desc, NULL, NULL); + else + ret = usb_find_common_endpoints(iface_desc, NULL, NULL, + &ep_rx_desc, &ep_tx_desc); + + if (ret) return -ENODEV; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - ep_desc = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_int_in(ep_desc) || - usb_endpoint_is_bulk_in(ep_desc)) { - if (!devpriv->ep_rx) - devpriv->ep_rx = ep_desc; - continue; - } - - if (usb_endpoint_is_int_out(ep_desc) || - usb_endpoint_is_bulk_out(ep_desc)) { - if (!devpriv->ep_tx) - devpriv->ep_tx = ep_desc; - continue; - } - } - - if (!devpriv->ep_rx || !devpriv->ep_tx) - return -ENODEV; + devpriv->ep_rx = ep_rx_desc; + devpriv->ep_tx = ep_tx_desc; if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx)) return -EINVAL; diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index f44efbb89c34..2102377f727b 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -1090,7 +1090,7 @@ static int __sev_snp_init_locked(int *error) void *arg = &data; int cmd, rc = 0; - if (!cpu_feature_enabled(X86_FEATURE_SEV_SNP)) + if (!cc_platform_has(CC_ATTR_HOST_SEV_SNP)) return -ENODEV; sev = psp->sev_data; diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index af5cb818f84d..cb8c155a2c9b 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -525,22 +525,11 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport) { struct acpi_device *hb = to_cxl_host_bridge(NULL, dev); u32 uid; - int rc; if (kstrtou32(acpi_device_uid(hb), 0, &uid)) return -EINVAL; - rc = acpi_get_genport_coordinates(uid, dport->hb_coord); - if (rc < 0) - return rc; - - /* Adjust back to picoseconds from nanoseconds */ - for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { - dport->hb_coord[i].read_latency *= 1000; - dport->hb_coord[i].write_latency *= 1000; - } - - return 0; + return acpi_get_genport_coordinates(uid, dport->coord); } static int add_host_bridge_dport(struct device *match, void *arg) diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c index eddbbe21450c..bb83867d9fec 100644 --- a/drivers/cxl/core/cdat.c +++ b/drivers/cxl/core/cdat.c @@ -14,12 +14,42 @@ struct dsmas_entry { struct range dpa_range; u8 handle; - struct access_coordinate coord; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; int entries; int qos_class; }; +static u32 cdat_normalize(u16 entry, u64 base, u8 type) +{ + u32 value; + + /* + * Check for invalid and overflow values + */ + if (entry == 0xffff || !entry) + return 0; + else if (base > (UINT_MAX / (entry))) + return 0; + + /* + * CDAT fields follow the format of HMAT fields. See table 5 Device + * Scoped Latency and Bandwidth Information Structure in Coherent Device + * Attribute Table (CDAT) Specification v1.01. + */ + value = entry * base; + switch (type) { + case ACPI_HMAT_ACCESS_LATENCY: + case ACPI_HMAT_READ_LATENCY: + case ACPI_HMAT_WRITE_LATENCY: + value = DIV_ROUND_UP(value, 1000); + break; + default: + break; + } + return value; +} + static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg, const unsigned long end) { @@ -58,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg, return 0; } -static void cxl_access_coordinate_set(struct access_coordinate *coord, - int access, unsigned int val) +static void __cxl_access_coordinate_set(struct access_coordinate *coord, + int access, unsigned int val) { switch (access) { case ACPI_HMAT_ACCESS_LATENCY: @@ -85,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord, } } +static void cxl_access_coordinate_set(struct access_coordinate *coord, + int access, unsigned int val) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + __cxl_access_coordinate_set(&coord[i], access, val); +} + static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, const unsigned long end) { @@ -97,7 +134,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, __le16 le_val; u64 val; u16 len; - int rc; len = le16_to_cpu((__force __le16)hdr->length); if (len != size || (unsigned long)hdr + len > end) { @@ -124,12 +160,10 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, le_base = (__force __le64)dslbis->entry_base_unit; le_val = (__force __le16)dslbis->entry[0]; - rc = check_mul_overflow(le64_to_cpu(le_base), - le16_to_cpu(le_val), &val); - if (rc) - pr_warn("DSLBIS value overflowed.\n"); + val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base), + dslbis->data_type); - cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val); + cxl_access_coordinate_set(dent->coord, dslbis->data_type, val); return 0; } @@ -163,25 +197,18 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port, static int cxl_port_perf_data_calculate(struct cxl_port *port, struct xarray *dsmas_xa) { - struct access_coordinate ep_c; - struct access_coordinate coord[ACCESS_COORDINATE_MAX]; + struct access_coordinate ep_c[ACCESS_COORDINATE_MAX]; struct dsmas_entry *dent; int valid_entries = 0; unsigned long index; int rc; - rc = cxl_endpoint_get_perf_coordinates(port, &ep_c); + rc = cxl_endpoint_get_perf_coordinates(port, ep_c); if (rc) { dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n"); return rc; } - rc = cxl_hb_get_perf_coordinates(port, coord); - if (rc) { - dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n"); - return rc; - } - struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port); if (!cxl_root) @@ -193,18 +220,10 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, xa_for_each(dsmas_xa, index, dent) { int qos_class; - cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c); - /* - * Keeping the host bridge coordinates separate from the dsmas - * coordinates in order to allow calculation of access class - * 0 and 1 for region later. - */ - cxl_coordinates_combine(&coord[ACCESS_COORDINATE_CPU], - &coord[ACCESS_COORDINATE_CPU], - &dent->coord); + cxl_coordinates_combine(dent->coord, dent->coord, ep_c); dent->entries = 1; rc = cxl_root->ops->qos_class(cxl_root, - &coord[ACCESS_COORDINATE_CPU], + &dent->coord[ACCESS_COORDINATE_CPU], 1, &qos_class); if (rc != 1) continue; @@ -222,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, static void update_perf_entry(struct device *dev, struct dsmas_entry *dent, struct cxl_dpa_perf *dpa_perf) { + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + dpa_perf->coord[i] = dent->coord[i]; dpa_perf->dpa_range = dent->dpa_range; - dpa_perf->coord = dent->coord; dpa_perf->qos_class = dent->qos_class; dev_dbg(dev, "DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n", dent->dpa_range.start, dpa_perf->qos_class, - dent->coord.read_bandwidth, dent->coord.write_bandwidth, - dent->coord.read_latency, dent->coord.write_latency); + dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth, + dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth, + dent->coord[ACCESS_COORDINATE_CPU].read_latency, + dent->coord[ACCESS_COORDINATE_CPU].write_latency); } static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds, @@ -461,17 +483,16 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg, le_base = (__force __le64)tbl->sslbis_header.entry_base_unit; le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth; - - if (check_mul_overflow(le64_to_cpu(le_base), - le16_to_cpu(le_val), &val)) - dev_warn(dev, "SSLBIS value overflowed!\n"); + val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base), + sslbis->data_type); xa_for_each(&port->dports, index, dport) { if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT || - dsp_id == dport->port_id) - cxl_access_coordinate_set(&dport->sw_coord, + dsp_id == dport->port_id) { + cxl_access_coordinate_set(dport->coord, sslbis->data_type, val); + } } } @@ -493,16 +514,9 @@ void cxl_switch_parse_cdat(struct cxl_port *port) } EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL); -/** - * cxl_coordinates_combine - Combine the two input coordinates - * - * @out: Output coordinate of c1 and c2 combined - * @c1: input coordinates - * @c2: input coordinates - */ -void cxl_coordinates_combine(struct access_coordinate *out, - struct access_coordinate *c1, - struct access_coordinate *c2) +static void __cxl_coordinates_combine(struct access_coordinate *out, + struct access_coordinate *c1, + struct access_coordinate *c2) { if (c1->write_bandwidth && c2->write_bandwidth) out->write_bandwidth = min(c1->write_bandwidth, @@ -515,23 +529,34 @@ void cxl_coordinates_combine(struct access_coordinate *out, out->read_latency = c1->read_latency + c2->read_latency; } +/** + * cxl_coordinates_combine - Combine the two input coordinates + * + * @out: Output coordinate of c1 and c2 combined + * @c1: input coordinates + * @c2: input coordinates + */ +void cxl_coordinates_combine(struct access_coordinate *out, + struct access_coordinate *c1, + struct access_coordinate *c2) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + __cxl_coordinates_combine(&out[i], &c1[i], &c2[i]); +} + MODULE_IMPORT_NS(CXL); void cxl_region_perf_data_calculate(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); - struct cxl_port *port = cxlmd->endpoint; struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX]; - struct access_coordinate coord; struct range dpa = { .start = cxled->dpa_res->start, .end = cxled->dpa_res->end, }; struct cxl_dpa_perf *perf; - int rc; switch (cxlr->mode) { case CXL_DECODER_RAM: @@ -549,35 +574,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, if (!range_contains(&perf->dpa_range, &dpa)) return; - rc = cxl_hb_get_perf_coordinates(port, hb_coord); - if (rc) { - dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n"); - return; - } - for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { - /* Pickup the host bridge coords */ - cxl_coordinates_combine(&coord, &hb_coord[i], &perf->coord); - /* Get total bandwidth and the worst latency for the cxl region */ cxlr->coord[i].read_latency = max_t(unsigned int, cxlr->coord[i].read_latency, - coord.read_latency); + perf->coord[i].read_latency); cxlr->coord[i].write_latency = max_t(unsigned int, cxlr->coord[i].write_latency, - coord.write_latency); - cxlr->coord[i].read_bandwidth += coord.read_bandwidth; - cxlr->coord[i].write_bandwidth += coord.write_bandwidth; - - /* - * Convert latency to nanosec from picosec to be consistent - * with the resulting latency coordinates computed by the - * HMAT_REPORTING code. - */ - cxlr->coord[i].read_latency = - DIV_ROUND_UP(cxlr->coord[i].read_latency, 1000); - cxlr->coord[i].write_latency = - DIV_ROUND_UP(cxlr->coord[i].write_latency, 1000); + perf->coord[i].write_latency); + cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth; + cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth; } } diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 9adda4795eb7..65185c9fa001 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, payload->handles[i++] = gen->hdr.handle; dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log, - le16_to_cpu(payload->handles[i])); + le16_to_cpu(payload->handles[i - 1])); if (i == max_handles) { payload->nr_recs = i; @@ -946,24 +946,22 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, struct cxl_memdev *cxlmd = mds->cxlds.cxlmd; struct device *dev = mds->cxlds.dev; struct cxl_get_event_payload *payload; - struct cxl_mbox_cmd mbox_cmd; u8 log_type = type; u16 nr_rec; mutex_lock(&mds->event.log_lock); payload = mds->event.buf; - mbox_cmd = (struct cxl_mbox_cmd) { - .opcode = CXL_MBOX_OP_GET_EVENT_RECORD, - .payload_in = &log_type, - .size_in = sizeof(log_type), - .payload_out = payload, - .size_out = mds->payload_size, - .min_out = struct_size(payload, records, 0), - }; - do { int rc, i; + struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) { + .opcode = CXL_MBOX_OP_GET_EVENT_RECORD, + .payload_in = &log_type, + .size_in = sizeof(log_type), + .payload_out = payload, + .size_out = mds->payload_size, + .min_out = struct_size(payload, records, 0), + }; rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) { @@ -1296,7 +1294,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds); struct cxl_mbox_poison_out *po; struct cxl_mbox_poison_in pi; - struct cxl_mbox_cmd mbox_cmd; int nr_records = 0; int rc; @@ -1308,16 +1305,16 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len, pi.offset = cpu_to_le64(offset); pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT); - mbox_cmd = (struct cxl_mbox_cmd) { - .opcode = CXL_MBOX_OP_GET_POISON, - .size_in = sizeof(pi), - .payload_in = &pi, - .size_out = mds->payload_size, - .payload_out = po, - .min_out = struct_size(po, record, 0), - }; - do { + struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd){ + .opcode = CXL_MBOX_OP_GET_POISON, + .size_in = sizeof(pi), + .payload_in = &pi, + .size_out = mds->payload_size, + .payload_out = po, + .min_out = struct_size(po, record, 0), + }; + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) break; diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 2b0cab556072..762783bb091a 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2133,36 +2133,44 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd) } EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL); -/** - * cxl_hb_get_perf_coordinates - Retrieve performance numbers between initiator - * and host bridge - * - * @port: endpoint cxl_port - * @coord: output access coordinates - * - * Return: errno on failure, 0 on success. - */ -int cxl_hb_get_perf_coordinates(struct cxl_port *port, - struct access_coordinate *coord) +static void add_latency(struct access_coordinate *c, long latency) { - struct cxl_port *iter = port; - struct cxl_dport *dport; + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + c[i].write_latency += latency; + c[i].read_latency += latency; + } +} - if (!is_cxl_endpoint(port)) - return -EINVAL; - - dport = iter->parent_dport; - while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) { - iter = to_cxl_port(iter->dev.parent); - dport = iter->parent_dport; +static bool coordinates_valid(struct access_coordinate *c) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + if (c[i].read_bandwidth && c[i].write_bandwidth && + c[i].read_latency && c[i].write_latency) + continue; + return false; } - coord[ACCESS_COORDINATE_LOCAL] = - dport->hb_coord[ACCESS_COORDINATE_LOCAL]; - coord[ACCESS_COORDINATE_CPU] = - dport->hb_coord[ACCESS_COORDINATE_CPU]; + return true; +} - return 0; +static void set_min_bandwidth(struct access_coordinate *c, unsigned int bw) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + c[i].write_bandwidth = min(c[i].write_bandwidth, bw); + c[i].read_bandwidth = min(c[i].read_bandwidth, bw); + } +} + +static void set_access_coordinates(struct access_coordinate *out, + struct access_coordinate *in) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + out[i] = in[i]; +} + +static bool parent_port_is_cxl_root(struct cxl_port *port) +{ + return is_cxl_root(to_cxl_port(port->dev.parent)); } /** @@ -2176,35 +2184,53 @@ int cxl_hb_get_perf_coordinates(struct cxl_port *port, int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct access_coordinate *coord) { - struct access_coordinate c = { - .read_bandwidth = UINT_MAX, - .write_bandwidth = UINT_MAX, + struct access_coordinate c[] = { + { + .read_bandwidth = UINT_MAX, + .write_bandwidth = UINT_MAX, + }, + { + .read_bandwidth = UINT_MAX, + .write_bandwidth = UINT_MAX, + }, }; struct cxl_port *iter = port; struct cxl_dport *dport; struct pci_dev *pdev; unsigned int bw; + bool is_cxl_root; if (!is_cxl_endpoint(port)) return -EINVAL; - dport = iter->parent_dport; - /* - * Exit the loop when the parent port of the current port is cxl root. - * The iterative loop starts at the endpoint and gathers the - * latency of the CXL link from the current iter to the next downstream - * port each iteration. If the parent is cxl root then there is - * nothing to gather. + * Exit the loop when the parent port of the current iter port is cxl + * root. The iterative loop starts at the endpoint and gathers the + * latency of the CXL link from the current device/port to the connected + * downstream port each iteration. */ - while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) { - cxl_coordinates_combine(&c, &c, &dport->sw_coord); - c.write_latency += dport->link_latency; - c.read_latency += dport->link_latency; - - iter = to_cxl_port(iter->dev.parent); + do { dport = iter->parent_dport; - } + iter = to_cxl_port(iter->dev.parent); + is_cxl_root = parent_port_is_cxl_root(iter); + + /* + * There's no valid access_coordinate for a root port since RPs do not + * have CDAT and therefore needs to be skipped. + */ + if (!is_cxl_root) { + if (!coordinates_valid(dport->coord)) + return -EINVAL; + cxl_coordinates_combine(c, c, dport->coord); + } + add_latency(c, dport->link_latency); + } while (!is_cxl_root); + + dport = iter->parent_dport; + /* Retrieve HB coords */ + if (!coordinates_valid(dport->coord)) + return -EINVAL; + cxl_coordinates_combine(c, c, dport->coord); /* Get the calculated PCI paths bandwidth */ pdev = to_pci_dev(port->uport_dev->parent); @@ -2213,10 +2239,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, return -ENXIO; bw /= BITS_PER_BYTE; - c.write_bandwidth = min(c.write_bandwidth, bw); - c.read_bandwidth = min(c.read_bandwidth, bw); - - *coord = c; + set_min_bandwidth(c, bw); + set_access_coordinates(coord, c); return 0; } diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 372786f80955..3c42f984eeaf 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -271,6 +271,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL); static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, struct cxl_register_map *map) { + u8 reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo); int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo); u64 offset = ((u64)reg_hi << 32) | (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK); @@ -278,11 +279,11 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, if (offset > pci_resource_len(pdev, bar)) { dev_warn(&pdev->dev, "BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar, - &pdev->resource[bar], &offset, map->reg_type); + &pdev->resource[bar], &offset, reg_type); return false; } - map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo); + map->reg_type = reg_type; map->resource = pci_resource_start(pdev, bar) + offset; map->max_size = pci_resource_len(pdev, bar) - offset; return true; diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 534e25e2f0a4..036d17db68e0 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -663,8 +663,7 @@ struct cxl_rcrb_info { * @rch: Indicate whether this dport was enumerated in RCH or VH mode * @port: reference to cxl_port that contains this downstream port * @regs: Dport parsed register blocks - * @sw_coord: access coordinates (performance) for switch from CDAT - * @hb_coord: access coordinates (performance) from ACPI generic port (host bridge) + * @coord: access coordinates (bandwidth and latency performance attributes) * @link_latency: calculated PCIe downstream latency */ struct cxl_dport { @@ -675,8 +674,7 @@ struct cxl_dport { bool rch; struct cxl_port *port; struct cxl_regs regs; - struct access_coordinate sw_coord; - struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX]; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; long link_latency; }; @@ -884,8 +882,6 @@ void cxl_switch_parse_cdat(struct cxl_port *port); int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct access_coordinate *coord); -int cxl_hb_get_perf_coordinates(struct cxl_port *port, - struct access_coordinate *coord); void cxl_region_perf_data_calculate(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled); diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 20fb3b35e89e..36cee9c30ceb 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -401,7 +401,7 @@ enum cxl_devtype { */ struct cxl_dpa_perf { struct range dpa_range; - struct access_coordinate coord; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; int qos_class; }; diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 8fe5aa67b167..8892bc701a66 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -35,12 +35,35 @@ static inline int is_dma_buf_file(struct file *); -struct dma_buf_list { - struct list_head head; - struct mutex lock; -}; +#if IS_ENABLED(CONFIG_DEBUG_FS) +static DEFINE_MUTEX(debugfs_list_mutex); +static LIST_HEAD(debugfs_list); -static struct dma_buf_list db_list; +static void __dma_buf_debugfs_list_add(struct dma_buf *dmabuf) +{ + mutex_lock(&debugfs_list_mutex); + list_add(&dmabuf->list_node, &debugfs_list); + mutex_unlock(&debugfs_list_mutex); +} + +static void __dma_buf_debugfs_list_del(struct dma_buf *dmabuf) +{ + if (!dmabuf) + return; + + mutex_lock(&debugfs_list_mutex); + list_del(&dmabuf->list_node); + mutex_unlock(&debugfs_list_mutex); +} +#else +static void __dma_buf_debugfs_list_add(struct dma_buf *dmabuf) +{ +} + +static void __dma_buf_debugfs_list_del(struct file *file) +{ +} +#endif static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen) { @@ -89,17 +112,10 @@ static void dma_buf_release(struct dentry *dentry) static int dma_buf_file_release(struct inode *inode, struct file *file) { - struct dma_buf *dmabuf; - if (!is_dma_buf_file(file)) return -EINVAL; - dmabuf = file->private_data; - if (dmabuf) { - mutex_lock(&db_list.lock); - list_del(&dmabuf->list_node); - mutex_unlock(&db_list.lock); - } + __dma_buf_debugfs_list_del(file->private_data); return 0; } @@ -672,9 +688,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) file->f_path.dentry->d_fsdata = dmabuf; dmabuf->file = file; - mutex_lock(&db_list.lock); - list_add(&dmabuf->list_node, &db_list.head); - mutex_unlock(&db_list.lock); + __dma_buf_debugfs_list_add(dmabuf); return dmabuf; @@ -1611,7 +1625,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) size_t size = 0; int ret; - ret = mutex_lock_interruptible(&db_list.lock); + ret = mutex_lock_interruptible(&debugfs_list_mutex); if (ret) return ret; @@ -1620,7 +1634,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) seq_printf(s, "%-8s\t%-8s\t%-8s\t%-8s\texp_name\t%-8s\tname\n", "size", "flags", "mode", "count", "ino"); - list_for_each_entry(buf_obj, &db_list.head, list_node) { + list_for_each_entry(buf_obj, &debugfs_list, list_node) { ret = dma_resv_lock_interruptible(buf_obj->resv, NULL); if (ret) @@ -1657,11 +1671,11 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) seq_printf(s, "\nTotal %d objects, %zu bytes\n", count, size); - mutex_unlock(&db_list.lock); + mutex_unlock(&debugfs_list_mutex); return 0; error_unlock: - mutex_unlock(&db_list.lock); + mutex_unlock(&debugfs_list_mutex); return ret; } @@ -1718,8 +1732,6 @@ static int __init dma_buf_init(void) if (IS_ERR(dma_buf_mnt)) return PTR_ERR(dma_buf_mnt); - mutex_init(&db_list.lock); - INIT_LIST_HEAD(&db_list.head); dma_buf_init_debugfs(); return 0; } diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 78a938969d7d..1398814d8fbb 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -171,6 +171,10 @@ static irqreturn_t idma64_irq(int irq, void *dev) u32 status_err; unsigned short i; + /* Since IRQ may be shared, check if DMA controller is powered on */ + if (status == GENMASK(31, 0)) + return IRQ_NONE; + dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status); /* Check if we have any interrupt from the DMA controller */ diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index 8078ab9acfbc..c095a2c8f659 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -342,7 +342,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid) if (!evl) return; - spin_lock(&evl->lock); + mutex_lock(&evl->lock); status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET); t = status.tail; h = status.head; @@ -354,9 +354,8 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid) set_bit(h, evl->bmap); h = (h + 1) % size; } - spin_unlock(&evl->lock); - drain_workqueue(wq->wq); + mutex_unlock(&evl->lock); } static int idxd_cdev_release(struct inode *node, struct file *filep) diff --git a/drivers/dma/idxd/debugfs.c b/drivers/dma/idxd/debugfs.c index f3f25ee676f3..ad4245cb301d 100644 --- a/drivers/dma/idxd/debugfs.c +++ b/drivers/dma/idxd/debugfs.c @@ -66,7 +66,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d) if (!evl || !evl->log) return 0; - spin_lock(&evl->lock); + mutex_lock(&evl->lock); evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET); t = evl_status.tail; @@ -87,7 +87,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d) dump_event_entry(idxd, s, i, &count, processed); } - spin_unlock(&evl->lock); + mutex_unlock(&evl->lock); return 0; } diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index ecfdf4a8f1f8..c41ef195eeb9 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -775,7 +775,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd) goto err_alloc; } - spin_lock(&evl->lock); + mutex_lock(&evl->lock); evl->log = addr; evl->dma = dma_addr; evl->log_size = size; @@ -796,7 +796,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd) gencfg.evl_en = 1; iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET); - spin_unlock(&evl->lock); + mutex_unlock(&evl->lock); return 0; err_alloc: @@ -819,7 +819,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd) if (!gencfg.evl_en) return; - spin_lock(&evl->lock); + mutex_lock(&evl->lock); gencfg.evl_en = 0; iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET); @@ -836,7 +836,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd) evl_dma = evl->dma; evl->log = NULL; evl->size = IDXD_EVL_SIZE_MIN; - spin_unlock(&evl->lock); + mutex_unlock(&evl->lock); dma_free_coherent(dev, evl_log_size, evl_log, evl_dma); } diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index a4099a1e2340..7b98944135eb 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -293,7 +293,7 @@ struct idxd_driver_data { struct idxd_evl { /* Lock to protect event log access. */ - spinlock_t lock; + struct mutex lock; void *log; dma_addr_t dma; /* Total size of event log = number of entries * entry size. */ diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 4954adc6bb60..264c4e47d7cc 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -354,7 +354,7 @@ static int idxd_init_evl(struct idxd_device *idxd) if (!evl) return -ENOMEM; - spin_lock_init(&evl->lock); + mutex_init(&evl->lock); evl->size = IDXD_EVL_SIZE_MIN; idxd_name = dev_name(idxd_confdev(idxd)); diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index 348aa21389a9..8dc029c86551 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -363,7 +363,7 @@ static void process_evl_entries(struct idxd_device *idxd) evl_status.bits = 0; evl_status.int_pending = 1; - spin_lock(&evl->lock); + mutex_lock(&evl->lock); /* Clear interrupt pending bit */ iowrite32(evl_status.bits_upper32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32)); @@ -380,7 +380,7 @@ static void process_evl_entries(struct idxd_device *idxd) evl_status.head = h; iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET); - spin_unlock(&evl->lock); + mutex_unlock(&evl->lock); } irqreturn_t idxd_misc_thread(int vec, void *data) diff --git a/drivers/dma/idxd/perfmon.c b/drivers/dma/idxd/perfmon.c index fdda6d604262..5e94247e1ea7 100644 --- a/drivers/dma/idxd/perfmon.c +++ b/drivers/dma/idxd/perfmon.c @@ -528,14 +528,11 @@ static int perf_event_cpu_offline(unsigned int cpu, struct hlist_node *node) return 0; target = cpumask_any_but(cpu_online_mask, cpu); - /* migrate events if there is a valid target */ - if (target < nr_cpu_ids) + if (target < nr_cpu_ids) { cpumask_set_cpu(target, &perfmon_dsa_cpu_mask); - else - target = -1; - - perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target); + perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target); + } return 0; } diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 4e76c4ec2d39..e001f4f7aa64 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -250,7 +250,7 @@ static void pchan_update(struct owl_dma_pchan *pchan, u32 reg, else regval &= ~val; - writel(val, pchan->base + reg); + writel(regval, pchan->base + reg); } static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data) @@ -274,7 +274,7 @@ static void dma_update(struct owl_dma *od, u32 reg, u32 val, bool state) else regval &= ~val; - writel(val, od->base + reg); + writel(regval, od->base + reg); } static void dma_writel(struct owl_dma *od, u32 reg, u32 data) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 5f6d7f1e095f..ad8e3da1b2cd 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1053,9 +1053,6 @@ static bool _trigger(struct pl330_thread *thrd) thrd->req_running = idx; - if (desc->rqtype == DMA_MEM_TO_DEV || desc->rqtype == DMA_DEV_TO_MEM) - UNTIL(thrd, PL330_STATE_WFP); - return true; } diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index 88547a23825b..3642508e88bb 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c @@ -746,6 +746,9 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc) bytes_xfer = dma_desc->bytes_xfer + sg_req[dma_desc->sg_idx].len - (wcount * 4); + if (dma_desc->bytes_req == bytes_xfer) + return 0; + residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req); return residual; diff --git a/drivers/dma/xilinx/xdma-regs.h b/drivers/dma/xilinx/xdma-regs.h index 98f5f6fb9ff9..6ad08878e938 100644 --- a/drivers/dma/xilinx/xdma-regs.h +++ b/drivers/dma/xilinx/xdma-regs.h @@ -117,6 +117,9 @@ struct xdma_hw_desc { CHAN_CTRL_IE_WRITE_ERROR | \ CHAN_CTRL_IE_DESC_ERROR) +/* bits of the channel status register */ +#define XDMA_CHAN_STATUS_BUSY BIT(0) + #define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START #define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \ diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c index 170017ff2aad..313b217388fe 100644 --- a/drivers/dma/xilinx/xdma.c +++ b/drivers/dma/xilinx/xdma.c @@ -71,6 +71,8 @@ struct xdma_chan { enum dma_transfer_direction dir; struct dma_slave_config cfg; u32 irq; + struct completion last_interrupt; + bool stop_requested; }; /** @@ -376,6 +378,8 @@ static int xdma_xfer_start(struct xdma_chan *xchan) return ret; xchan->busy = true; + xchan->stop_requested = false; + reinit_completion(&xchan->last_interrupt); return 0; } @@ -387,7 +391,6 @@ static int xdma_xfer_start(struct xdma_chan *xchan) static int xdma_xfer_stop(struct xdma_chan *xchan) { int ret; - u32 val; struct xdma_device *xdev = xchan->xdev_hdl; /* clear run stop bit to prevent any further auto-triggering */ @@ -395,13 +398,7 @@ static int xdma_xfer_stop(struct xdma_chan *xchan) CHAN_CTRL_RUN_STOP); if (ret) return ret; - - /* Clear the channel status register */ - ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val); - if (ret) - return ret; - - return 0; + return ret; } /** @@ -474,6 +471,8 @@ static int xdma_alloc_channels(struct xdma_device *xdev, xchan->xdev_hdl = xdev; xchan->base = base + i * XDMA_CHAN_STRIDE; xchan->dir = dir; + xchan->stop_requested = false; + init_completion(&xchan->last_interrupt); ret = xdma_channel_init(xchan); if (ret) @@ -521,6 +520,7 @@ static int xdma_terminate_all(struct dma_chan *chan) spin_lock_irqsave(&xdma_chan->vchan.lock, flags); xdma_chan->busy = false; + xdma_chan->stop_requested = true; vd = vchan_next_desc(&xdma_chan->vchan); if (vd) { list_del(&vd->node); @@ -542,17 +542,26 @@ static int xdma_terminate_all(struct dma_chan *chan) static void xdma_synchronize(struct dma_chan *chan) { struct xdma_chan *xdma_chan = to_xdma_chan(chan); + struct xdma_device *xdev = xdma_chan->xdev_hdl; + int st = 0; + + /* If the engine continues running, wait for the last interrupt */ + regmap_read(xdev->rmap, xdma_chan->base + XDMA_CHAN_STATUS, &st); + if (st & XDMA_CHAN_STATUS_BUSY) + wait_for_completion_timeout(&xdma_chan->last_interrupt, msecs_to_jiffies(1000)); vchan_synchronize(&xdma_chan->vchan); } /** - * xdma_fill_descs - Fill hardware descriptors with contiguous memory block addresses - * @sw_desc: tx descriptor state container - * @src_addr: Value for a ->src_addr field of a first descriptor - * @dst_addr: Value for a ->dst_addr field of a first descriptor - * @size: Total size of a contiguous memory block - * @filled_descs_num: Number of filled hardware descriptors for corresponding sw_desc + * xdma_fill_descs() - Fill hardware descriptors for one contiguous memory chunk. + * More than one descriptor will be used if the size is bigger + * than XDMA_DESC_BLEN_MAX. + * @sw_desc: Descriptor container + * @src_addr: First value for the ->src_addr field + * @dst_addr: First value for the ->dst_addr field + * @size: Size of the contiguous memory block + * @filled_descs_num: Index of the first descriptor to take care of in @sw_desc */ static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr, u64 dst_addr, u32 size, u32 filled_descs_num) @@ -704,7 +713,7 @@ xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address, desc_num = 0; for (i = 0; i < periods; i++) { desc_num += xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num); - addr += i * period_size; + addr += period_size; } tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags); @@ -876,6 +885,9 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id) u32 st; bool repeat_tx; + if (xchan->stop_requested) + complete(&xchan->last_interrupt); + spin_lock(&xchan->vchan.lock); /* get submitted request */ diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index b82815e64d24..eb0637d90342 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -214,7 +214,8 @@ struct xilinx_dpdma_tx_desc { * @running: true if the channel is running * @first_frame: flag for the first frame of stream * @video_group: flag if multi-channel operation is needed for video channels - * @lock: lock to access struct xilinx_dpdma_chan + * @lock: lock to access struct xilinx_dpdma_chan. Must be taken before + * @vchan.lock, if both are to be held. * @desc_pool: descriptor allocation pool * @err_task: error IRQ bottom half handler * @desc: References to descriptors being processed @@ -1097,12 +1098,14 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan) * Complete the active descriptor, if any, promote the pending * descriptor to active, and queue the next transfer, if any. */ + spin_lock(&chan->vchan.lock); if (chan->desc.active) vchan_cookie_complete(&chan->desc.active->vdesc); chan->desc.active = pending; chan->desc.pending = NULL; xilinx_dpdma_chan_queue_transfer(chan); + spin_unlock(&chan->vchan.lock); out: spin_unlock_irqrestore(&chan->lock, flags); @@ -1264,10 +1267,12 @@ static void xilinx_dpdma_issue_pending(struct dma_chan *dchan) struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan); unsigned long flags; - spin_lock_irqsave(&chan->vchan.lock, flags); + spin_lock_irqsave(&chan->lock, flags); + spin_lock(&chan->vchan.lock); if (vchan_issue_pending(&chan->vchan)) xilinx_dpdma_chan_queue_transfer(chan); - spin_unlock_irqrestore(&chan->vchan.lock, flags); + spin_unlock(&chan->vchan.lock); + spin_unlock_irqrestore(&chan->lock, flags); } static int xilinx_dpdma_config(struct dma_chan *dchan, @@ -1495,7 +1500,9 @@ static void xilinx_dpdma_chan_err_task(struct tasklet_struct *t) XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id); spin_lock_irqsave(&chan->lock, flags); + spin_lock(&chan->vchan.lock); xilinx_dpdma_chan_queue_transfer(chan); + spin_unlock(&chan->vchan.lock); spin_unlock_irqrestore(&chan->lock, flags); } diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 64eaca80d736..d0f6693ca142 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -42,6 +42,7 @@ struct dpll_pin_registration { struct list_head list; const struct dpll_pin_ops *ops; void *priv; + void *cookie; }; struct dpll_device *dpll_device_get_by_id(int id) @@ -54,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id) static struct dpll_pin_registration * dpll_pin_registration_find(struct dpll_pin_ref *ref, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; list_for_each_entry(reg, &ref->registration_list, list) { - if (reg->ops == ops && reg->priv == priv) + if (reg->ops == ops && reg->priv == priv && + reg->cookie == cookie) return reg; } return NULL; @@ -67,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref, static int dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -78,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, xa_for_each(xa_pins, i, ref) { if (ref->pin != pin) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (reg) { refcount_inc(&ref->refcount); return 0; @@ -111,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, } reg->ops = ops; reg->priv = priv; + reg->cookie = cookie; if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -119,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, } static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -128,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, xa_for_each(xa_pins, i, ref) { if (ref->pin != pin) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (WARN_ON(!reg)) return -EINVAL; list_del(®->list); @@ -146,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, static int dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -157,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, xa_for_each(xa_dplls, i, ref) { if (ref->dpll != dpll) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (reg) { refcount_inc(&ref->refcount); return 0; @@ -190,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, } reg->ops = ops; reg->priv = priv; + reg->cookie = cookie; if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -199,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, static void dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -208,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, xa_for_each(xa_dplls, i, ref) { if (ref->dpll != dpll) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (WARN_ON(!reg)) return; list_del(®->list); @@ -594,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put); static int __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { int ret; - ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv); + ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); if (ret) return ret; - ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv); + ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); if (ret) goto ref_pin_del; xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); @@ -610,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, return ret; ref_pin_del: - dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); return ret; } @@ -642,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, dpll->clock_id == pin->clock_id))) ret = -EINVAL; else - ret = __dpll_pin_register(dpll, pin, ops, priv); + ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); mutex_unlock(&dpll_lock); return ret; @@ -651,11 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register); static void __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { ASSERT_DPLL_PIN_REGISTERED(pin); - dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); - dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); + dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); if (xa_empty(&pin->dpll_refs)) xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); } @@ -680,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, mutex_lock(&dpll_lock); dpll_pin_delete_ntf(pin); - __dpll_pin_unregister(dpll, pin, ops, priv); + __dpll_pin_unregister(dpll, pin, ops, priv, NULL); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_pin_unregister); @@ -716,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, return -EINVAL; mutex_lock(&dpll_lock); - ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv); + ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); if (ret) goto unlock; refcount_inc(&pin->refcount); xa_for_each(&parent->dpll_refs, i, ref) { - ret = __dpll_pin_register(ref->dpll, pin, ops, priv); + ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); if (ret) { stop = i; goto dpll_unregister; @@ -735,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, dpll_unregister: xa_for_each(&parent->dpll_refs, i, ref) if (i < stop) { - __dpll_pin_unregister(ref->dpll, pin, ops, priv); + __dpll_pin_unregister(ref->dpll, pin, ops, priv, + parent); dpll_pin_delete_ntf(pin); } refcount_dec(&pin->refcount); - dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); unlock: mutex_unlock(&dpll_lock); return ret; @@ -764,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, mutex_lock(&dpll_lock); dpll_pin_delete_ntf(pin); - dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); refcount_dec(&pin->refcount); xa_for_each(&pin->dpll_refs, i, ref) - __dpll_pin_unregister(ref->dpll, pin, ops, priv); + __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7bc71f4be64a..38d19410a2be 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2060,6 +2060,8 @@ static void bus_reset_work(struct work_struct *work) ohci->generation = generation; reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); + if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) + reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); if (ohci->quirks & QUIRK_RESET_PACKET) ohci->request_generation = generation; @@ -2125,12 +2127,14 @@ static irqreturn_t irq_handler(int irq, void *data) return IRQ_NONE; /* - * busReset and postedWriteErr must not be cleared yet + * busReset and postedWriteErr events must not be cleared yet * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1) */ reg_write(ohci, OHCI1394_IntEventClear, event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr)); log_irqs(ohci, event); + if (event & OHCI1394_busReset) + reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); if (event & OHCI1394_selfIDComplete) queue_work(selfid_workqueue, &ohci->bus_reset_work); diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index f2556a8e9401..9bc2e10381af 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -790,7 +790,7 @@ static void ffa_notification_info_get(void) part_id = packed_id_list[ids_processed++]; - if (!ids_count[list]) { /* Global Notification */ + if (ids_count[list] == 1) { /* Global Notification */ __do_sched_recv_cb(part_id, 0, false); continue; } diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c index ea9201e7044c..1fa79bba492e 100644 --- a/drivers/firmware/arm_scmi/powercap.c +++ b/drivers/firmware/arm_scmi/powercap.c @@ -736,7 +736,7 @@ static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph, ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, POWERCAP_PAI_GET, 4, domain, &fc[POWERCAP_FC_PAI].get_addr, NULL, - &fc[POWERCAP_PAI_GET].rate_limit); + &fc[POWERCAP_FC_PAI].rate_limit); *p_fc = fc; } diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 350573518503..130d13e9cd6b 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -921,7 +921,7 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp) rd->raw = raw; filp->private_data = rd; - return 0; + return nonseekable_open(inode, filp); } static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp) @@ -950,6 +950,7 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = { .open = scmi_dbg_raw_mode_open, .release = scmi_dbg_raw_mode_release, .write = scmi_dbg_raw_mode_reset_write, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -959,6 +960,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = { .read = scmi_dbg_raw_mode_message_read, .write = scmi_dbg_raw_mode_message_write, .poll = scmi_dbg_raw_mode_message_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -975,6 +977,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = { .read = scmi_dbg_raw_mode_message_read, .write = scmi_dbg_raw_mode_message_async_write, .poll = scmi_dbg_raw_mode_message_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -998,6 +1001,7 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = { .release = scmi_dbg_raw_mode_release, .read = scmi_test_dbg_raw_mode_notif_read, .poll = scmi_test_dbg_raw_mode_notif_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -1021,6 +1025,7 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = { .release = scmi_dbg_raw_mode_release, .read = scmi_test_dbg_raw_mode_errors_read, .poll = scmi_test_dbg_raw_mode_errors_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c index 32188f098ef3..bc550ad0dbe0 100644 --- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c +++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c @@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info { * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t, * however, has an alignment of 4 byte (32 bits). So far, this seems to work * fine here. See also the comment on the typedef of efi_guid_t. + * + * Note: It looks like uefisecapp is quite picky about how the memory passed to + * it is structured and aligned. In particular the request/response setup used + * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory, + * accepts separate buffers/addresses for the request and response parts, in + * practice, however, it seems to expect them to be both part of a larger + * contiguous block. We initially allocated separate buffers for the request + * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to + * either not write any response to the response buffer or outright crash the + * device. Therefore, we now allocate a single contiguous block of DMA memory + * for both and properly align the data using the macros below. In particular, + * request and response structs are aligned at 8 byte (via __reqdata_offs()), + * following the driver that this has been reverse-engineered from. */ #define qcuefi_buf_align_fields(fields...) \ ({ \ @@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info { #define __array_offs(type, count, offset) \ __field_impl(sizeof(type) * (count), __alignof__(type), offset) +#define __array_offs_aligned(type, count, align, offset) \ + __field_impl(sizeof(type) * (count), align, offset) + +#define __reqdata_offs(size, offset) \ + __array_offs_aligned(u8, size, 8, offset) + #define __array(type, count) __array_offs(type, count, NULL) #define __field_offs(type, offset) __array_offs(type, 1, offset) #define __field(type) __array_offs(type, 1, NULL) @@ -277,10 +296,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e unsigned long buffer_size = *data_size; efi_status_t efi_status = EFI_SUCCESS; unsigned long name_length; + dma_addr_t cmd_buf_dma; + size_t cmd_buf_size; + void *cmd_buf; size_t guid_offs; size_t name_offs; size_t req_size; size_t rsp_size; + size_t req_offs; + size_t rsp_offs; ssize_t status; if (!name || !guid) @@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e __array(u8, buffer_size) ); - req_data = kzalloc(req_size, GFP_KERNEL); - if (!req_data) { + cmd_buf_size = qcuefi_buf_align_fields( + __reqdata_offs(req_size, &req_offs) + __reqdata_offs(rsp_size, &rsp_offs) + ); + + cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); + if (!cmd_buf) { efi_status = EFI_OUT_OF_RESOURCES; goto out; } - rsp_data = kzalloc(rsp_size, GFP_KERNEL); - if (!rsp_data) { - efi_status = EFI_OUT_OF_RESOURCES; - goto out_free_req; - } + req_data = cmd_buf + req_offs; + rsp_data = cmd_buf + rsp_offs; req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE; req_data->data_size = buffer_size; @@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size); - status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size); + status = qcom_qseecom_app_send(qcuefi->client, + cmd_buf_dma + req_offs, req_size, + cmd_buf_dma + rsp_offs, rsp_size); if (status) { efi_status = EFI_DEVICE_ERROR; goto out_free; @@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size); out_free: - kfree(rsp_data); -out_free_req: - kfree(req_data); + qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); out: return efi_status; } @@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e struct qsee_rsp_uefi_set_variable *rsp_data; efi_status_t efi_status = EFI_SUCCESS; unsigned long name_length; + dma_addr_t cmd_buf_dma; + size_t cmd_buf_size; + void *cmd_buf; size_t name_offs; size_t guid_offs; size_t data_offs; size_t req_size; + size_t req_offs; + size_t rsp_offs; ssize_t status; if (!name || !guid) @@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e __array_offs(u8, data_size, &data_offs) ); - req_data = kzalloc(req_size, GFP_KERNEL); - if (!req_data) { + cmd_buf_size = qcuefi_buf_align_fields( + __reqdata_offs(req_size, &req_offs) + __reqdata_offs(sizeof(*rsp_data), &rsp_offs) + ); + + cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); + if (!cmd_buf) { efi_status = EFI_OUT_OF_RESOURCES; goto out; } - rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL); - if (!rsp_data) { - efi_status = EFI_OUT_OF_RESOURCES; - goto out_free_req; - } + req_data = cmd_buf + req_offs; + rsp_data = cmd_buf + rsp_offs; req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE; req_data->attributes = attributes; @@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e if (data_size) memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size); - status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, - sizeof(*rsp_data)); + status = qcom_qseecom_app_send(qcuefi->client, + cmd_buf_dma + req_offs, req_size, + cmd_buf_dma + rsp_offs, sizeof(*rsp_data)); if (status) { efi_status = EFI_DEVICE_ERROR; goto out_free; @@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e } out_free: - kfree(rsp_data); -out_free_req: - kfree(req_data); + qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); out: return efi_status; } @@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, struct qsee_req_uefi_get_next_variable *req_data; struct qsee_rsp_uefi_get_next_variable *rsp_data; efi_status_t efi_status = EFI_SUCCESS; + dma_addr_t cmd_buf_dma; + size_t cmd_buf_size; + void *cmd_buf; size_t guid_offs; size_t name_offs; size_t req_size; size_t rsp_size; + size_t req_offs; + size_t rsp_offs; ssize_t status; if (!name_size || !name || !guid) @@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, __array(*name, *name_size / sizeof(*name)) ); - req_data = kzalloc(req_size, GFP_KERNEL); - if (!req_data) { + cmd_buf_size = qcuefi_buf_align_fields( + __reqdata_offs(req_size, &req_offs) + __reqdata_offs(rsp_size, &rsp_offs) + ); + + cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); + if (!cmd_buf) { efi_status = EFI_OUT_OF_RESOURCES; goto out; } - rsp_data = kzalloc(rsp_size, GFP_KERNEL); - if (!rsp_data) { - efi_status = EFI_OUT_OF_RESOURCES; - goto out_free_req; - } + req_data = cmd_buf + req_offs; + rsp_data = cmd_buf + rsp_offs; req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE; req_data->guid_offset = guid_offs; @@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, goto out_free; } - status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size); + status = qcom_qseecom_app_send(qcuefi->client, + cmd_buf_dma + req_offs, req_size, + cmd_buf_dma + rsp_offs, rsp_size); if (status) { efi_status = EFI_DEVICE_ERROR; goto out_free; @@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi, } out_free: - kfree(rsp_data); -out_free_req: - kfree(req_data); + qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); out: return efi_status; } @@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, struct qsee_req_uefi_query_variable_info *req_data; struct qsee_rsp_uefi_query_variable_info *rsp_data; efi_status_t efi_status = EFI_SUCCESS; + dma_addr_t cmd_buf_dma; + size_t cmd_buf_size; + void *cmd_buf; + size_t req_offs; + size_t rsp_offs; int status; - req_data = kzalloc(sizeof(*req_data), GFP_KERNEL); - if (!req_data) { + cmd_buf_size = qcuefi_buf_align_fields( + __reqdata_offs(sizeof(*req_data), &req_offs) + __reqdata_offs(sizeof(*rsp_data), &rsp_offs) + ); + + cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL); + if (!cmd_buf) { efi_status = EFI_OUT_OF_RESOURCES; goto out; } - rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL); - if (!rsp_data) { - efi_status = EFI_OUT_OF_RESOURCES; - goto out_free_req; - } + req_data = cmd_buf + req_offs; + rsp_data = cmd_buf + rsp_offs; req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO; req_data->attributes = attr; req_data->length = sizeof(*req_data); - status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data, - sizeof(*rsp_data)); + status = qcom_qseecom_app_send(qcuefi->client, + cmd_buf_dma + req_offs, sizeof(*req_data), + cmd_buf_dma + rsp_offs, sizeof(*rsp_data)); if (status) { efi_status = EFI_DEVICE_ERROR; goto out_free; @@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi, *max_variable_size = rsp_data->max_variable_size; out_free: - kfree(rsp_data); -out_free_req: - kfree(req_data); + qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma); out: return efi_status; } diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c index 520de9b5633a..90283f160a22 100644 --- a/drivers/firmware/qcom/qcom_scm.c +++ b/drivers/firmware/qcom/qcom_scm.c @@ -1576,9 +1576,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id); /** * qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app. * @app_id: The ID of the target app. - * @req: Request buffer sent to the app (must be DMA-mappable). + * @req: DMA address of the request buffer sent to the app. * @req_size: Size of the request buffer. - * @rsp: Response buffer, written to by the app (must be DMA-mappable). + * @rsp: DMA address of the response buffer, written to by the app. * @rsp_size: Size of the response buffer. * * Sends a request to the QSEE app associated with the given ID and read back @@ -1589,33 +1589,13 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id); * * Return: Zero on success, nonzero on failure. */ -int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp, - size_t rsp_size) +int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size, + dma_addr_t rsp, size_t rsp_size) { struct qcom_scm_qseecom_resp res = {}; struct qcom_scm_desc desc = {}; - dma_addr_t req_phys; - dma_addr_t rsp_phys; int status; - /* Map request buffer */ - req_phys = dma_map_single(__scm->dev, req, req_size, DMA_TO_DEVICE); - status = dma_mapping_error(__scm->dev, req_phys); - if (status) { - dev_err(__scm->dev, "qseecom: failed to map request buffer\n"); - return status; - } - - /* Map response buffer */ - rsp_phys = dma_map_single(__scm->dev, rsp, rsp_size, DMA_FROM_DEVICE); - status = dma_mapping_error(__scm->dev, rsp_phys); - if (status) { - dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE); - dev_err(__scm->dev, "qseecom: failed to map response buffer\n"); - return status; - } - - /* Set up SCM call data */ desc.owner = QSEECOM_TZ_OWNER_TZ_APPS; desc.svc = QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER; desc.cmd = QSEECOM_TZ_CMD_APP_SEND; @@ -1623,18 +1603,13 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp, QCOM_SCM_RW, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL); desc.args[0] = app_id; - desc.args[1] = req_phys; + desc.args[1] = req; desc.args[2] = req_size; - desc.args[3] = rsp_phys; + desc.args[3] = rsp; desc.args[4] = rsp_size; - /* Perform call */ status = qcom_scm_qseecom_call(&desc, &res); - /* Unmap buffers */ - dma_unmap_single(__scm->dev, rsp_phys, rsp_size, DMA_FROM_DEVICE); - dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE); - if (status) return status; diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 1ee62cd58582..25db014494a4 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) case 0x5e: return GPIOPANELCTL; default: - return -EOPNOTSUPP; + return -ENOTSUPP; } } diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 5ef8af824980..c097e310c9e8 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = { { .compatible = "nxp,lpc3220-gpio", }, { }, }; +MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match); static struct platform_driver lpc32xx_gpio_driver = { .driver = { diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c index b75e0b12087a..4b29abafecf6 100644 --- a/drivers/gpio/gpio-tangier.c +++ b/drivers/gpio/gpio-tangier.c @@ -195,7 +195,8 @@ static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset, static void tng_irq_ack(struct irq_data *d) { - struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct tng_gpio *priv = gpiochip_get_data(gc); irq_hw_number_t gpio = irqd_to_hwirq(d); void __iomem *gisr; u8 shift; @@ -227,7 +228,8 @@ static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask) static void tng_irq_mask(struct irq_data *d) { - struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct tng_gpio *priv = gpiochip_get_data(gc); irq_hw_number_t gpio = irqd_to_hwirq(d); tng_irq_unmask_mask(priv, gpio, false); @@ -236,7 +238,8 @@ static void tng_irq_mask(struct irq_data *d) static void tng_irq_unmask(struct irq_data *d) { - struct tng_gpio *priv = irq_data_get_irq_chip_data(d); + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + struct tng_gpio *priv = gpiochip_get_data(gc); irq_hw_number_t gpio = irqd_to_hwirq(d); gpiochip_enable_irq(&priv->chip, gpio); diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index d87dd06db40d..9130c691a2dd 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -36,12 +36,6 @@ #define TEGRA186_GPIO_SCR_SEC_REN BIT(27) #define TEGRA186_GPIO_SCR_SEC_G1W BIT(9) #define TEGRA186_GPIO_SCR_SEC_G1R BIT(1) -#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \ - TEGRA186_GPIO_SCR_SEC_REN | \ - TEGRA186_GPIO_SCR_SEC_G1R | \ - TEGRA186_GPIO_SCR_SEC_G1W) -#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \ - TEGRA186_GPIO_SCR_SEC_REN) /* control registers */ #define TEGRA186_GPIO_ENABLE_CONFIG 0x00 @@ -177,10 +171,18 @@ static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned value = __raw_readl(secure + TEGRA186_GPIO_SCR); - if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0) - return true; + /* + * When SCR_SEC_[R|W]EN is unset, then we have full read/write access to all the + * registers for given GPIO pin. + * When SCR_SEC[R|W]EN is set, then there is need to further check the accompanying + * SCR_SEC_G1[R|W] bit to determine read/write access to all the registers for given + * GPIO pin. + */ - if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS) + if (((value & TEGRA186_GPIO_SCR_SEC_REN) == 0 || + ((value & TEGRA186_GPIO_SCR_SEC_REN) && (value & TEGRA186_GPIO_SCR_SEC_G1R))) && + ((value & TEGRA186_GPIO_SCR_SEC_WEN) == 0 || + ((value & TEGRA186_GPIO_SCR_SEC_WEN) && (value & TEGRA186_GPIO_SCR_SEC_G1W)))) return true; return false; diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index c18b6b47384f..94ca9d03c094 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type) unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE; if (gpio >= WCOVE_GPIO_NUM) - return -EOPNOTSUPP; + return -ENOTSUPP; return reg + gpio; } diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index fa9635610251..d09c7d728365 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -728,6 +728,25 @@ static u32 line_event_id(int level) GPIO_V2_LINE_EVENT_FALLING_EDGE; } +static inline char *make_irq_label(const char *orig) +{ + char *new; + + if (!orig) + return NULL; + + new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); + if (!new) + return ERR_PTR(-ENOMEM); + + return new; +} + +static inline void free_irq_label(const char *label) +{ + kfree(label); +} + #ifdef CONFIG_HTE static enum hte_return process_hw_ts_thread(void *p) @@ -1015,6 +1034,7 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) { unsigned long irqflags; int ret, level, irq; + char *label; /* try hardware */ ret = gpiod_set_debounce(line->desc, debounce_period_us); @@ -1037,11 +1057,17 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us) if (irq < 0) return -ENXIO; + label = make_irq_label(line->req->label); + if (IS_ERR(label)) + return -ENOMEM; + irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING; ret = request_irq(irq, debounce_irq_handler, irqflags, - line->req->label, line); - if (ret) + label, line); + if (ret) { + free_irq_label(label); return ret; + } line->irq = irq; } else { ret = hte_edge_setup(line, GPIO_V2_LINE_FLAG_EDGE_BOTH); @@ -1083,16 +1109,6 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc, return 0; } -static inline char *make_irq_label(const char *orig) -{ - return kstrdup_and_replace(orig, '/', ':', GFP_KERNEL); -} - -static inline void free_irq_label(const char *label) -{ - kfree(label); -} - static void edge_detector_stop(struct line *line) { if (line->irq) { @@ -1158,8 +1174,8 @@ static int edge_detector_setup(struct line *line, irqflags |= IRQF_ONESHOT; label = make_irq_label(line->req->label); - if (!label) - return -ENOMEM; + if (IS_ERR(label)) + return PTR_ERR(label); /* Request a thread to read the events */ ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread, @@ -2217,8 +2233,8 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) goto out_free_le; label = make_irq_label(le->label); - if (!label) { - ret = -ENOMEM; + if (IS_ERR(label)) { + ret = PTR_ERR(label); goto out_free_le; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 59ccf9a3e153..94903fc1c145 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1175,6 +1175,9 @@ struct gpio_device *gpio_device_find(const void *data, list_for_each_entry_srcu(gdev, &gpio_devices, list, srcu_read_lock_held(&gpio_devices_srcu)) { + if (!device_is_registered(&gdev->dev)) + continue; + guard(srcu)(&gdev->srcu); gc = srcu_dereference(gdev->chip, &gdev->srcu); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3914aaf443a8..959b19a04101 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -104,6 +104,38 @@ config DRM_KMS_HELPER help CRTC helpers for KMS drivers. +config DRM_PANIC + bool "Display a user-friendly message when a kernel panic occurs" + depends on DRM && !FRAMEBUFFER_CONSOLE + select DRM_KMS_HELPER + select FONT_SUPPORT + help + Enable a drm panic handler, which will display a user-friendly message + when a kernel panic occurs. It's useful when using a user-space + console instead of fbcon. + It will only work if your graphic driver supports this feature. + To support Hi-DPI Display, you can enable bigger fonts like + FONT_TER16x32 + +config DRM_PANIC_FOREGROUND_COLOR + hex "Drm panic screen foreground color, in RGB" + depends on DRM_PANIC + default 0xffffff + +config DRM_PANIC_BACKGROUND_COLOR + hex "Drm panic screen background color, in RGB" + depends on DRM_PANIC + default 0x000000 + +config DRM_PANIC_DEBUG + bool "Add a debug fs entry to trigger drm_panic" + depends on DRM_PANIC && DEBUG_FS + help + Add dri/[device]/drm_panic_plane_x in the kernel debugfs, to force the + panic handler to write the panic message to this plane scanout buffer. + This is unsafe and should not be enabled on a production build. + If in doubt, say "N". + config DRM_DEBUG_DP_MST_TOPOLOGY_REFS bool "Enable refcount backtrace history in the DP MST helpers" depends on STACKTRACE_SUPPORT diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a73c04d2d7a3..f9ca4f8fa6c5 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -88,6 +88,7 @@ drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \ drm_privacy_screen.o \ drm_privacy_screen_x86.o drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o +drm-$(CONFIG_DRM_PANIC) += drm_panic.o obj-$(CONFIG_DRM) += drm.o obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 4536c8ad0e11..1f6b56ec99f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -70,7 +70,8 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o \ atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ - amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_ib.o amdgpu_pll.o \ + amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_vm_tlb_fence.o \ + amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \ amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \ @@ -80,7 +81,7 @@ amdgpu-y += amdgpu_device.o amdgpu_doorbell_mgr.o amdgpu_kms.o \ amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o \ amdgpu_fw_attestation.o amdgpu_securedisplay.o \ amdgpu_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \ - amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o + amdgpu_ring_mux.o amdgpu_xcp.o amdgpu_seq64.o amdgpu_aca.o amdgpu_dev_coredump.o amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o @@ -247,7 +248,8 @@ amdgpu-y += \ smuio_v11_0_6.o \ smuio_v13_0.o \ smuio_v13_0_3.o \ - smuio_v13_0_6.o + smuio_v13_0_6.o \ + smuio_v14_0_2.o # add reset block amdgpu-y += \ diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c index 576067d66bb9..d0a8da67dc2a 100644 --- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c +++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c @@ -97,7 +97,7 @@ static int aldebaran_mode2_suspend_ip(struct amdgpu_device *adev) adev->ip_blocks[i].status.hw = false; } - return r; + return 0; } static int diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9c62552bec34..f87d53e183c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -139,6 +139,14 @@ enum amdgpu_ss { AMDGPU_SS_DRV_UNLOAD }; +struct amdgpu_hwip_reg_entry { + u32 hwip; + u32 inst; + u32 seg; + u32 reg_offset; + const char *reg_name; +}; + struct amdgpu_watchdog_timer { bool timeout_fatal_disable; uint32_t period; /* maxCycles = (1 << period), the number of cycles before a timeout */ @@ -210,6 +218,7 @@ extern int amdgpu_async_gfx_ring; extern int amdgpu_mcbp; extern int amdgpu_discovery; extern int amdgpu_mes; +extern int amdgpu_mes_log_enable; extern int amdgpu_mes_kiq; extern int amdgpu_noretry; extern int amdgpu_force_asic_type; @@ -493,6 +502,7 @@ struct amdgpu_wb { uint64_t gpu_addr; u32 num_wb; /* Number of wb slots actually reserved for amdgpu. */ unsigned long used[DIV_ROUND_UP(AMDGPU_MAX_WB, BITS_PER_LONG)]; + spinlock_t lock; }; int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb); @@ -605,7 +615,7 @@ struct amdgpu_asic_funcs { /* PCIe replay counter */ uint64_t (*get_pcie_replay_count)(struct amdgpu_device *adev); /* device supports BACO */ - bool (*supports_baco)(struct amdgpu_device *adev); + int (*supports_baco)(struct amdgpu_device *adev); /* pre asic_init quirks */ void (*pre_asic_init)(struct amdgpu_device *adev); /* enter/exit umd stable pstate */ @@ -1407,7 +1417,8 @@ bool amdgpu_device_supports_atpx(struct drm_device *dev); bool amdgpu_device_supports_px(struct drm_device *dev); bool amdgpu_device_supports_boco(struct drm_device *dev); bool amdgpu_device_supports_smart_shift(struct drm_device *dev); -bool amdgpu_device_supports_baco(struct drm_device *dev); +int amdgpu_device_supports_baco(struct drm_device *dev); +void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev); bool amdgpu_device_is_peer_accessible(struct amdgpu_device *adev, struct amdgpu_device *peer_adev); int amdgpu_device_baco_enter(struct drm_device *dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c index 493982f94649..c50202215f6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.c @@ -28,7 +28,7 @@ #define ACA_BANK_HWID(type, hwid, mcatype) [ACA_HWIP_TYPE_##type] = {hwid, mcatype} -typedef int bank_handler_t(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, void *data); +typedef int bank_handler_t(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data); struct aca_banks { int nr_banks; @@ -86,7 +86,7 @@ static void aca_banks_release(struct aca_banks *banks) } } -static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, enum aca_error_type type, u32 *count) +static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, enum aca_smu_type type, u32 *count) { struct amdgpu_aca *aca = &adev->aca; const struct aca_smu_funcs *smu_funcs = aca->smu_funcs; @@ -116,20 +116,22 @@ static struct aca_regs_dump { {"CONTROL_MASK", ACA_REG_IDX_CTL_MASK}, }; -static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank) +static void aca_smu_bank_dump(struct amdgpu_device *adev, int idx, int total, struct aca_bank *bank, + struct ras_query_context *qctx) { + u64 event_id = qctx ? qctx->event_id : 0ULL; int i; - dev_info(adev->dev, HW_ERR "Accelerator Check Architecture events logged\n"); + RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n"); /* plus 1 for output format, e.g: ACA[08/08]: xxxx */ for (i = 0; i < ARRAY_SIZE(aca_regs); i++) - dev_info(adev->dev, HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n", - idx + 1, total, aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]); + RAS_EVENT_LOG(adev, event_id, HW_ERR "ACA[%02d/%02d].%s=0x%016llx\n", + idx + 1, total, aca_regs[i].name, bank->regs[aca_regs[i].reg_idx]); } -static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_error_type type, +static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_smu_type type, int start, int count, - struct aca_banks *banks) + struct aca_banks *banks, struct ras_query_context *qctx) { struct amdgpu_aca *aca = &adev->aca; const struct aca_smu_funcs *smu_funcs = aca->smu_funcs; @@ -143,13 +145,12 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_erro return -EOPNOTSUPP; switch (type) { - case ACA_ERROR_TYPE_UE: + case ACA_SMU_TYPE_UE: max_count = smu_funcs->max_ue_bank_count; break; - case ACA_ERROR_TYPE_CE: + case ACA_SMU_TYPE_CE: max_count = smu_funcs->max_ce_bank_count; break; - case ACA_ERROR_TYPE_DEFERRED: default: return -EINVAL; } @@ -164,7 +165,9 @@ static int aca_smu_get_valid_aca_banks(struct amdgpu_device *adev, enum aca_erro if (ret) return ret; - aca_smu_bank_dump(adev, i, count, &bank); + bank.type = type; + + aca_smu_bank_dump(adev, i, count, &bank, qctx); ret = aca_banks_add_bank(banks, &bank); if (ret) @@ -195,7 +198,7 @@ static bool aca_bank_hwip_is_matched(struct aca_bank *bank, enum aca_hwip_type t return hwip->hwid == hwid && hwip->mcatype == mcatype; } -static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type) +static bool aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type) { const struct aca_bank_ops *bank_ops = handle->bank_ops; @@ -273,59 +276,49 @@ static struct aca_bank_error *get_bank_error(struct aca_error *aerr, struct aca_ return new_bank_error(aerr, info); } -static int aca_log_errors(struct aca_handle *handle, enum aca_error_type type, - struct aca_bank_report *report) +int aca_error_cache_log_bank_error(struct aca_handle *handle, struct aca_bank_info *info, + enum aca_error_type type, u64 count) { struct aca_error_cache *error_cache = &handle->error_cache; struct aca_bank_error *bank_error; struct aca_error *aerr; - if (!handle || !report) + if (!handle || !info || type >= ACA_ERROR_TYPE_COUNT) return -EINVAL; - if (!report->count[type]) + if (!count) return 0; aerr = &error_cache->errors[type]; - bank_error = get_bank_error(aerr, &report->info); + bank_error = get_bank_error(aerr, info); if (!bank_error) return -ENOMEM; - bank_error->count[type] += report->count[type]; + bank_error->count += count; return 0; } -static int aca_generate_bank_report(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, struct aca_bank_report *report) +static int aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type) { const struct aca_bank_ops *bank_ops = handle->bank_ops; - if (!bank || !report) + if (!bank) return -EINVAL; - if (!bank_ops->aca_bank_generate_report) + if (!bank_ops->aca_bank_parser) return -EOPNOTSUPP; - memset(report, 0, sizeof(*report)); - return bank_ops->aca_bank_generate_report(handle, bank, type, - report, handle->data); + return bank_ops->aca_bank_parser(handle, bank, type, + handle->data); } static int handler_aca_log_bank_error(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, void *data) + enum aca_smu_type type, void *data) { - struct aca_bank_report report; int ret; - ret = aca_generate_bank_report(handle, bank, type, &report); - if (ret) - return ret; - - if (!report.count[type]) - return 0; - - ret = aca_log_errors(handle, type, &report); + ret = aca_bank_parser(handle, bank, type); if (ret) return ret; @@ -333,7 +326,7 @@ static int handler_aca_log_bank_error(struct aca_handle *handle, struct aca_bank } static int aca_dispatch_bank(struct aca_handle_manager *mgr, struct aca_bank *bank, - enum aca_error_type type, bank_handler_t handler, void *data) + enum aca_smu_type type, bank_handler_t handler, void *data) { struct aca_handle *handle; int ret; @@ -354,7 +347,7 @@ static int aca_dispatch_bank(struct aca_handle_manager *mgr, struct aca_bank *ba } static int aca_dispatch_banks(struct aca_handle_manager *mgr, struct aca_banks *banks, - enum aca_error_type type, bank_handler_t handler, void *data) + enum aca_smu_type type, bank_handler_t handler, void *data) { struct aca_bank_node *node; struct aca_bank *bank; @@ -378,8 +371,28 @@ static int aca_dispatch_banks(struct aca_handle_manager *mgr, struct aca_banks * return 0; } -static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type, - bank_handler_t handler, void *data) +static bool aca_bank_should_update(struct amdgpu_device *adev, enum aca_smu_type type) +{ + struct amdgpu_aca *aca = &adev->aca; + bool ret = true; + + /* + * Because the UE Valid MCA count will only be cleared after reset, + * in order to avoid repeated counting of the error count, + * the aca bank is only updated once during the gpu recovery stage. + */ + if (type == ACA_SMU_TYPE_UE) { + if (amdgpu_ras_intr_triggered()) + ret = atomic_cmpxchg(&aca->ue_update_flag, 0, 1) == 0; + else + atomic_set(&aca->ue_update_flag, 0); + } + + return ret; +} + +static int aca_banks_update(struct amdgpu_device *adev, enum aca_smu_type type, + bank_handler_t handler, struct ras_query_context *qctx, void *data) { struct amdgpu_aca *aca = &adev->aca; struct aca_banks banks; @@ -389,9 +402,8 @@ static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type if (list_empty(&aca->mgr.list)) return 0; - /* NOTE: pmfw is only support UE and CE */ - if (type == ACA_ERROR_TYPE_DEFERRED) - type = ACA_ERROR_TYPE_CE; + if (!aca_bank_should_update(adev, type)) + return 0; ret = aca_smu_get_valid_aca_count(adev, type, &count); if (ret) @@ -402,7 +414,7 @@ static int aca_banks_update(struct amdgpu_device *adev, enum aca_error_type type aca_banks_init(&banks); - ret = aca_smu_get_valid_aca_banks(adev, type, 0, count, &banks); + ret = aca_smu_get_valid_aca_banks(adev, type, 0, count, &banks, qctx); if (ret) goto err_release_banks; @@ -431,7 +443,7 @@ static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_er if (type >= ACA_ERROR_TYPE_COUNT) return -EINVAL; - count = bank_error->count[type]; + count = bank_error->count; if (!count) return 0; @@ -447,6 +459,8 @@ static int aca_log_aca_error_data(struct aca_bank_error *bank_error, enum aca_er amdgpu_ras_error_statistic_ce_count(err_data, &mcm_info, NULL, count); break; case ACA_ERROR_TYPE_DEFERRED: + amdgpu_ras_error_statistic_de_count(err_data, &mcm_info, NULL, count); + break; default: break; } @@ -477,12 +491,25 @@ static int aca_log_aca_error(struct aca_handle *handle, enum aca_error_type type } static int __aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, enum aca_error_type type, - struct ras_err_data *err_data) + struct ras_err_data *err_data, struct ras_query_context *qctx) { + enum aca_smu_type smu_type; int ret; + switch (type) { + case ACA_ERROR_TYPE_UE: + smu_type = ACA_SMU_TYPE_UE; + break; + case ACA_ERROR_TYPE_CE: + case ACA_ERROR_TYPE_DEFERRED: + smu_type = ACA_SMU_TYPE_CE; + break; + default: + return -EINVAL; + } + /* udpate aca bank to aca source error_cache first */ - ret = aca_banks_update(adev, type, handler_aca_log_bank_error, NULL); + ret = aca_banks_update(adev, smu_type, handler_aca_log_bank_error, qctx, NULL); if (ret) return ret; @@ -498,10 +525,9 @@ static bool aca_handle_is_valid(struct aca_handle *handle) } int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, - enum aca_error_type type, void *data) + enum aca_error_type type, struct ras_err_data *err_data, + struct ras_query_context *qctx) { - struct ras_err_data *err_data = (struct ras_err_data *)data; - if (!handle || !err_data) return -EINVAL; @@ -511,7 +537,7 @@ int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *han if (!(BIT(type) & handle->mask)) return 0; - return __aca_get_error_data(adev, handle, type, err_data); + return __aca_get_error_data(adev, handle, type, err_data, qctx); } static void aca_error_init(struct aca_error *aerr, enum aca_error_type type) @@ -668,6 +694,8 @@ int amdgpu_aca_init(struct amdgpu_device *adev) struct amdgpu_aca *aca = &adev->aca; int ret; + atomic_set(&aca->ue_update_flag, 0); + ret = aca_manager_init(&aca->mgr); if (ret) return ret; @@ -680,6 +708,8 @@ void amdgpu_aca_fini(struct amdgpu_device *adev) struct amdgpu_aca *aca = &adev->aca; aca_manager_fini(&aca->mgr); + + atomic_set(&aca->ue_update_flag, 0); } int amdgpu_aca_reset(struct amdgpu_device *adev) @@ -723,23 +753,13 @@ int aca_bank_info_decode(struct aca_bank *bank, struct aca_bank_info *info) static int aca_bank_get_error_code(struct amdgpu_device *adev, struct aca_bank *bank) { - int error_code; + struct amdgpu_aca *aca = &adev->aca; + const struct aca_smu_funcs *smu_funcs = aca->smu_funcs; - switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { - case IP_VERSION(13, 0, 6): - if (!(adev->flags & AMD_IS_APU) && adev->pm.fw_version >= 0x00555600) { - error_code = ACA_REG__SYND__ERRORINFORMATION(bank->regs[ACA_REG_IDX_SYND]); - return error_code & 0xff; - } - break; - default: - break; - } + if (!smu_funcs || !smu_funcs->parse_error_code) + return -EOPNOTSUPP; - /* NOTE: the true error code is encoded in status.errorcode[0:7] */ - error_code = ACA_REG__STATUS__ERRORCODE(bank->regs[ACA_REG_IDX_STATUS]); - - return error_code & 0xff; + return smu_funcs->parse_error_code(adev, bank); } int aca_bank_check_error_codes(struct amdgpu_device *adev, struct aca_bank *bank, int *err_codes, int size) @@ -750,6 +770,9 @@ int aca_bank_check_error_codes(struct amdgpu_device *adev, struct aca_bank *bank return -EINVAL; error_code = aca_bank_get_error_code(adev, bank); + if (error_code < 0) + return error_code; + for (i = 0; i < size; i++) { if (err_codes[i] == error_code) return 0; @@ -784,7 +807,7 @@ static int amdgpu_aca_smu_debug_mode_set(void *data, u64 val) return 0; } -static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_error_type type, int idx) +static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_smu_type type, int idx) { struct aca_bank_info info; int i, ret; @@ -793,7 +816,7 @@ static void aca_dump_entry(struct seq_file *m, struct aca_bank *bank, enum aca_e if (ret) return; - seq_printf(m, "aca entry[%d].type: %s\n", idx, type == ACA_ERROR_TYPE_UE ? "UE" : "CE"); + seq_printf(m, "aca entry[%d].type: %s\n", idx, type == ACA_SMU_TYPE_UE ? "UE" : "CE"); seq_printf(m, "aca entry[%d].info: socketid:%d aid:%d hwid:0x%03x mcatype:0x%04x\n", idx, info.socket_id, info.die_id, info.hwid, info.mcatype); @@ -807,7 +830,7 @@ struct aca_dump_context { }; static int handler_aca_bank_dump(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, void *data) + enum aca_smu_type type, void *data) { struct aca_dump_context *ctx = (struct aca_dump_context *)data; @@ -816,7 +839,7 @@ static int handler_aca_bank_dump(struct aca_handle *handle, struct aca_bank *ban return handler_aca_log_bank_error(handle, bank, type, NULL); } -static int aca_dump_show(struct seq_file *m, enum aca_error_type type) +static int aca_dump_show(struct seq_file *m, enum aca_smu_type type) { struct amdgpu_device *adev = (struct amdgpu_device *)m->private; struct aca_dump_context context = { @@ -824,12 +847,12 @@ static int aca_dump_show(struct seq_file *m, enum aca_error_type type) .idx = 0, }; - return aca_banks_update(adev, type, handler_aca_bank_dump, (void *)&context); + return aca_banks_update(adev, type, handler_aca_bank_dump, NULL, (void *)&context); } static int aca_dump_ce_show(struct seq_file *m, void *unused) { - return aca_dump_show(m, ACA_ERROR_TYPE_CE); + return aca_dump_show(m, ACA_SMU_TYPE_CE); } static int aca_dump_ce_open(struct inode *inode, struct file *file) @@ -847,7 +870,7 @@ static const struct file_operations aca_ce_dump_debug_fops = { static int aca_dump_ue_show(struct seq_file *m, void *unused) { - return aca_dump_show(m, ACA_ERROR_TYPE_UE); + return aca_dump_show(m, ACA_SMU_TYPE_UE); } static int aca_dump_ue_open(struct inode *inode, struct file *file) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h index 2da50e095883..5ef6b745f222 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_aca.h @@ -26,6 +26,9 @@ #include +struct ras_err_data; +struct ras_query_context; + #define ACA_MAX_REGS_COUNT (16) #define ACA_REG_FIELD(x, h, l) (((x) & GENMASK_ULL(h, l)) >> l) @@ -99,7 +102,14 @@ enum aca_error_type { ACA_ERROR_TYPE_COUNT }; +enum aca_smu_type { + ACA_SMU_TYPE_UE = 0, + ACA_SMU_TYPE_CE, + ACA_SMU_TYPE_COUNT, +}; + struct aca_bank { + enum aca_smu_type type; u64 regs[ACA_MAX_REGS_COUNT]; }; @@ -115,15 +125,10 @@ struct aca_bank_info { int mcatype; }; -struct aca_bank_report { - struct aca_bank_info info; - u64 count[ACA_ERROR_TYPE_COUNT]; -}; - struct aca_bank_error { struct list_head node; struct aca_bank_info info; - u64 count[ACA_ERROR_TYPE_COUNT]; + u64 count; }; struct aca_error { @@ -157,9 +162,8 @@ struct aca_handle { }; struct aca_bank_ops { - int (*aca_bank_generate_report)(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data); - bool (*aca_bank_is_valid)(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, + int (*aca_bank_parser)(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data); + bool (*aca_bank_is_valid)(struct aca_handle *handle, struct aca_bank *bank, enum aca_smu_type type, void *data); }; @@ -167,13 +171,15 @@ struct aca_smu_funcs { int max_ue_bank_count; int max_ce_bank_count; int (*set_debug_mode)(struct amdgpu_device *adev, bool enable); - int (*get_valid_aca_count)(struct amdgpu_device *adev, enum aca_error_type type, u32 *count); - int (*get_valid_aca_bank)(struct amdgpu_device *adev, enum aca_error_type type, int idx, struct aca_bank *bank); + int (*get_valid_aca_count)(struct amdgpu_device *adev, enum aca_smu_type type, u32 *count); + int (*get_valid_aca_bank)(struct amdgpu_device *adev, enum aca_smu_type type, int idx, struct aca_bank *bank); + int (*parse_error_code)(struct amdgpu_device *adev, struct aca_bank *bank); }; struct amdgpu_aca { struct aca_handle_manager mgr; const struct aca_smu_funcs *smu_funcs; + atomic_t ue_update_flag; bool is_enabled; }; @@ -196,7 +202,10 @@ int amdgpu_aca_add_handle(struct amdgpu_device *adev, struct aca_handle *handle, const char *name, const struct aca_info *aca_info, void *data); void amdgpu_aca_remove_handle(struct aca_handle *handle); int amdgpu_aca_get_error_data(struct amdgpu_device *adev, struct aca_handle *handle, - enum aca_error_type type, void *data); + enum aca_error_type type, struct ras_err_data *err_data, + struct ras_query_context *qctx); int amdgpu_aca_smu_set_debug_mode(struct amdgpu_device *adev, bool en); void amdgpu_aca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root); +int aca_error_cache_log_bank_error(struct aca_handle *handle, struct aca_bank_info *info, + enum aca_error_type type, u64 count); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 6d72355ac492..bf6c4a0d0525 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -637,6 +637,8 @@ static const struct amd_ip_funcs acp_ip_funcs = { .soft_reset = acp_soft_reset, .set_clockgating_state = acp_set_clockgating_state, .set_powergating_state = acp_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version acp_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 35dd6effa9a3..7ba05f030dd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -747,10 +747,17 @@ bool amdgpu_amdkfd_is_fed(struct amdgpu_device *adev) return amdgpu_ras_get_fed_status(adev); } -void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, - enum amdgpu_ras_block block, bool reset) +void amdgpu_amdkfd_ras_pasid_poison_consumption_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset) { - amdgpu_umc_poison_handler(adev, block, reset); + amdgpu_umc_pasid_poison_handler(adev, block, pasid, pasid_fn, data, reset); +} + +void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint32_t reset) +{ + amdgpu_umc_pasid_poison_handler(adev, block, 0, NULL, NULL, reset); } int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev, @@ -769,12 +776,20 @@ int amdgpu_amdkfd_send_close_event_drain_irq(struct amdgpu_device *adev, return 0; } -bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev) +bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev, + int hub_inst, int hub_type) { - if (adev->gfx.ras && adev->gfx.ras->query_utcl2_poison_status) - return adev->gfx.ras->query_utcl2_poison_status(adev); - else - return false; + if (!hub_type) { + if (adev->gfxhub.funcs->query_utcl2_poison_status) + return adev->gfxhub.funcs->query_utcl2_poison_status(adev, hub_inst); + else + return false; + } else { + if (adev->mmhub.funcs->query_utcl2_poison_status) + return adev->mmhub.funcs->query_utcl2_poison_status(adev, hub_inst); + else + return false; + } } int amdgpu_amdkfd_check_and_lock_kfd(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 0ef223c2affb..1de021ebdd46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -336,12 +336,18 @@ void amdgpu_amdkfd_debug_mem_fence(struct amdgpu_device *adev); int amdgpu_amdkfd_get_tile_config(struct amdgpu_device *adev, struct tile_config *config); void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, - enum amdgpu_ras_block block, bool reset); + enum amdgpu_ras_block block, uint32_t reset); + +void amdgpu_amdkfd_ras_pasid_poison_consumption_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset); + bool amdgpu_amdkfd_is_fed(struct amdgpu_device *adev); bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem); void amdgpu_amdkfd_block_mmu_notifications(void *p); int amdgpu_amdkfd_criu_resume(void *p); -bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev); +bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev, + int hub_inst, int hub_type); int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, uint64_t size, u32 alloc_flag, int8_t xcp_id); void amdgpu_amdkfd_unreserve_mem_limit(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index 69810b3f1c63..3ab6c3aa0ad1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -881,6 +881,7 @@ uint32_t kgd_gfx_v10_set_wave_launch_mode(struct amdgpu_device *adev, } #define TCP_WATCH_STRIDE (mmTCP_WATCH1_ADDR_H - mmTCP_WATCH0_ADDR_H) +#define SQ_WATCH_STRIDE (mmSQ_WATCH1_ADDR_H - mmSQ_WATCH0_ADDR_H) uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev, uint64_t watch_address, uint32_t watch_address_mask, @@ -889,55 +890,93 @@ uint32_t kgd_gfx_v10_set_address_watch(struct amdgpu_device *adev, uint32_t debug_vmid, uint32_t inst) { + /* SQ_WATCH?_ADDR_* and TCP_WATCH?_ADDR_* are programmed with the + * same values. + */ uint32_t watch_address_high; uint32_t watch_address_low; - uint32_t watch_address_cntl; - - watch_address_cntl = 0; + uint32_t tcp_watch_address_cntl; + uint32_t sq_watch_address_cntl; watch_address_low = lower_32_bits(watch_address); watch_address_high = upper_32_bits(watch_address) & 0xffff; - watch_address_cntl = REG_SET_FIELD(watch_address_cntl, + tcp_watch_address_cntl = 0; + tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl, TCP_WATCH0_CNTL, VMID, debug_vmid); - watch_address_cntl = REG_SET_FIELD(watch_address_cntl, + tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl, TCP_WATCH0_CNTL, MODE, watch_mode); - watch_address_cntl = REG_SET_FIELD(watch_address_cntl, + tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl, TCP_WATCH0_CNTL, MASK, watch_address_mask >> 7); + sq_watch_address_cntl = 0; + sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl, + SQ_WATCH0_CNTL, + VMID, + debug_vmid); + sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl, + SQ_WATCH0_CNTL, + MODE, + watch_mode); + sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl, + SQ_WATCH0_CNTL, + MASK, + watch_address_mask >> 6); + /* Turning off this watch point until we set all the registers */ - watch_address_cntl = REG_SET_FIELD(watch_address_cntl, + tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl, TCP_WATCH0_CNTL, VALID, 0); - WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) + (watch_id * TCP_WATCH_STRIDE)), - watch_address_cntl); + tcp_watch_address_cntl); + sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl, + SQ_WATCH0_CNTL, + VALID, + 0); + WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) + + (watch_id * SQ_WATCH_STRIDE)), + sq_watch_address_cntl); + + /* Program {TCP,SQ}_WATCH?_ADDR* */ WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_H) + (watch_id * TCP_WATCH_STRIDE)), watch_address_high); - WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_ADDR_L) + (watch_id * TCP_WATCH_STRIDE)), watch_address_low); + WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_H) + + (watch_id * SQ_WATCH_STRIDE)), + watch_address_high); + WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_ADDR_L) + + (watch_id * SQ_WATCH_STRIDE)), + watch_address_low); + /* Enable the watch point */ - watch_address_cntl = REG_SET_FIELD(watch_address_cntl, + tcp_watch_address_cntl = REG_SET_FIELD(tcp_watch_address_cntl, TCP_WATCH0_CNTL, VALID, 1); - WREG32((SOC15_REG_OFFSET(GC, 0, mmTCP_WATCH0_CNTL) + (watch_id * TCP_WATCH_STRIDE)), - watch_address_cntl); + tcp_watch_address_cntl); + + sq_watch_address_cntl = REG_SET_FIELD(sq_watch_address_cntl, + SQ_WATCH0_CNTL, + VALID, + 1); + WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) + + (watch_id * SQ_WATCH_STRIDE)), + sq_watch_address_cntl); return 0; } @@ -953,8 +992,14 @@ uint32_t kgd_gfx_v10_clear_address_watch(struct amdgpu_device *adev, (watch_id * TCP_WATCH_STRIDE)), watch_address_cntl); + WREG32((SOC15_REG_OFFSET(GC, 0, mmSQ_WATCH0_CNTL) + + (watch_id * SQ_WATCH_STRIDE)), + watch_address_cntl); + return 0; } +#undef TCP_WATCH_STRIDE +#undef SQ_WATCH_STRIDE /* kgd_gfx_v10_get_iq_wait_times: Returns the mmCP_IQ_WAIT_TIME1/2 values diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index df58a6a1a67e..e4d4e55c08ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -220,7 +220,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > kfd_mem_limit.max_ttm_mem_limit) || (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed > - vram_size - reserved_for_pt)) { + vram_size - reserved_for_pt - atomic64_read(&adev->vram_pin_size))) { ret = -ENOMEM; goto release; } @@ -1854,6 +1854,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( err_bo_create: amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id); err_reserve_limit: + amdgpu_sync_free(&(*mem)->sync); mutex_destroy(&(*mem)->lock); if (gobj) drm_gem_object_put(gobj); @@ -2900,13 +2901,12 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu * amdgpu_sync_create(&sync_obj); - /* Validate BOs and map them to GPUVM (update VM page tables). */ + /* Validate BOs managed by KFD */ list_for_each_entry(mem, &process_info->kfd_bo_list, validate_list) { struct amdgpu_bo *bo = mem->bo; uint32_t domain = mem->domain; - struct kfd_mem_attachment *attachment; struct dma_resv_iter cursor; struct dma_fence *fence; @@ -2931,6 +2931,25 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu * goto validate_map_fail; } } + } + + if (failed_size) + pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size); + + /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO + * validations above would invalidate DMABuf imports again. + */ + ret = process_validate_vms(process_info, &exec.ticket); + if (ret) { + pr_debug("Validating VMs failed, ret: %d\n", ret); + goto validate_map_fail; + } + + /* Update mappings managed by KFD. */ + list_for_each_entry(mem, &process_info->kfd_bo_list, + validate_list) { + struct kfd_mem_attachment *attachment; + list_for_each_entry(attachment, &mem->attachments, list) { if (!attachment->is_mapped) continue; @@ -2947,18 +2966,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence __rcu * } } - if (failed_size) - pr_debug("0x%lx/0x%lx in system\n", failed_size, total_size); - - /* Validate PDs, PTs and evicted DMABuf imports last. Otherwise BO - * validations above would invalidate DMABuf imports again. - */ - ret = process_validate_vms(process_info, &exec.ticket); - if (ret) { - pr_debug("Validating VMs failed, ret: %d\n", ret); - goto validate_map_fail; - } - /* Update mappings not managed by KFD */ list_for_each_entry(peer_vm, &process_info->vm_list_head, vm_list_node) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 6857c586ded7..a6d64bdbbb14 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -34,6 +34,7 @@ union firmware_info { struct atom_firmware_info_v3_2 v32; struct atom_firmware_info_v3_3 v33; struct atom_firmware_info_v3_4 v34; + struct atom_firmware_info_v3_5 v35; }; /* @@ -872,6 +873,10 @@ int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev) fw_reserved_fb_size = (firmware_info->v34.fw_reserved_size_in_kb << 10); break; + case 5: + fw_reserved_fb_size = + (firmware_info->v35.fw_reserved_size_in_kb << 10); + break; default: fw_reserved_fb_size = 0; break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c index edc6377ec5ff..199693369c7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c @@ -39,7 +39,7 @@ static int amdgpu_benchmark_do_move(struct amdgpu_device *adev, unsigned size, for (i = 0; i < n; i++) { struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; r = amdgpu_copy_buffer(ring, saddr, daddr, size, NULL, &fence, - false, false, false); + false, false, 0); if (r) goto exit_do_move; r = dma_fence_wait(fence, false); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 0a4b09709cfb..ec888fc6ead8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -819,7 +819,7 @@ static int amdgpu_cs_bo_validate(void *param, struct amdgpu_bo *bo) p->bytes_moved += ctx.bytes_moved; if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && - amdgpu_bo_in_cpu_visible_vram(bo)) + amdgpu_res_cpu_visible(adev, bo->tbo.resource)) p->bytes_moved_vis += ctx.bytes_moved; if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index f5d0fa207a88..b62ae3c91a9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -2065,12 +2065,13 @@ static ssize_t amdgpu_reset_dump_register_list_write(struct file *f, struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; char reg_offset[11]; uint32_t *new = NULL, *tmp = NULL; - int ret, i = 0, len = 0; + unsigned int len = 0; + int ret, i = 0; do { memset(reg_offset, 0, 11); if (copy_from_user(reg_offset, buf + len, - min(10, ((int)size-len)))) { + min(10, (size-len)))) { ret = -EFAULT; goto error_free; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c new file mode 100644 index 000000000000..c1cb62683695 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c @@ -0,0 +1,360 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright 2024 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include "amdgpu_dev_coredump.h" +#include "atom.h" + +#ifndef CONFIG_DEV_COREDUMP +void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, + struct amdgpu_reset_context *reset_context) +{ +} +#else + +const char *hw_ip_names[MAX_HWIP] = { + [GC_HWIP] = "GC", + [HDP_HWIP] = "HDP", + [SDMA0_HWIP] = "SDMA0", + [SDMA1_HWIP] = "SDMA1", + [SDMA2_HWIP] = "SDMA2", + [SDMA3_HWIP] = "SDMA3", + [SDMA4_HWIP] = "SDMA4", + [SDMA5_HWIP] = "SDMA5", + [SDMA6_HWIP] = "SDMA6", + [SDMA7_HWIP] = "SDMA7", + [LSDMA_HWIP] = "LSDMA", + [MMHUB_HWIP] = "MMHUB", + [ATHUB_HWIP] = "ATHUB", + [NBIO_HWIP] = "NBIO", + [MP0_HWIP] = "MP0", + [MP1_HWIP] = "MP1", + [UVD_HWIP] = "UVD/JPEG/VCN", + [VCN1_HWIP] = "VCN1", + [VCE_HWIP] = "VCE", + [VPE_HWIP] = "VPE", + [DF_HWIP] = "DF", + [DCE_HWIP] = "DCE", + [OSSSYS_HWIP] = "OSSSYS", + [SMUIO_HWIP] = "SMUIO", + [PWR_HWIP] = "PWR", + [NBIF_HWIP] = "NBIF", + [THM_HWIP] = "THM", + [CLK_HWIP] = "CLK", + [UMC_HWIP] = "UMC", + [RSMU_HWIP] = "RSMU", + [XGMI_HWIP] = "XGMI", + [DCI_HWIP] = "DCI", + [PCIE_HWIP] = "PCIE", +}; + +static void amdgpu_devcoredump_fw_info(struct amdgpu_device *adev, + struct drm_printer *p) +{ + uint32_t version; + uint32_t feature; + uint8_t smu_program, smu_major, smu_minor, smu_debug; + struct atom_context *ctx = adev->mode_info.atom_context; + + drm_printf(p, "VCE feature version: %u, fw version: 0x%08x\n", + adev->vce.fb_version, adev->vce.fw_version); + drm_printf(p, "UVD feature version: %u, fw version: 0x%08x\n", 0, + adev->uvd.fw_version); + drm_printf(p, "GMC feature version: %u, fw version: 0x%08x\n", 0, + adev->gmc.fw_version); + drm_printf(p, "ME feature version: %u, fw version: 0x%08x\n", + adev->gfx.me_feature_version, adev->gfx.me_fw_version); + drm_printf(p, "PFP feature version: %u, fw version: 0x%08x\n", + adev->gfx.pfp_feature_version, adev->gfx.pfp_fw_version); + drm_printf(p, "CE feature version: %u, fw version: 0x%08x\n", + adev->gfx.ce_feature_version, adev->gfx.ce_fw_version); + drm_printf(p, "RLC feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlc_feature_version, adev->gfx.rlc_fw_version); + + drm_printf(p, "RLC SRLC feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlc_srlc_feature_version, + adev->gfx.rlc_srlc_fw_version); + drm_printf(p, "RLC SRLG feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlc_srlg_feature_version, + adev->gfx.rlc_srlg_fw_version); + drm_printf(p, "RLC SRLS feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlc_srls_feature_version, + adev->gfx.rlc_srls_fw_version); + drm_printf(p, "RLCP feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlcp_ucode_feature_version, + adev->gfx.rlcp_ucode_version); + drm_printf(p, "RLCV feature version: %u, fw version: 0x%08x\n", + adev->gfx.rlcv_ucode_feature_version, + adev->gfx.rlcv_ucode_version); + drm_printf(p, "MEC feature version: %u, fw version: 0x%08x\n", + adev->gfx.mec_feature_version, adev->gfx.mec_fw_version); + + if (adev->gfx.mec2_fw) + drm_printf(p, "MEC2 feature version: %u, fw version: 0x%08x\n", + adev->gfx.mec2_feature_version, + adev->gfx.mec2_fw_version); + + drm_printf(p, "IMU feature version: %u, fw version: 0x%08x\n", 0, + adev->gfx.imu_fw_version); + drm_printf(p, "PSP SOS feature version: %u, fw version: 0x%08x\n", + adev->psp.sos.feature_version, adev->psp.sos.fw_version); + drm_printf(p, "PSP ASD feature version: %u, fw version: 0x%08x\n", + adev->psp.asd_context.bin_desc.feature_version, + adev->psp.asd_context.bin_desc.fw_version); + + drm_printf(p, "TA XGMI feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.xgmi_context.context.bin_desc.feature_version, + adev->psp.xgmi_context.context.bin_desc.fw_version); + drm_printf(p, "TA RAS feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.ras_context.context.bin_desc.feature_version, + adev->psp.ras_context.context.bin_desc.fw_version); + drm_printf(p, "TA HDCP feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.hdcp_context.context.bin_desc.feature_version, + adev->psp.hdcp_context.context.bin_desc.fw_version); + drm_printf(p, "TA DTM feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.dtm_context.context.bin_desc.feature_version, + adev->psp.dtm_context.context.bin_desc.fw_version); + drm_printf(p, "TA RAP feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.rap_context.context.bin_desc.feature_version, + adev->psp.rap_context.context.bin_desc.fw_version); + drm_printf(p, + "TA SECURE DISPLAY feature version: 0x%08x, fw version: 0x%08x\n", + adev->psp.securedisplay_context.context.bin_desc.feature_version, + adev->psp.securedisplay_context.context.bin_desc.fw_version); + + /* SMC firmware */ + version = adev->pm.fw_version; + + smu_program = (version >> 24) & 0xff; + smu_major = (version >> 16) & 0xff; + smu_minor = (version >> 8) & 0xff; + smu_debug = (version >> 0) & 0xff; + drm_printf(p, + "SMC feature version: %u, program: %d, fw version: 0x%08x (%d.%d.%d)\n", + 0, smu_program, version, smu_major, smu_minor, smu_debug); + + /* SDMA firmware */ + for (int i = 0; i < adev->sdma.num_instances; i++) { + drm_printf(p, + "SDMA%d feature version: %u, firmware version: 0x%08x\n", + i, adev->sdma.instance[i].feature_version, + adev->sdma.instance[i].fw_version); + } + + drm_printf(p, "VCN feature version: %u, fw version: 0x%08x\n", 0, + adev->vcn.fw_version); + drm_printf(p, "DMCU feature version: %u, fw version: 0x%08x\n", 0, + adev->dm.dmcu_fw_version); + drm_printf(p, "DMCUB feature version: %u, fw version: 0x%08x\n", 0, + adev->dm.dmcub_fw_version); + drm_printf(p, "PSP TOC feature version: %u, fw version: 0x%08x\n", + adev->psp.toc.feature_version, adev->psp.toc.fw_version); + + version = adev->mes.kiq_version & AMDGPU_MES_VERSION_MASK; + feature = (adev->mes.kiq_version & AMDGPU_MES_FEAT_VERSION_MASK) >> + AMDGPU_MES_FEAT_VERSION_SHIFT; + drm_printf(p, "MES_KIQ feature version: %u, fw version: 0x%08x\n", + feature, version); + + version = adev->mes.sched_version & AMDGPU_MES_VERSION_MASK; + feature = (adev->mes.sched_version & AMDGPU_MES_FEAT_VERSION_MASK) >> + AMDGPU_MES_FEAT_VERSION_SHIFT; + drm_printf(p, "MES feature version: %u, fw version: 0x%08x\n", feature, + version); + + drm_printf(p, "VPE feature version: %u, fw version: 0x%08x\n", + adev->vpe.feature_version, adev->vpe.fw_version); + + drm_printf(p, "\nVBIOS Information\n"); + drm_printf(p, "vbios name : %s\n", ctx->name); + drm_printf(p, "vbios pn : %s\n", ctx->vbios_pn); + drm_printf(p, "vbios version : %d\n", ctx->version); + drm_printf(p, "vbios ver_str : %s\n", ctx->vbios_ver_str); + drm_printf(p, "vbios date : %s\n", ctx->date); +} + +static ssize_t +amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count, + void *data, size_t datalen) +{ + struct drm_printer p; + struct amdgpu_coredump_info *coredump = data; + struct drm_print_iterator iter; + struct amdgpu_vm_fault_info *fault_info; + int i, ver; + + iter.data = buffer; + iter.offset = 0; + iter.start = offset; + iter.remain = count; + + p = drm_coredump_printer(&iter); + + drm_printf(&p, "**** AMDGPU Device Coredump ****\n"); + drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n"); + drm_printf(&p, "kernel: " UTS_RELEASE "\n"); + drm_printf(&p, "module: " KBUILD_MODNAME "\n"); + drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec, + coredump->reset_time.tv_nsec); + + if (coredump->reset_task_info.pid) + drm_printf(&p, "process_name: %s PID: %d\n", + coredump->reset_task_info.process_name, + coredump->reset_task_info.pid); + + /* GPU IP's information of the SOC */ + drm_printf(&p, "\nIP Information\n"); + drm_printf(&p, "SOC Family: %d\n", coredump->adev->family); + drm_printf(&p, "SOC Revision id: %d\n", coredump->adev->rev_id); + drm_printf(&p, "SOC External Revision id: %d\n", coredump->adev->external_rev_id); + + for (int i = 1; i < MAX_HWIP; i++) { + for (int j = 0; j < HWIP_MAX_INSTANCE; j++) { + ver = coredump->adev->ip_versions[i][j]; + if (ver) + drm_printf(&p, "HWIP: %s[%d][%d]: v%d.%d.%d.%d.%d\n", + hw_ip_names[i], i, j, + IP_VERSION_MAJ(ver), + IP_VERSION_MIN(ver), + IP_VERSION_REV(ver), + IP_VERSION_VARIANT(ver), + IP_VERSION_SUBREV(ver)); + } + } + + /* IP firmware information */ + drm_printf(&p, "\nIP Firmwares\n"); + amdgpu_devcoredump_fw_info(coredump->adev, &p); + + if (coredump->ring) { + drm_printf(&p, "\nRing timed out details\n"); + drm_printf(&p, "IP Type: %d Ring Name: %s\n", + coredump->ring->funcs->type, + coredump->ring->name); + } + + /* Add page fault information */ + fault_info = &coredump->adev->vm_manager.fault_info; + drm_printf(&p, "\n[%s] Page fault observed\n", + fault_info->vmhub ? "mmhub" : "gfxhub"); + drm_printf(&p, "Faulty page starting at address: 0x%016llx\n", fault_info->addr); + drm_printf(&p, "Protection fault status register: 0x%x\n\n", fault_info->status); + + /* dump the ip state for each ip */ + drm_printf(&p, "IP Dump\n"); + for (int i = 0; i < coredump->adev->num_ip_blocks; i++) { + if (coredump->adev->ip_blocks[i].version->funcs->print_ip_state) { + drm_printf(&p, "IP: %s\n", + coredump->adev->ip_blocks[i] + .version->funcs->name); + coredump->adev->ip_blocks[i] + .version->funcs->print_ip_state( + (void *)coredump->adev, &p); + drm_printf(&p, "\n"); + } + } + + /* Add ring buffer information */ + drm_printf(&p, "Ring buffer information\n"); + for (int i = 0; i < coredump->adev->num_rings; i++) { + int j = 0; + struct amdgpu_ring *ring = coredump->adev->rings[i]; + + drm_printf(&p, "ring name: %s\n", ring->name); + drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n", + amdgpu_ring_get_rptr(ring), + amdgpu_ring_get_wptr(ring), + ring->buf_mask); + drm_printf(&p, "Ring size in dwords: %d\n", + ring->ring_size / 4); + drm_printf(&p, "Ring contents\n"); + drm_printf(&p, "Offset \t Value\n"); + + while (j < ring->ring_size) { + drm_printf(&p, "0x%x \t 0x%x\n", j, ring->ring[j / 4]); + j += 4; + } + } + + if (coredump->reset_vram_lost) + drm_printf(&p, "VRAM is lost due to GPU reset!\n"); + if (coredump->adev->reset_info.num_regs) { + drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n"); + + for (i = 0; i < coredump->adev->reset_info.num_regs; i++) + drm_printf(&p, "0x%08x: 0x%08x\n", + coredump->adev->reset_info.reset_dump_reg_list[i], + coredump->adev->reset_info.reset_dump_reg_value[i]); + } + + return count - iter.remain; +} + +static void amdgpu_devcoredump_free(void *data) +{ + kfree(data); +} + +void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, + struct amdgpu_reset_context *reset_context) +{ + struct amdgpu_coredump_info *coredump; + struct drm_device *dev = adev_to_drm(adev); + struct amdgpu_job *job = reset_context->job; + struct drm_sched_job *s_job; + + coredump = kzalloc(sizeof(*coredump), GFP_NOWAIT); + + if (!coredump) { + DRM_ERROR("%s: failed to allocate memory for coredump\n", __func__); + return; + } + + coredump->reset_vram_lost = vram_lost; + + if (reset_context->job && reset_context->job->vm) { + struct amdgpu_task_info *ti; + struct amdgpu_vm *vm = reset_context->job->vm; + + ti = amdgpu_vm_get_task_info_vm(vm); + if (ti) { + coredump->reset_task_info = *ti; + amdgpu_vm_put_task_info(ti); + } + } + + if (job) { + s_job = &job->base; + coredump->ring = to_amdgpu_ring(s_job->sched); + } + + coredump->adev = adev; + + ktime_get_ts64(&coredump->reset_time); + + dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT, + amdgpu_devcoredump_read, amdgpu_devcoredump_free); +} +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h new file mode 100644 index 000000000000..52459512cb2b --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2024 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_DEV_COREDUMP_H__ +#define __AMDGPU_DEV_COREDUMP_H__ + +#include "amdgpu.h" +#include "amdgpu_reset.h" + +#ifdef CONFIG_DEV_COREDUMP + +#define AMDGPU_COREDUMP_VERSION "1" + +struct amdgpu_coredump_info { + struct amdgpu_device *adev; + struct amdgpu_task_info reset_task_info; + struct timespec64 reset_time; + bool reset_vram_lost; + struct amdgpu_ring *ring; +}; +#endif + +void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, + struct amdgpu_reset_context *reset_context); + +#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index aa16d51dd842..861ccff78af9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -74,6 +74,7 @@ #include "amdgpu_fru_eeprom.h" #include "amdgpu_reset.h" #include "amdgpu_virt.h" +#include "amdgpu_dev_coredump.h" #include #include @@ -143,6 +144,8 @@ const char *amdgpu_asic_name[] = { "LAST", }; +static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev); + /** * DOC: pcie_replay_count * @@ -335,16 +338,93 @@ bool amdgpu_device_supports_boco(struct drm_device *dev) * * @dev: drm_device pointer * - * Returns true if the device supporte BACO, - * otherwise return false. + * Return: + * 1 if the device supporte BACO; + * 3 if the device support MACO (only works if BACO is supported) + * otherwise return 0. */ -bool amdgpu_device_supports_baco(struct drm_device *dev) +int amdgpu_device_supports_baco(struct drm_device *dev) { struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_asic_supports_baco(adev); } +void amdgpu_device_detect_runtime_pm_mode(struct amdgpu_device *adev) +{ + struct drm_device *dev; + int bamaco_support; + + dev = adev_to_drm(adev); + + adev->pm.rpm_mode = AMDGPU_RUNPM_NONE; + bamaco_support = amdgpu_device_supports_baco(dev); + + switch (amdgpu_runtime_pm) { + case 2: + if (bamaco_support & MACO_SUPPORT) { + adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO; + dev_info(adev->dev, "Forcing BAMACO for runtime pm\n"); + } else if (bamaco_support == BACO_SUPPORT) { + adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; + dev_info(adev->dev, "Requested mode BAMACO not available,fallback to use BACO\n"); + } + break; + case 1: + if (bamaco_support & BACO_SUPPORT) { + adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; + dev_info(adev->dev, "Forcing BACO for runtime pm\n"); + } + break; + case -1: + case -2: + if (amdgpu_device_supports_px(dev)) { /* enable PX as runtime mode */ + adev->pm.rpm_mode = AMDGPU_RUNPM_PX; + dev_info(adev->dev, "Using ATPX for runtime pm\n"); + } else if (amdgpu_device_supports_boco(dev)) { /* enable boco as runtime mode */ + adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO; + dev_info(adev->dev, "Using BOCO for runtime pm\n"); + } else { + if (!bamaco_support) + goto no_runtime_pm; + + switch (adev->asic_type) { + case CHIP_VEGA20: + case CHIP_ARCTURUS: + /* BACO are not supported on vega20 and arctrus */ + break; + case CHIP_VEGA10: + /* enable BACO as runpm mode if noretry=0 */ + if (!adev->gmc.noretry) + adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; + break; + default: + /* enable BACO as runpm mode on CI+ */ + adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; + break; + } + + if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) { + if (bamaco_support & MACO_SUPPORT) { + adev->pm.rpm_mode = AMDGPU_RUNPM_BAMACO; + dev_info(adev->dev, "Using BAMACO for runtime pm\n"); + } else { + dev_info(adev->dev, "Using BACO for runtime pm\n"); + } + } + } + break; + case 0: + dev_info(adev->dev, "runtime pm is manually disabled\n"); + break; + default: + break; + } + +no_runtime_pm: + if (adev->pm.rpm_mode == AMDGPU_RUNPM_NONE) + dev_info(adev->dev, "Runtime PM not available\n"); +} /** * amdgpu_device_supports_smart_shift - Is the device dGPU with * smart shift support @@ -1402,13 +1482,17 @@ static int amdgpu_device_wb_init(struct amdgpu_device *adev) */ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb) { - unsigned long offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb); + unsigned long flags, offset; + spin_lock_irqsave(&adev->wb.lock, flags); + offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb); if (offset < adev->wb.num_wb) { __set_bit(offset, adev->wb.used); + spin_unlock_irqrestore(&adev->wb.lock, flags); *wb = offset << 3; /* convert to dw offset */ return 0; } else { + spin_unlock_irqrestore(&adev->wb.lock, flags); return -EINVAL; } } @@ -1423,9 +1507,13 @@ int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb) */ void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb) { + unsigned long flags; + wb >>= 3; + spin_lock_irqsave(&adev->wb.lock, flags); if (wb < adev->wb.num_wb) __clear_bit(wb, adev->wb.used); + spin_unlock_irqrestore(&adev->wb.lock, flags); } /** @@ -1455,7 +1543,7 @@ int amdgpu_device_resize_fb_bar(struct amdgpu_device *adev) /* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */ if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR)) - DRM_WARN("System can't access extended configuration space,please check!!\n"); + DRM_WARN("System can't access extended configuration space, please check!!\n"); /* skip if the bios has already enabled large BAR */ if (adev->gmc.real_vram_size && @@ -3981,6 +4069,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, spin_lock_init(&adev->se_cac_idx_lock); spin_lock_init(&adev->audio_endpt_idx_lock); spin_lock_init(&adev->mm_stats.lock); + spin_lock_init(&adev->wb.lock); INIT_LIST_HEAD(&adev->shadow_list); mutex_init(&adev->shadow_list_lock); @@ -4069,6 +4158,13 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* Enable TMZ based on IP_VERSION */ amdgpu_gmc_tmz_set(adev); + if (amdgpu_sriov_vf(adev) && + amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(10, 3, 0)) + /* VF MMIO access (except mailbox range) from CPU + * will be blocked during sriov runtime + */ + adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT; + amdgpu_gmc_noretry_set(adev); /* Need to get xgmi info early to decide the reset behavior*/ if (adev->gmc.xgmi.supported) { @@ -4135,18 +4231,22 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->ip_blocks[i].status.hw = true; } } + } else if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) && + !amdgpu_device_has_display_hardware(adev)) { + r = psp_gpu_reset(adev); } else { - tmp = amdgpu_reset_method; - /* It should do a default reset when loading or reloading the driver, - * regardless of the module parameter reset_method. - */ - amdgpu_reset_method = AMD_RESET_METHOD_NONE; - r = amdgpu_asic_reset(adev); - amdgpu_reset_method = tmp; - if (r) { - dev_err(adev->dev, "asic reset on init failed\n"); - goto failed; - } + tmp = amdgpu_reset_method; + /* It should do a default reset when loading or reloading the driver, + * regardless of the module parameter reset_method. + */ + amdgpu_reset_method = AMD_RESET_METHOD_NONE; + r = amdgpu_asic_reset(adev); + amdgpu_reset_method = tmp; + } + + if (r) { + dev_err(adev->dev, "asic reset on init failed\n"); + goto failed; } } @@ -4970,12 +5070,15 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev, retry: amdgpu_amdkfd_pre_reset(adev); + amdgpu_device_stop_pending_resets(adev); + if (from_hypervisor) r = amdgpu_virt_request_full_gpu(adev, true); else r = amdgpu_virt_reset_gpu(adev); if (r) return r; + amdgpu_ras_set_fed(adev, false); amdgpu_irq_gpu_reset_resume_helper(adev); /* some sw clean up VF needs to do before recover */ @@ -5259,11 +5362,21 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, struct amdgpu_device *tmp_adev = NULL; bool need_full_reset, skip_hw_reset, vram_lost = false; int r = 0; + uint32_t i; /* Try reset handler method first */ tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device, reset_list); - amdgpu_reset_reg_dumps(tmp_adev); + + if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) { + amdgpu_reset_reg_dumps(tmp_adev); + + /* Trigger ip dump before we reset the asic */ + for (i = 0; i < tmp_adev->num_ip_blocks; i++) + if (tmp_adev->ip_blocks[i].version->funcs->dump_ip_state) + tmp_adev->ip_blocks[i].version->funcs + ->dump_ip_state((void *)tmp_adev); + } reset_context->reset_device_list = device_list_handle; r = amdgpu_reset_perform_reset(tmp_adev, reset_context); @@ -5336,7 +5449,8 @@ int amdgpu_do_asic_reset(struct list_head *device_list_handle, vram_lost = amdgpu_device_check_vram_lost(tmp_adev); - amdgpu_coredump(tmp_adev, vram_lost, reset_context); + if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) + amdgpu_coredump(tmp_adev, vram_lost, reset_context); if (vram_lost) { DRM_INFO("VRAM is lost due to GPU reset!\n"); @@ -5534,6 +5648,23 @@ static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev) } +static int amdgpu_device_health_check(struct list_head *device_list_handle) +{ + struct amdgpu_device *tmp_adev; + int ret = 0; + u32 status; + + list_for_each_entry(tmp_adev, device_list_handle, reset_list) { + pci_read_config_dword(tmp_adev->pdev, PCI_COMMAND, &status); + if (PCI_POSSIBLE_ERROR(status)) { + dev_err(tmp_adev->dev, "device lost from bus!"); + ret = -ENODEV; + } + } + + return ret; +} + /** * amdgpu_device_gpu_recover - reset the asic and recover scheduler * @@ -5605,6 +5736,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, device_list_handle = &device_list; } + if (!amdgpu_sriov_vf(adev)) { + r = amdgpu_device_health_check(device_list_handle); + if (r) + goto end_reset; + } + /* We need to lock reset domain only once both for XGMI and single device */ tmp_adev = list_first_entry(device_list_handle, struct amdgpu_device, reset_list); @@ -5687,11 +5824,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, tmp_adev->asic_reset_res = r; } - /* - * Drop all pending non scheduler resets. Scheduler resets - * were already dropped during drm_sched_stop - */ - amdgpu_device_stop_pending_resets(tmp_adev); + if (!amdgpu_sriov_vf(tmp_adev)) + /* + * Drop all pending non scheduler resets. Scheduler resets + * were already dropped during drm_sched_stop + */ + amdgpu_device_stop_pending_resets(tmp_adev); } /* Actual ASIC resets if needed.*/ @@ -5770,6 +5908,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, reset_list); amdgpu_device_unlock_reset_domain(tmp_adev->reset_domain); +end_reset: if (hive) { mutex_unlock(&hive->hive_lock); amdgpu_put_xgmi_hive(hive); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index fdd36fb027ab..0e31bdb4b7cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -97,6 +97,7 @@ #include "smuio_v13_0.h" #include "smuio_v13_0_3.h" #include "smuio_v13_0_6.h" +#include "smuio_v14_0_2.h" #include "vcn_v5_0_0.h" #include "jpeg_v5_0_0.h" @@ -245,6 +246,9 @@ static int amdgpu_discovery_read_binary_from_sysmem(struct amdgpu_device *adev, return -ENOENT; } +#define IP_DISCOVERY_V2 2 +#define IP_DISCOVERY_V4 4 + static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, uint8_t *binary) { @@ -259,14 +263,14 @@ static int amdgpu_discovery_read_binary_from_mem(struct amdgpu_device *adev, * wait for this to complete. Once the C2PMSG is updated, we can * continue. */ - if (dev_is_removable(&adev->pdev->dev)) { - for (i = 0; i < 1000; i++) { - msg = RREG32(mmMP0_SMN_C2PMSG_33); - if (msg & 0x80000000) - break; - msleep(1); - } + + for (i = 0; i < 1000; i++) { + msg = RREG32(mmMP0_SMN_C2PMSG_33); + if (msg & 0x80000000) + break; + usleep_range(1000, 1100); } + vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20; if (vram_size) { @@ -1896,6 +1900,9 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); break; case IP_VERSION(14, 0, 0): + case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 2): + case IP_VERSION(14, 0, 3): amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block); break; default: @@ -2677,6 +2684,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) case IP_VERSION(14, 0, 1): adev->smuio.funcs = &smuio_v13_0_6_funcs; break; + case IP_VERSION(14, 0, 2): + adev->smuio.funcs = &smuio_v14_0_2_funcs; + break; default: break; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 80b9642f2bc4..ea14f1c8f430 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -195,6 +195,7 @@ int amdgpu_async_gfx_ring = 1; int amdgpu_mcbp = -1; int amdgpu_discovery = -1; int amdgpu_mes; +int amdgpu_mes_log_enable = 0; int amdgpu_mes_kiq; int amdgpu_noretry = -1; int amdgpu_force_asic_type = -1; @@ -667,6 +668,15 @@ MODULE_PARM_DESC(mes, "Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)"); module_param_named(mes, amdgpu_mes, int, 0444); +/** + * DOC: mes_log_enable (int) + * Enable Micro Engine Scheduler log. This is used to enable/disable MES internal log. + * (0 = disabled (default), 1 = enabled) + */ +MODULE_PARM_DESC(mes_log_enable, + "Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)"); +module_param_named(mes_log_enable, amdgpu_mes_log_enable, int, 0444); + /** * DOC: mes_kiq (int) * Enable Micro Engine Scheduler KIQ. This is a new engine pipe for kiq. @@ -915,7 +925,7 @@ module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444); * GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco) */ MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco/bamaco)"); -module_param_named(reset_method, amdgpu_reset_method, int, 0444); +module_param_named(reset_method, amdgpu_reset_method, int, 0644); /** * DOC: bad_page_threshold (int) Bad page threshold is specifies the @@ -2471,6 +2481,7 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work) /* Use a common context, just need to make sure full reset is done */ set_bit(AMDGPU_SKIP_HW_RESET, &reset_context.flags); + set_bit(AMDGPU_SKIP_COREDUMP, &reset_context.flags); r = amdgpu_do_asic_reset(&device_list, &reset_context); if (r) { @@ -2734,7 +2745,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF; } else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BOCO) { /* nothing to do */ - } else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) { + } else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) || + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) { amdgpu_device_baco_enter(drm_dev); } @@ -2774,7 +2786,8 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) * PCI core handles it for _PR3. */ pci_set_master(pdev); - } else if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) { + } else if ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) || + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO)) { amdgpu_device_baco_exit(drm_dev); } ret = amdgpu_device_resume(drm_dev, false); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 55d5508987ff..1d955652f3ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -1206,7 +1206,8 @@ void amdgpu_gfx_cp_init_microcode(struct amdgpu_device *adev, fw_size = le32_to_cpu(cp_hdr_v2_0->data_size_bytes); break; default: - break; + dev_err(adev->dev, "Invalid ucode id %u\n", ucode_id); + return; } if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 8fcf889ddce9..64f197bbc866 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -259,7 +259,6 @@ struct amdgpu_cu_info { struct amdgpu_gfx_ras { struct amdgpu_ras_block_object ras_block; void (*enable_watchdog_timer)(struct amdgpu_device *adev); - bool (*query_utcl2_poison_status)(struct amdgpu_device *adev); int (*rlc_gc_fed_irq)(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); @@ -434,6 +433,10 @@ struct amdgpu_gfx { uint32_t num_xcc_per_xcp; struct mutex partition_mutex; bool mcbp; /* mid command buffer preemption */ + + /* IP reg dump */ + uint32_t *ip_dump; + uint32_t reg_count; }; struct amdgpu_gfx_ras_reg_entry { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h index c7b44aeb671b..103a837ccc71 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfxhub.h @@ -38,6 +38,8 @@ struct amdgpu_gfxhub_funcs { void (*mode2_save_regs)(struct amdgpu_device *adev); void (*mode2_restore_regs)(struct amdgpu_device *adev); void (*halt)(struct amdgpu_device *adev); + bool (*query_utcl2_poison_status)(struct amdgpu_device *adev, + int xcc_id); }; struct amdgpu_gfxhub { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index d79cb13e1aa8..00d6211e0fbf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c @@ -279,7 +279,7 @@ amdgpu_i2c_lookup(struct amdgpu_device *adev, return NULL; } -static void amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus, +static int amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus, u8 slave_addr, u8 addr, u8 *val) @@ -304,16 +304,18 @@ static void amdgpu_i2c_get_byte(struct amdgpu_i2c_chan *i2c_bus, out_buf[0] = addr; out_buf[1] = 0; - if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) { - *val = in_buf[0]; - DRM_DEBUG("val = 0x%02x\n", *val); - } else { - DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n", - addr, *val); + if (i2c_transfer(&i2c_bus->adapter, msgs, 2) != 2) { + DRM_DEBUG("i2c 0x%02x read failed\n", addr); + return -EIO; } + + *val = in_buf[0]; + DRM_DEBUG("val = 0x%02x\n", *val); + + return 0; } -static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus, +static int amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus, u8 slave_addr, u8 addr, u8 val) @@ -329,9 +331,12 @@ static void amdgpu_i2c_put_byte(struct amdgpu_i2c_chan *i2c_bus, out_buf[0] = addr; out_buf[1] = val; - if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) - DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", - addr, val); + if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1) { + DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n", addr, val); + return -EIO; + } + + return 0; } /* ddc router switching */ @@ -346,16 +351,18 @@ amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connecto if (!amdgpu_connector->router_bus) return; - amdgpu_i2c_get_byte(amdgpu_connector->router_bus, + if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, - 0x3, &val); + 0x3, &val)) + return; val &= ~amdgpu_connector->router.ddc_mux_control_pin; amdgpu_i2c_put_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, 0x3, val); - amdgpu_i2c_get_byte(amdgpu_connector->router_bus, + if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, - 0x1, &val); + 0x1, &val)) + return; val &= ~amdgpu_connector->router.ddc_mux_control_pin; val |= amdgpu_connector->router.ddc_mux_state; amdgpu_i2c_put_byte(amdgpu_connector->router_bus, @@ -375,16 +382,18 @@ amdgpu_i2c_router_select_cd_port(const struct amdgpu_connector *amdgpu_connector if (!amdgpu_connector->router_bus) return; - amdgpu_i2c_get_byte(amdgpu_connector->router_bus, + if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, - 0x3, &val); + 0x3, &val)) + return; val &= ~amdgpu_connector->router.cd_mux_control_pin; amdgpu_i2c_put_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, 0x3, val); - amdgpu_i2c_get_byte(amdgpu_connector->router_bus, + if (amdgpu_i2c_get_byte(amdgpu_connector->router_bus, amdgpu_connector->router.i2c_addr, - 0x1, &val); + 0x1, &val)) + return; val &= ~amdgpu_connector->router.cd_mux_control_pin; val |= amdgpu_connector->router.cd_mux_state; amdgpu_i2c_put_byte(amdgpu_connector->router_bus, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 7e6d09730e6d..665c63f55278 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -445,6 +445,14 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev, entry.ih = ih; entry.iv_entry = (const uint32_t *)&ih->ring[ring_index]; + + /* + * timestamp is not supported on some legacy SOCs (cik, cz, iceland, + * si and tonga), so initialize timestamp and timestamp_src to 0 + */ + entry.timestamp = 0; + entry.timestamp_src = 0; + amdgpu_ih_decode_iv(adev, &entry); trace_amdgpu_iv(ih - &adev->irq.ih, &entry); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 4b3000c21ef2..e4742b65032d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -304,12 +304,15 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) dma_fence_set_error(finished, -ECANCELED); if (finished->error < 0) { - DRM_INFO("Skip scheduling IBs!\n"); + dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)", + ring->name); } else { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, &fence); if (r) - DRM_ERROR("Error scheduling IBs (%d)\n", r); + dev_err(adev->dev, + "Error scheduling IBs (%d) in ring(%s)", r, + ring->name); } job->job_run_counter++; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index a2df3025a754..a0ea6fe8d060 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -149,38 +149,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) goto out; } - adev->pm.rpm_mode = AMDGPU_RUNPM_NONE; - if (amdgpu_device_supports_px(dev) && - (amdgpu_runtime_pm != 0)) { /* enable PX as runtime mode */ - adev->pm.rpm_mode = AMDGPU_RUNPM_PX; - dev_info(adev->dev, "Using ATPX for runtime pm\n"); - } else if (amdgpu_device_supports_boco(dev) && - (amdgpu_runtime_pm != 0)) { /* enable boco as runtime mode */ - adev->pm.rpm_mode = AMDGPU_RUNPM_BOCO; - dev_info(adev->dev, "Using BOCO for runtime pm\n"); - } else if (amdgpu_device_supports_baco(dev) && - (amdgpu_runtime_pm != 0)) { - switch (adev->asic_type) { - case CHIP_VEGA20: - case CHIP_ARCTURUS: - /* enable BACO as runpm mode if runpm=1 */ - if (amdgpu_runtime_pm > 0) - adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; - break; - case CHIP_VEGA10: - /* enable BACO as runpm mode if noretry=0 */ - if (!adev->gmc.noretry) - adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; - break; - default: - /* enable BACO as runpm mode on CI+ */ - adev->pm.rpm_mode = AMDGPU_RUNPM_BACO; - break; - } - - if (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) - dev_info(adev->dev, "Using BACO for runtime pm\n"); - } + amdgpu_device_detect_runtime_pm_mode(adev); /* Call ACPI methods: require modeset init * but failure is not fatal diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c index 24ad4b97177b..0734490347db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c @@ -210,22 +210,26 @@ int amdgpu_mca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable) return -EOPNOTSUPP; } -static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry) +static void amdgpu_mca_smu_mca_bank_dump(struct amdgpu_device *adev, int idx, struct mca_bank_entry *entry, + struct ras_query_context *qctx) { - dev_info(adev->dev, HW_ERR "Accelerator Check Architecture events logged\n"); - dev_info(adev->dev, HW_ERR "aca entry[%02d].STATUS=0x%016llx\n", - idx, entry->regs[MCA_REG_IDX_STATUS]); - dev_info(adev->dev, HW_ERR "aca entry[%02d].ADDR=0x%016llx\n", - idx, entry->regs[MCA_REG_IDX_ADDR]); - dev_info(adev->dev, HW_ERR "aca entry[%02d].MISC0=0x%016llx\n", - idx, entry->regs[MCA_REG_IDX_MISC0]); - dev_info(adev->dev, HW_ERR "aca entry[%02d].IPID=0x%016llx\n", - idx, entry->regs[MCA_REG_IDX_IPID]); - dev_info(adev->dev, HW_ERR "aca entry[%02d].SYND=0x%016llx\n", - idx, entry->regs[MCA_REG_IDX_SYND]); + u64 event_id = qctx->event_id; + + RAS_EVENT_LOG(adev, event_id, HW_ERR "Accelerator Check Architecture events logged\n"); + RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].STATUS=0x%016llx\n", + idx, entry->regs[MCA_REG_IDX_STATUS]); + RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].ADDR=0x%016llx\n", + idx, entry->regs[MCA_REG_IDX_ADDR]); + RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].MISC0=0x%016llx\n", + idx, entry->regs[MCA_REG_IDX_MISC0]); + RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].IPID=0x%016llx\n", + idx, entry->regs[MCA_REG_IDX_IPID]); + RAS_EVENT_LOG(adev, event_id, HW_ERR "aca entry[%02d].SYND=0x%016llx\n", + idx, entry->regs[MCA_REG_IDX_SYND]); } -int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data) +int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, + struct ras_err_data *err_data, struct ras_query_context *qctx) { struct amdgpu_smuio_mcm_config_info mcm_info; struct ras_err_addr err_addr = {0}; @@ -244,7 +248,7 @@ int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_blo list_for_each_entry(node, &mca_set.list, node) { entry = &node->entry; - amdgpu_mca_smu_mca_bank_dump(adev, i++, entry); + amdgpu_mca_smu_mca_bank_dump(adev, i++, entry, qctx); count = 0; ret = amdgpu_mca_smu_parse_mca_error_count(adev, blk, type, entry, &count); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h index b964110ed1e0..e5bf07ce3451 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mca.h @@ -169,6 +169,7 @@ void amdgpu_mca_smu_debugfs_init(struct amdgpu_device *adev, struct dentry *root void amdgpu_mca_bank_set_init(struct mca_bank_set *mca_set); int amdgpu_mca_bank_set_add_entry(struct mca_bank_set *mca_set, struct mca_bank_entry *entry); void amdgpu_mca_bank_set_release(struct mca_bank_set *mca_set); -int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, struct ras_err_data *err_data); +int amdgpu_mca_smu_log_ras_error(struct amdgpu_device *adev, enum amdgpu_ras_block blk, enum amdgpu_mca_error_type type, + struct ras_err_data *err_data, struct ras_query_context *qctx); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index a98e03e0a51f..5ca5c47ab54e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -32,6 +32,18 @@ #define AMDGPU_MES_MAX_NUM_OF_QUEUES_PER_PROCESS 1024 #define AMDGPU_ONE_DOORBELL_SIZE 8 +signed long amdgpu_mes_fence_wait_polling(u64 *fence, + u64 wait_seq, + signed long timeout) +{ + + while ((s64)(wait_seq - *fence) > 0 && timeout > 0) { + udelay(2); + timeout -= 2; + } + return timeout > 0 ? timeout : 0; +} + int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev) { return roundup(AMDGPU_ONE_DOORBELL_SIZE * @@ -40,7 +52,6 @@ int amdgpu_mes_doorbell_process_slice(struct amdgpu_device *adev) } static int amdgpu_mes_kernel_doorbell_get(struct amdgpu_device *adev, - struct amdgpu_mes_process *process, int ip_type, uint64_t *doorbell_index) { unsigned int offset, found; @@ -65,7 +76,6 @@ static int amdgpu_mes_kernel_doorbell_get(struct amdgpu_device *adev, } static void amdgpu_mes_kernel_doorbell_free(struct amdgpu_device *adev, - struct amdgpu_mes_process *process, uint32_t doorbell_index) { unsigned int old, rel_index; @@ -102,7 +112,10 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev) { int r; - r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, + if (!amdgpu_mes_log_enable) + return 0; + + r = amdgpu_bo_create_kernel(adev, AMDGPU_MES_LOG_BUFFER_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, &adev->mes.event_log_gpu_obj, &adev->mes.event_log_gpu_addr, @@ -653,7 +666,7 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id, *queue_id = queue->queue_id = r; /* allocate a doorbell index for the queue */ - r = amdgpu_mes_kernel_doorbell_get(adev, gang->process, + r = amdgpu_mes_kernel_doorbell_get(adev, qprops->queue_type, &qprops->doorbell_off); if (r) @@ -711,8 +724,7 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id, return 0; clean_up_doorbell: - amdgpu_mes_kernel_doorbell_free(adev, gang->process, - qprops->doorbell_off); + amdgpu_mes_kernel_doorbell_free(adev, qprops->doorbell_off); clean_up_queue_id: spin_lock_irqsave(&adev->mes.queue_id_lock, flags); idr_remove(&adev->mes.queue_id_idr, queue->queue_id); @@ -766,8 +778,7 @@ int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id) queue_id); list_del(&queue->list); - amdgpu_mes_kernel_doorbell_free(adev, gang->process, - queue->doorbell_off); + amdgpu_mes_kernel_doorbell_free(adev, queue->doorbell_off); amdgpu_mes_unlock(&adev->mes); amdgpu_mes_queue_free_mqd(queue); @@ -775,6 +786,28 @@ int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id) return 0; } +int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev, + struct amdgpu_ring *ring) +{ + struct mes_map_legacy_queue_input queue_input; + int r; + + memset(&queue_input, 0, sizeof(queue_input)); + + queue_input.queue_type = ring->funcs->type; + queue_input.doorbell_offset = ring->doorbell_index; + queue_input.pipe_id = ring->pipe; + queue_input.queue_id = ring->queue; + queue_input.mqd_addr = amdgpu_bo_gpu_offset(ring->mqd_obj); + queue_input.wptr_addr = ring->wptr_gpu_addr; + + r = adev->mes.funcs->map_legacy_queue(&adev->mes, &queue_input); + if (r) + DRM_ERROR("failed to map legacy queue\n"); + + return r; +} + int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev, struct amdgpu_ring *ring, enum amdgpu_unmap_queues_action action, @@ -1129,6 +1162,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev, return; amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id); + del_timer_sync(&ring->fence_drv.fallback_timer); amdgpu_ring_fini(ring); kfree(ring); } @@ -1471,7 +1505,7 @@ int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe) const struct mes_firmware_header_v1_0 *mes_hdr; struct amdgpu_firmware_info *info; char ucode_prefix[30]; - char fw_name[40]; + char fw_name[50]; bool need_retry = false; int r; @@ -1549,12 +1583,11 @@ static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused) uint32_t *mem = (uint32_t *)(adev->mes.event_log_cpu_addr); seq_hex_dump(m, "", DUMP_PREFIX_OFFSET, 32, 4, - mem, PAGE_SIZE, false); + mem, AMDGPU_MES_LOG_BUFFER_SIZE, false); return 0; } - DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_mes_event_log); #endif @@ -1565,7 +1598,7 @@ void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev) #if defined(CONFIG_DEBUG_FS) struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; - if (adev->enable_mes) + if (adev->enable_mes && amdgpu_mes_log_enable) debugfs_create_file("amdgpu_mes_event_log", 0444, root, adev, &amdgpu_debugfs_mes_event_log_fops); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 7d4f93fea937..df9f0404d842 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -52,6 +52,7 @@ enum amdgpu_mes_priority_level { #define AMDGPU_MES_PROC_CTX_SIZE 0x1000 /* one page area */ #define AMDGPU_MES_GANG_CTX_SIZE 0x1000 /* one page area */ +#define AMDGPU_MES_LOG_BUFFER_SIZE 0x4000 /* Maximu log buffer size for MES */ struct amdgpu_mes_funcs; @@ -140,6 +141,12 @@ struct amdgpu_mes { /* ip specific functions */ const struct amdgpu_mes_funcs *funcs; + + /* mes resource_1 bo*/ + struct amdgpu_bo *resource_1; + uint64_t resource_1_gpu_addr; + void *resource_1_addr; + }; struct amdgpu_mes_process { @@ -241,6 +248,15 @@ struct mes_remove_queue_input { uint64_t gang_context_addr; }; +struct mes_map_legacy_queue_input { + uint32_t queue_type; + uint32_t doorbell_offset; + uint32_t pipe_id; + uint32_t queue_id; + uint64_t mqd_addr; + uint64_t wptr_addr; +}; + struct mes_unmap_legacy_queue_input { enum amdgpu_unmap_queues_action action; uint32_t queue_type; @@ -317,6 +333,9 @@ struct amdgpu_mes_funcs { int (*remove_hw_queue)(struct amdgpu_mes *mes, struct mes_remove_queue_input *input); + int (*map_legacy_queue)(struct amdgpu_mes *mes, + struct mes_map_legacy_queue_input *input); + int (*unmap_legacy_queue)(struct amdgpu_mes *mes, struct mes_unmap_legacy_queue_input *input); @@ -333,6 +352,10 @@ struct amdgpu_mes_funcs { #define amdgpu_mes_kiq_hw_init(adev) (adev)->mes.kiq_hw_init((adev)) #define amdgpu_mes_kiq_hw_fini(adev) (adev)->mes.kiq_hw_fini((adev)) +signed long amdgpu_mes_fence_wait_polling(u64 *fence, + u64 wait_seq, + signed long timeout); + int amdgpu_mes_ctx_get_offs(struct amdgpu_ring *ring, unsigned int id_offs); int amdgpu_mes_init_microcode(struct amdgpu_device *adev, int pipe); @@ -356,6 +379,8 @@ int amdgpu_mes_add_hw_queue(struct amdgpu_device *adev, int gang_id, int *queue_id); int amdgpu_mes_remove_hw_queue(struct amdgpu_device *adev, int queue_id); +int amdgpu_mes_map_legacy_queue(struct amdgpu_device *adev, + struct amdgpu_ring *ring); int amdgpu_mes_unmap_legacy_queue(struct amdgpu_device *adev, struct amdgpu_ring *ring, enum amdgpu_unmap_queues_action action, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index 1ca9d4ed8063..95d676ee207f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -63,6 +63,8 @@ struct amdgpu_mmhub_funcs { uint64_t page_table_base); void (*update_power_gating)(struct amdgpu_device *adev, bool enable); + bool (*query_utcl2_poison_status)(struct amdgpu_device *adev, + int hub_inst); }; struct amdgpu_mmhub { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 8bc79924d171..b2a83c802bbd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -39,6 +39,7 @@ #include "amdgpu.h" #include "amdgpu_trace.h" #include "amdgpu_amdkfd.h" +#include "amdgpu_vram_mgr.h" /** * DOC: amdgpu_object @@ -153,8 +154,10 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) else places[c].flags |= TTM_PL_FLAG_TOPDOWN; - if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) + if (abo->tbo.type == ttm_bo_type_kernel && + flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) places[c].flags |= TTM_PL_FLAG_CONTIGUOUS; + c++; } @@ -601,8 +604,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if (!amdgpu_bo_support_uswc(bo->flags)) bo->flags &= ~AMDGPU_GEM_CREATE_CPU_GTT_USWC; - if (adev->ras_enabled) - bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; + bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; bo->tbo.bdev = &adev->mman.bdev; if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA | @@ -611,6 +613,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev, else amdgpu_bo_placement_from_domain(bo, bp->domain); if (bp->type == ttm_bo_type_kernel) + bo->tbo.priority = 2; + else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE)) bo->tbo.priority = 1; if (!bp->destroy) @@ -623,8 +627,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, return r; if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && - bo->tbo.resource->mem_type == TTM_PL_VRAM && - amdgpu_bo_in_cpu_visible_vram(bo)) + amdgpu_res_cpu_visible(adev, bo->tbo.resource)) amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, ctx.bytes_moved); else @@ -634,7 +637,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, bo->tbo.resource->mem_type == TTM_PL_VRAM) { struct dma_fence *fence; - r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence, true); + r = amdgpu_ttm_clear_buffer(bo, bo->tbo.base.resv, &fence); if (unlikely(r)) goto fail_unreserve; @@ -764,7 +767,7 @@ int amdgpu_bo_restore_shadow(struct amdgpu_bo *shadow, struct dma_fence **fence) return amdgpu_copy_buffer(ring, shadow_addr, parent_addr, amdgpu_bo_size(shadow), NULL, fence, - true, false, false); + true, false, 0); } /** @@ -966,6 +969,10 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if (!bo->placements[i].lpfn || (lpfn && lpfn < bo->placements[i].lpfn)) bo->placements[i].lpfn = lpfn; + + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && + bo->placements[i].mem_type == TTM_PL_VRAM) + bo->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS; } r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); @@ -1278,23 +1285,25 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict) void amdgpu_bo_get_memory(struct amdgpu_bo *bo, struct amdgpu_mem_stats *stats) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + struct ttm_resource *res = bo->tbo.resource; uint64_t size = amdgpu_bo_size(bo); struct drm_gem_object *obj; unsigned int domain; bool shared; /* Abort if the BO doesn't currently have a backing store */ - if (!bo->tbo.resource) + if (!res) return; obj = &bo->tbo.base; shared = drm_gem_object_is_shared_for_memory_stats(obj); - domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type); + domain = amdgpu_mem_type_to_domain(res->mem_type); switch (domain) { case AMDGPU_GEM_DOMAIN_VRAM: stats->vram += size; - if (amdgpu_bo_in_cpu_visible_vram(bo)) + if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) stats->visible_vram += size; if (shared) stats->vram_shared += size; @@ -1365,8 +1374,9 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv))) return; - r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence, true); + r = amdgpu_fill_buffer(abo, 0, bo->base.resv, &fence, true); if (!WARN_ON(r)) { + amdgpu_vram_mgr_set_cleared(bo->resource); amdgpu_bo_fence(abo, fence, false); dma_fence_put(fence); } @@ -1395,10 +1405,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* Remember that this BO was accessed by the CPU */ abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - if (bo->resource->mem_type != TTM_PL_VRAM) - return 0; - - if (amdgpu_bo_in_cpu_visible_vram(abo)) + if (amdgpu_res_cpu_visible(adev, bo->resource)) return 0; /* Can't move a pinned BO to visible VRAM */ @@ -1421,7 +1428,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* this should never happen */ if (bo->resource->mem_type == TTM_PL_VRAM && - !amdgpu_bo_in_cpu_visible_vram(abo)) + !amdgpu_res_cpu_visible(adev, bo->resource)) return VM_FAULT_SIGBUS; ttm_bo_move_to_lru_tail_unlocked(bo); @@ -1585,6 +1592,7 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, */ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct dma_buf_attachment *attachment; struct dma_buf *dma_buf; const char *placement; @@ -1593,10 +1601,11 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) if (dma_resv_trylock(bo->tbo.base.resv)) { unsigned int domain; + domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type); switch (domain) { case AMDGPU_GEM_DOMAIN_VRAM: - if (amdgpu_bo_in_cpu_visible_vram(bo)) + if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) placement = "VRAM VISIBLE"; else placement = "VRAM"; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index be679c42b0b8..fa03d9e4874c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -250,28 +250,6 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } -/** - * amdgpu_bo_in_cpu_visible_vram - check if BO is (partly) in visible VRAM - */ -static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo) -{ - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct amdgpu_res_cursor cursor; - - if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM) - return false; - - amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); - while (cursor.remaining) { - if (cursor.start < adev->gmc.visible_vram_size) - return true; - - amdgpu_res_next(&cursor, cursor.size); - } - - return false; -} - /** * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 94b310fdb719..4bd4602d11b1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1053,6 +1053,11 @@ static int psp_asd_initialize(struct psp_context *psp) if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes) return 0; + /* bypass asd if display hardware is not available */ + if (!amdgpu_device_has_display_hardware(psp->adev) && + amdgpu_ip_version(psp->adev, MP0_HWIP, 0) >= IP_VERSION(13, 0, 10)) + return 0; + psp->asd_context.mem_context.shared_mc_addr = 0; psp->asd_context.mem_context.shared_mem_size = PSP_ASD_SHARED_MEM_SIZE; psp->asd_context.ta_load_type = GFX_CMD_ID_LOAD_ASD; @@ -2260,6 +2265,15 @@ static int psp_hw_start(struct psp_context *psp) } } + if ((is_psp_fw_valid(psp->ipkeymgr_drv)) && + (psp->funcs->bootloader_load_ipkeymgr_drv != NULL)) { + ret = psp_bootloader_load_ipkeymgr_drv(psp); + if (ret) { + dev_err(adev->dev, "PSP load ipkeymgr_drv failed!\n"); + return ret; + } + } + if ((is_psp_fw_valid(psp->sos)) && (psp->funcs->bootloader_load_sos != NULL)) { ret = psp_bootloader_load_sos(psp); @@ -2617,7 +2631,8 @@ static int psp_load_p2s_table(struct psp_context *psp) struct amdgpu_firmware_info *ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_P2S_TABLE]; - if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO)) + if (adev->in_runpm && ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) || + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO))) return 0; if (amdgpu_ip_version(adev, MP0_HWIP, 0) == IP_VERSION(13, 0, 6)) { @@ -2647,7 +2662,8 @@ static int psp_load_smu_fw(struct psp_context *psp) * Skip SMU FW reloading in case of using BACO for runpm only, * as SMU is always alive. */ - if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO)) + if (adev->in_runpm && ((adev->pm.rpm_mode == AMDGPU_RUNPM_BACO) || + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO))) return 0; if (!ucode->fw || amdgpu_sriov_vf(psp->adev)) @@ -3273,6 +3289,12 @@ static int parse_sos_bin_descriptor(struct psp_context *psp, psp->ras_drv.size_bytes = le32_to_cpu(desc->size_bytes); psp->ras_drv.start_addr = ucode_start_addr; break; + case PSP_FW_TYPE_PSP_IPKEYMGR_DRV: + psp->ipkeymgr_drv.fw_version = le32_to_cpu(desc->fw_version); + psp->ipkeymgr_drv.feature_version = le32_to_cpu(desc->fw_version); + psp->ipkeymgr_drv.size_bytes = le32_to_cpu(desc->size_bytes); + psp->ipkeymgr_drv.start_addr = ucode_start_addr; + break; default: dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index ee16f134ae92..3635303e6548 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -73,8 +73,10 @@ enum psp_bootloader_cmd { PSP_BL__LOAD_KEY_DATABASE = 0x80000, PSP_BL__LOAD_SOCDRV = 0xB0000, PSP_BL__LOAD_DBGDRV = 0xC0000, + PSP_BL__LOAD_HADDRV = PSP_BL__LOAD_DBGDRV, PSP_BL__LOAD_INTFDRV = 0xD0000, - PSP_BL__LOAD_RASDRV = 0xE0000, + PSP_BL__LOAD_RASDRV = 0xE0000, + PSP_BL__LOAD_IPKEYMGRDRV = 0xF0000, PSP_BL__DRAM_LONG_TRAIN = 0x100000, PSP_BL__DRAM_SHORT_TRAIN = 0x200000, PSP_BL__LOAD_TOS_SPL_TABLE = 0x10000000, @@ -117,6 +119,7 @@ struct psp_funcs { int (*bootloader_load_intf_drv)(struct psp_context *psp); int (*bootloader_load_dbg_drv)(struct psp_context *psp); int (*bootloader_load_ras_drv)(struct psp_context *psp); + int (*bootloader_load_ipkeymgr_drv)(struct psp_context *psp); int (*bootloader_load_sos)(struct psp_context *psp); int (*ring_create)(struct psp_context *psp, enum psp_ring_type ring_type); @@ -336,6 +339,7 @@ struct psp_context { struct psp_bin_desc intf_drv; struct psp_bin_desc dbg_drv; struct psp_bin_desc ras_drv; + struct psp_bin_desc ipkeymgr_drv; /* tmr buffer */ struct amdgpu_bo *tmr_bo; @@ -424,6 +428,9 @@ struct amdgpu_psp_funcs { #define psp_bootloader_load_ras_drv(psp) \ ((psp)->funcs->bootloader_load_ras_drv ? \ (psp)->funcs->bootloader_load_ras_drv((psp)) : 0) +#define psp_bootloader_load_ipkeymgr_drv(psp) \ + ((psp)->funcs->bootloader_load_ipkeymgr_drv ? \ + (psp)->funcs->bootloader_load_ipkeymgr_drv((psp)) : 0) #define psp_bootloader_load_sos(psp) \ ((psp)->funcs->bootloader_load_sos ? (psp)->funcs->bootloader_load_sos((psp)) : 0) #define psp_smu_reload_quirk(psp) \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 8ebab6f22e5a..1adc81a55734 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -122,6 +122,8 @@ const char *get_ras_block_str(struct ras_common_if *ras_block) #define MAX_UMC_POISON_POLLING_TIME_ASYNC 100 //ms +#define AMDGPU_RAS_RETIRE_PAGE_INTERVAL 100 //ms + enum amdgpu_ras_retire_page_reservation { AMDGPU_RAS_RETIRE_PAGE_RESERVED, AMDGPU_RAS_RETIRE_PAGE_PENDING, @@ -1045,6 +1047,7 @@ static void amdgpu_ras_get_ecc_info(struct amdgpu_device *adev, struct ras_err_d static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev, struct ras_manager *ras_mgr, struct ras_err_data *err_data, + struct ras_query_context *qctx, const char *blk_name, bool is_ue, bool is_de) @@ -1052,27 +1055,28 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev, struct amdgpu_smuio_mcm_config_info *mcm_info; struct ras_err_node *err_node; struct ras_err_info *err_info; + u64 event_id = qctx->event_id; if (is_ue) { for_each_ras_error(err_node, err_data) { err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; if (err_info->ue_count) { - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld new uncorrectable hardware errors detected in %s block\n", - mcm_info->socket_id, - mcm_info->die_id, - err_info->ue_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld new uncorrectable hardware errors detected in %s block\n", + mcm_info->socket_id, + mcm_info->die_id, + err_info->ue_count, + blk_name); } } for_each_ras_error(err_node, &ras_mgr->err_data) { err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld uncorrectable hardware errors detected in total in %s block\n", - mcm_info->socket_id, mcm_info->die_id, err_info->ue_count, blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld uncorrectable hardware errors detected in total in %s block\n", + mcm_info->socket_id, mcm_info->die_id, err_info->ue_count, blk_name); } } else { @@ -1081,44 +1085,44 @@ static void amdgpu_ras_error_print_error_data(struct amdgpu_device *adev, err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; if (err_info->de_count) { - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld new deferred hardware errors detected in %s block\n", - mcm_info->socket_id, - mcm_info->die_id, - err_info->de_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld new deferred hardware errors detected in %s block\n", + mcm_info->socket_id, + mcm_info->die_id, + err_info->de_count, + blk_name); } } for_each_ras_error(err_node, &ras_mgr->err_data) { err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld deferred hardware errors detected in total in %s block\n", - mcm_info->socket_id, mcm_info->die_id, - err_info->de_count, blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld deferred hardware errors detected in total in %s block\n", + mcm_info->socket_id, mcm_info->die_id, + err_info->de_count, blk_name); } } else { for_each_ras_error(err_node, err_data) { err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; if (err_info->ce_count) { - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld new correctable hardware errors detected in %s block\n", - mcm_info->socket_id, - mcm_info->die_id, - err_info->ce_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld new correctable hardware errors detected in %s block\n", + mcm_info->socket_id, + mcm_info->die_id, + err_info->ce_count, + blk_name); } } for_each_ras_error(err_node, &ras_mgr->err_data) { err_info = &err_node->err_info; mcm_info = &err_info->mcm_info; - dev_info(adev->dev, "socket: %d, die: %d, " - "%lld correctable hardware errors detected in total in %s block\n", - mcm_info->socket_id, mcm_info->die_id, - err_info->ce_count, blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d, " + "%lld correctable hardware errors detected in total in %s block\n", + mcm_info->socket_id, mcm_info->die_id, + err_info->ce_count, blk_name); } } } @@ -1131,77 +1135,79 @@ static inline bool err_data_has_source_info(struct ras_err_data *data) static void amdgpu_ras_error_generate_report(struct amdgpu_device *adev, struct ras_query_if *query_if, - struct ras_err_data *err_data) + struct ras_err_data *err_data, + struct ras_query_context *qctx) { struct ras_manager *ras_mgr = amdgpu_ras_find_obj(adev, &query_if->head); const char *blk_name = get_ras_block_str(&query_if->head); + u64 event_id = qctx->event_id; if (err_data->ce_count) { if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, + amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, blk_name, false, false); } else if (!adev->aid_mask && adev->smuio.funcs && adev->smuio.funcs->get_socket_id && adev->smuio.funcs->get_die_id) { - dev_info(adev->dev, "socket: %d, die: %d " - "%ld correctable hardware errors " - "detected in %s block\n", - adev->smuio.funcs->get_socket_id(adev), - adev->smuio.funcs->get_die_id(adev), - ras_mgr->err_data.ce_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d " + "%ld correctable hardware errors " + "detected in %s block\n", + adev->smuio.funcs->get_socket_id(adev), + adev->smuio.funcs->get_die_id(adev), + ras_mgr->err_data.ce_count, + blk_name); } else { - dev_info(adev->dev, "%ld correctable hardware errors " - "detected in %s block\n", - ras_mgr->err_data.ce_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "%ld correctable hardware errors " + "detected in %s block\n", + ras_mgr->err_data.ce_count, + blk_name); } } if (err_data->ue_count) { if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, + amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, blk_name, true, false); } else if (!adev->aid_mask && adev->smuio.funcs && adev->smuio.funcs->get_socket_id && adev->smuio.funcs->get_die_id) { - dev_info(adev->dev, "socket: %d, die: %d " - "%ld uncorrectable hardware errors " - "detected in %s block\n", - adev->smuio.funcs->get_socket_id(adev), - adev->smuio.funcs->get_die_id(adev), - ras_mgr->err_data.ue_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d " + "%ld uncorrectable hardware errors " + "detected in %s block\n", + adev->smuio.funcs->get_socket_id(adev), + adev->smuio.funcs->get_die_id(adev), + ras_mgr->err_data.ue_count, + blk_name); } else { - dev_info(adev->dev, "%ld uncorrectable hardware errors " - "detected in %s block\n", - ras_mgr->err_data.ue_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "%ld uncorrectable hardware errors " + "detected in %s block\n", + ras_mgr->err_data.ue_count, + blk_name); } } if (err_data->de_count) { if (err_data_has_source_info(err_data)) { - amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, + amdgpu_ras_error_print_error_data(adev, ras_mgr, err_data, qctx, blk_name, false, true); } else if (!adev->aid_mask && adev->smuio.funcs && adev->smuio.funcs->get_socket_id && adev->smuio.funcs->get_die_id) { - dev_info(adev->dev, "socket: %d, die: %d " - "%ld deferred hardware errors " - "detected in %s block\n", - adev->smuio.funcs->get_socket_id(adev), - adev->smuio.funcs->get_die_id(adev), - ras_mgr->err_data.de_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "socket: %d, die: %d " + "%ld deferred hardware errors " + "detected in %s block\n", + adev->smuio.funcs->get_socket_id(adev), + adev->smuio.funcs->get_die_id(adev), + ras_mgr->err_data.de_count, + blk_name); } else { - dev_info(adev->dev, "%ld deferred hardware errors " - "detected in %s block\n", - ras_mgr->err_data.de_count, - blk_name); + RAS_EVENT_LOG(adev, event_id, "%ld deferred hardware errors " + "detected in %s block\n", + ras_mgr->err_data.de_count, + blk_name); } } } @@ -1244,6 +1250,10 @@ int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk, { struct ras_manager *obj; + /* in resume phase, no need to create aca fs node */ + if (adev->in_suspend || amdgpu_in_reset(adev)) + return 0; + obj = get_ras_manager(adev, blk); if (!obj) return -EINVAL; @@ -1265,7 +1275,8 @@ int amdgpu_ras_unbind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk) } static int amdgpu_aca_log_ras_error_data(struct amdgpu_device *adev, enum amdgpu_ras_block blk, - enum aca_error_type type, struct ras_err_data *err_data) + enum aca_error_type type, struct ras_err_data *err_data, + struct ras_query_context *qctx) { struct ras_manager *obj; @@ -1273,7 +1284,7 @@ static int amdgpu_aca_log_ras_error_data(struct amdgpu_device *adev, enum amdgpu if (!obj) return -EINVAL; - return amdgpu_aca_get_error_data(adev, &obj->aca_handle, type, err_data); + return amdgpu_aca_get_error_data(adev, &obj->aca_handle, type, err_data, qctx); } ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *attr, @@ -1287,13 +1298,14 @@ ssize_t amdgpu_ras_aca_sysfs_read(struct device *dev, struct device_attribute *a if (amdgpu_ras_query_error_status(obj->adev, &info)) return -EINVAL; - return sysfs_emit(buf, "%s: %lu\n%s: %lu\n", "ue", info.ue_count, - "ce", info.ce_count); + return sysfs_emit(buf, "%s: %lu\n%s: %lu\n%s: %lu\n", "ue", info.ue_count, + "ce", info.ce_count, "de", info.ue_count); } static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev, struct ras_query_if *info, struct ras_err_data *err_data, + struct ras_query_context *qctx, unsigned int error_query_mode) { enum amdgpu_ras_block blk = info ? info->head.block : AMDGPU_RAS_BLOCK_COUNT; @@ -1329,17 +1341,21 @@ static int amdgpu_ras_query_error_status_helper(struct amdgpu_device *adev, } } else { if (amdgpu_aca_is_enabled(adev)) { - ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_UE, err_data); + ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_UE, err_data, qctx); if (ret) return ret; - ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_CE, err_data); + ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_CE, err_data, qctx); + if (ret) + return ret; + + ret = amdgpu_aca_log_ras_error_data(adev, blk, ACA_ERROR_TYPE_DEFERRED, err_data, qctx); if (ret) return ret; } else { /* FIXME: add code to check return value later */ - amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data); - amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data); + amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_UE, err_data, qctx); + amdgpu_mca_smu_log_ras_error(adev, blk, AMDGPU_MCA_ERROR_TYPE_CE, err_data, qctx); } } @@ -1351,6 +1367,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i { struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head); struct ras_err_data err_data; + struct ras_query_context qctx; unsigned int error_query_mode; int ret; @@ -1364,8 +1381,12 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i if (!amdgpu_ras_get_error_query_mode(adev, &error_query_mode)) return -EINVAL; + memset(&qctx, 0, sizeof(qctx)); + qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ? + RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID); ret = amdgpu_ras_query_error_status_helper(adev, info, &err_data, + &qctx, error_query_mode); if (ret) goto out_fini_err_data; @@ -1376,7 +1397,7 @@ int amdgpu_ras_query_error_status(struct amdgpu_device *adev, struct ras_query_i info->ce_count = obj->err_data.ce_count; info->de_count = obj->err_data.de_count; - amdgpu_ras_error_generate_report(adev, info, &err_data); + amdgpu_ras_error_generate_report(adev, info, &err_data, &qctx); out_fini_err_data: amdgpu_ras_error_data_fini(&err_data); @@ -2041,7 +2062,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager * } } - amdgpu_umc_poison_handler(adev, obj->head.block, false); + amdgpu_umc_poison_handler(adev, obj->head.block, 0); if (block_obj->hw_ops && block_obj->hw_ops->handle_poison_consumption) poison_stat = block_obj->hw_ops->handle_poison_consumption(adev); @@ -2061,6 +2082,17 @@ static void amdgpu_ras_interrupt_poison_creation_handler(struct ras_manager *obj { dev_info(obj->adev->dev, "Poison is created\n"); + + if (amdgpu_ip_version(obj->adev, UMC_HWIP, 0) >= IP_VERSION(12, 0, 0)) { + struct amdgpu_ras *con = amdgpu_ras_get_context(obj->adev); + + amdgpu_ras_put_poison_req(obj->adev, + AMDGPU_RAS_BLOCK__UMC, 0, NULL, NULL, false); + + atomic_inc(&con->page_retirement_req_cnt); + + wake_up(&con->page_retirement_wq); + } } static void amdgpu_ras_interrupt_umc_handler(struct ras_manager *obj, @@ -2371,7 +2403,7 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev, .flags = AMDGPU_RAS_RETIRE_PAGE_RESERVED, }; status = amdgpu_vram_mgr_query_page_status(&adev->mman.vram_mgr, - data->bps[i].retired_page); + data->bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT); if (status == -EBUSY) (*bps)[i].flags = AMDGPU_RAS_RETIRE_PAGE_PENDING; else if (status == -ENOENT) @@ -2384,6 +2416,19 @@ static int amdgpu_ras_badpages_read(struct amdgpu_device *adev, return ret; } +static void amdgpu_ras_set_fed_all(struct amdgpu_device *adev, + struct amdgpu_hive_info *hive, bool status) +{ + struct amdgpu_device *tmp_adev; + + if (hive) { + list_for_each_entry(tmp_adev, &hive->device_list, gmc.xgmi.head) + amdgpu_ras_set_fed(tmp_adev, status); + } else { + amdgpu_ras_set_fed(adev, status); + } +} + static void amdgpu_ras_do_recovery(struct work_struct *work) { struct amdgpu_ras *ras = @@ -2393,8 +2438,21 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) struct list_head device_list, *device_list_handle = NULL; struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); - if (hive) + if (hive) { atomic_set(&hive->ras_recovery, 1); + + /* If any device which is part of the hive received RAS fatal + * error interrupt, set fatal error status on all. This + * condition will need a recovery, and flag will be cleared + * as part of recovery. + */ + list_for_each_entry(remote_adev, &hive->device_list, + gmc.xgmi.head) + if (amdgpu_ras_get_fed_status(remote_adev)) { + amdgpu_ras_set_fed_all(adev, hive, true); + break; + } + } if (!ras->disable_ras_err_cnt_harvest) { /* Build list of devices to query RAS related errors */ @@ -2439,18 +2497,6 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) ras->gpu_reset_flags &= ~AMDGPU_RAS_GPU_RESET_MODE1_RESET; set_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags); - /* For any RAS error that needs a full reset to - * recover, set the fatal error status - */ - if (hive) { - list_for_each_entry(remote_adev, - &hive->device_list, - gmc.xgmi.head) - amdgpu_ras_set_fed(remote_adev, - true); - } else { - amdgpu_ras_set_fed(adev, true); - } psp_fatal_error_recovery_quirk(&adev->psp); } } @@ -2516,9 +2562,7 @@ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, goto out; } - amdgpu_vram_mgr_reserve_range(&adev->mman.vram_mgr, - bps[i].retired_page << AMDGPU_GPU_PAGE_SHIFT, - AMDGPU_GPU_PAGE_SIZE); + amdgpu_ras_reserve_page(adev, bps[i].retired_page); memcpy(&data->bps[data->count], &bps[i], sizeof(*data->bps)); data->count++; @@ -2674,10 +2718,167 @@ static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, } } +int amdgpu_ras_put_poison_req(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset) +{ + int ret = 0; + struct ras_poison_msg poison_msg; + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + + memset(&poison_msg, 0, sizeof(poison_msg)); + poison_msg.block = block; + poison_msg.pasid = pasid; + poison_msg.reset = reset; + poison_msg.pasid_fn = pasid_fn; + poison_msg.data = data; + + ret = kfifo_put(&con->poison_fifo, poison_msg); + if (!ret) { + dev_err(adev->dev, "Poison message fifo is full!\n"); + return -ENOSPC; + } + + return 0; +} + +static int amdgpu_ras_get_poison_req(struct amdgpu_device *adev, + struct ras_poison_msg *poison_msg) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + + return kfifo_get(&con->poison_fifo, poison_msg); +} + +static void amdgpu_ras_ecc_log_init(struct ras_ecc_log_info *ecc_log) +{ + mutex_init(&ecc_log->lock); + + /* Set any value as siphash key */ + memset(&ecc_log->ecc_key, 0xad, sizeof(ecc_log->ecc_key)); + + INIT_RADIX_TREE(&ecc_log->de_page_tree, GFP_KERNEL); + ecc_log->de_updated = false; +} + +static void amdgpu_ras_ecc_log_fini(struct ras_ecc_log_info *ecc_log) +{ + struct radix_tree_iter iter; + void __rcu **slot; + struct ras_ecc_err *ecc_err; + + mutex_lock(&ecc_log->lock); + radix_tree_for_each_slot(slot, &ecc_log->de_page_tree, &iter, 0) { + ecc_err = radix_tree_deref_slot(slot); + kfree(ecc_err->err_pages.pfn); + kfree(ecc_err); + radix_tree_iter_delete(&ecc_log->de_page_tree, &iter, slot); + } + mutex_unlock(&ecc_log->lock); + + mutex_destroy(&ecc_log->lock); + ecc_log->de_updated = false; +} + +static void amdgpu_ras_do_page_retirement(struct work_struct *work) +{ + struct amdgpu_ras *con = container_of(work, struct amdgpu_ras, + page_retirement_dwork.work); + struct amdgpu_device *adev = con->adev; + struct ras_err_data err_data; + + if (amdgpu_in_reset(adev) || atomic_read(&con->in_recovery)) + return; + + amdgpu_ras_error_data_init(&err_data); + + amdgpu_umc_handle_bad_pages(adev, &err_data); + + amdgpu_ras_error_data_fini(&err_data); + + mutex_lock(&con->umc_ecc_log.lock); + if (radix_tree_tagged(&con->umc_ecc_log.de_page_tree, + UMC_ECC_NEW_DETECTED_TAG)) + schedule_delayed_work(&con->page_retirement_dwork, + msecs_to_jiffies(AMDGPU_RAS_RETIRE_PAGE_INTERVAL)); + mutex_unlock(&con->umc_ecc_log.lock); +} + +static int amdgpu_ras_query_ecc_status(struct amdgpu_device *adev, + enum amdgpu_ras_block ras_block, uint32_t timeout_ms) +{ + int ret = 0; + struct ras_ecc_log_info *ecc_log; + struct ras_query_if info; + uint32_t timeout = timeout_ms; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + + memset(&info, 0, sizeof(info)); + info.head.block = ras_block; + + ecc_log = &ras->umc_ecc_log; + ecc_log->de_updated = false; + do { + ret = amdgpu_ras_query_error_status(adev, &info); + if (ret) { + dev_err(adev->dev, "Failed to query ras error! ret:%d\n", ret); + return ret; + } + + if (timeout && !ecc_log->de_updated) { + msleep(1); + timeout--; + } + } while (timeout && !ecc_log->de_updated); + + if (timeout_ms && !timeout) { + dev_warn(adev->dev, "Can't find deferred error\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void amdgpu_ras_poison_creation_handler(struct amdgpu_device *adev, + uint32_t timeout) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + int ret; + + ret = amdgpu_ras_query_ecc_status(adev, AMDGPU_RAS_BLOCK__UMC, timeout); + if (!ret) + schedule_delayed_work(&con->page_retirement_dwork, 0); +} + +static int amdgpu_ras_poison_consumption_handler(struct amdgpu_device *adev, + struct ras_poison_msg *poison_msg) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + uint32_t reset = poison_msg->reset; + uint16_t pasid = poison_msg->pasid; + + kgd2kfd_set_sram_ecc_flag(adev->kfd.dev); + + if (poison_msg->pasid_fn) + poison_msg->pasid_fn(adev, pasid, poison_msg->data); + + if (reset) { + flush_delayed_work(&con->page_retirement_dwork); + + con->gpu_reset_flags |= reset; + amdgpu_ras_reset_gpu(adev); + } + + return 0; +} + static int amdgpu_ras_page_retirement_thread(void *param) { struct amdgpu_device *adev = (struct amdgpu_device *)param; struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_poison_msg poison_msg; + enum amdgpu_ras_block ras_block; + bool poison_creation_is_handled = false; while (!kthread_should_stop()) { @@ -2688,13 +2889,34 @@ static int amdgpu_ras_page_retirement_thread(void *param) if (kthread_should_stop()) break; - dev_info(adev->dev, "Start processing page retirement. request:%d\n", - atomic_read(&con->page_retirement_req_cnt)); - atomic_dec(&con->page_retirement_req_cnt); - amdgpu_umc_bad_page_polling_timeout(adev, - false, MAX_UMC_POISON_POLLING_TIME_ASYNC); + if (!amdgpu_ras_get_poison_req(adev, &poison_msg)) + continue; + + ras_block = poison_msg.block; + + dev_info(adev->dev, "Start processing ras block %s(%d)\n", + ras_block_str(ras_block), ras_block); + + if (ras_block == AMDGPU_RAS_BLOCK__UMC) { + amdgpu_ras_poison_creation_handler(adev, + MAX_UMC_POISON_POLLING_TIME_ASYNC); + poison_creation_is_handled = true; + } else { + /* poison_creation_is_handled: + * false: no poison creation interrupt, but it has poison + * consumption interrupt. + * true: It has poison creation interrupt at the beginning, + * but it has no poison creation interrupt later. + */ + amdgpu_ras_poison_creation_handler(adev, + poison_creation_is_handled ? + 0 : MAX_UMC_POISON_POLLING_TIME_ASYNC); + + amdgpu_ras_poison_consumption_handler(adev, &poison_msg); + poison_creation_is_handled = false; + } } return 0; @@ -2763,6 +2985,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) } } + mutex_init(&con->page_rsv_lock); + INIT_KFIFO(con->poison_fifo); mutex_init(&con->page_retirement_lock); init_waitqueue_head(&con->page_retirement_wq); atomic_set(&con->page_retirement_req_cnt, 0); @@ -2773,6 +2997,8 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) dev_warn(adev->dev, "Failed to create umc_page_retirement thread!!!\n"); } + INIT_DELAYED_WORK(&con->page_retirement_dwork, amdgpu_ras_do_page_retirement); + amdgpu_ras_ecc_log_init(&con->umc_ecc_log); #ifdef CONFIG_X86_MCE_AMD if ((adev->asic_type == CHIP_ALDEBARAN) && (adev->gmc.xgmi.connected_to_cpu)) @@ -2813,8 +3039,14 @@ static int amdgpu_ras_recovery_fini(struct amdgpu_device *adev) atomic_set(&con->page_retirement_req_cnt, 0); + mutex_destroy(&con->page_rsv_lock); + cancel_work_sync(&con->recovery_work); + cancel_delayed_work_sync(&con->page_retirement_dwork); + + amdgpu_ras_ecc_log_fini(&con->umc_ecc_log); + mutex_lock(&con->recovery_lock); con->eh_data = NULL; kfree(data->bps); @@ -3036,6 +3268,35 @@ static int amdgpu_get_ras_schema(struct amdgpu_device *adev) AMDGPU_RAS_ERROR__PARITY; } +static void ras_event_mgr_init(struct ras_event_manager *mgr) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mgr->seqnos); i++) + atomic64_set(&mgr->seqnos[i], 0); +} + +static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev) +{ + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + struct amdgpu_hive_info *hive; + + if (!ras) + return; + + hive = amdgpu_get_xgmi_hive(adev); + ras->event_mgr = hive ? &hive->event_mgr : &ras->__event_mgr; + + /* init event manager with node 0 on xgmi system */ + if (!amdgpu_in_reset(adev)) { + if (!hive || adev->gmc.xgmi.node_id == 0) + ras_event_mgr_init(ras->event_mgr); + } + + if (hive) + amdgpu_put_xgmi_hive(hive); +} + int amdgpu_ras_init(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -3356,6 +3617,8 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev) if (amdgpu_sriov_vf(adev)) return 0; + amdgpu_ras_event_mgr_init(adev); + if (amdgpu_aca_is_enabled(adev)) { if (amdgpu_in_reset(adev)) r = amdgpu_aca_reset(adev); @@ -3472,14 +3735,39 @@ void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status) atomic_set(&ras->fed, !!status); } +bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id) +{ + return !(id & BIT_ULL(63)); +} + +u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type) +{ + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + u64 id; + + switch (type) { + case RAS_EVENT_TYPE_ISR: + id = (u64)atomic64_read(&ras->event_mgr->seqnos[type]); + break; + case RAS_EVENT_TYPE_INVALID: + default: + id = BIT_ULL(63) | 0ULL; + break; + } + + return id; +} + void amdgpu_ras_global_ras_isr(struct amdgpu_device *adev) { if (atomic_cmpxchg(&amdgpu_ras_in_intr, 0, 1) == 0) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + u64 event_id = (u64)atomic64_inc_return(&ras->event_mgr->seqnos[RAS_EVENT_TYPE_ISR]); - dev_info(adev->dev, "uncorrectable hardware error" - "(ERREVENT_ATHUB_INTERRUPT) detected!\n"); + RAS_EVENT_LOG(adev, event_id, "uncorrectable hardware error" + "(ERREVENT_ATHUB_INTERRUPT) detected!\n"); + amdgpu_ras_set_fed(adev, true); ras->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE1_RESET; amdgpu_ras_reset_gpu(adev); } @@ -3998,6 +4286,8 @@ void amdgpu_ras_add_mca_err_addr(struct ras_err_info *err_info, struct ras_err_a { struct ras_err_addr *mca_err_addr; + /* This function will be retired. */ + return; mca_err_addr = kzalloc(sizeof(*mca_err_addr), GFP_KERNEL); if (!mca_err_addr) return; @@ -4195,3 +4485,19 @@ void amdgpu_ras_query_boot_status(struct amdgpu_device *adev, u32 num_instances) amdgpu_ras_boot_time_error_reporting(adev, i, boot_error); } } + +int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr; + uint64_t start = pfn << AMDGPU_GPU_PAGE_SHIFT; + int ret = 0; + + mutex_lock(&con->page_rsv_lock); + ret = amdgpu_vram_mgr_query_page_status(mgr, start); + if (ret == -ENOENT) + ret = amdgpu_vram_mgr_reserve_range(mgr, start, AMDGPU_GPU_PAGE_SIZE); + mutex_unlock(&con->page_rsv_lock); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index e0f8ce9d8440..c8980d5f6540 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -26,6 +26,9 @@ #include #include +#include +#include +#include #include "ta_ras_if.h" #include "amdgpu_ras_eeprom.h" #include "amdgpu_smuio.h" @@ -64,6 +67,14 @@ struct amdgpu_iv_entry; /* The high three bits indicates socketid */ #define AMDGPU_RAS_GET_FEATURES(val) ((val) & ~AMDGPU_RAS_FEATURES_SOCKETID_MASK) +#define RAS_EVENT_LOG(_adev, _id, _fmt, ...) \ +do { \ + if (amdgpu_ras_event_id_is_valid((_adev), (_id))) \ + dev_info((_adev)->dev, "{%llu}" _fmt, (_id), ##__VA_ARGS__); \ + else \ + dev_info((_adev)->dev, _fmt, ##__VA_ARGS__); \ +} while (0) + enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__UMC = 0, AMDGPU_RAS_BLOCK__SDMA, @@ -419,6 +430,52 @@ struct umc_ecc_info { int record_ce_addr_supported; }; +enum ras_event_type { + RAS_EVENT_TYPE_INVALID = -1, + RAS_EVENT_TYPE_ISR = 0, + RAS_EVENT_TYPE_COUNT, +}; + +struct ras_event_manager { + atomic64_t seqnos[RAS_EVENT_TYPE_COUNT]; +}; + +struct ras_query_context { + enum ras_event_type type; + u64 event_id; +}; + +typedef int (*pasid_notify)(struct amdgpu_device *adev, + uint16_t pasid, void *data); + +struct ras_poison_msg { + enum amdgpu_ras_block block; + uint16_t pasid; + uint32_t reset; + pasid_notify pasid_fn; + void *data; +}; + +struct ras_err_pages { + uint32_t count; + uint64_t *pfn; +}; + +struct ras_ecc_err { + u64 hash_index; + uint64_t status; + uint64_t ipid; + uint64_t addr; + struct ras_err_pages err_pages; +}; + +struct ras_ecc_log_info { + struct mutex lock; + siphash_key_t ecc_key; + struct radix_tree_root de_page_tree; + bool de_updated; +}; + struct amdgpu_ras { /* ras infrastructure */ /* for ras itself. */ @@ -477,8 +534,18 @@ struct amdgpu_ras { wait_queue_head_t page_retirement_wq; struct mutex page_retirement_lock; atomic_t page_retirement_req_cnt; + struct mutex page_rsv_lock; + DECLARE_KFIFO(poison_fifo, struct ras_poison_msg, 128); + struct ras_ecc_log_info umc_ecc_log; + struct delayed_work page_retirement_dwork; + /* Fatal error detected flag */ atomic_t fed; + + /* RAS event manager */ + struct ras_event_manager __event_mgr; + struct ras_event_manager *event_mgr; + }; struct ras_fs_data { @@ -512,6 +579,7 @@ struct ras_err_data { unsigned long de_count; unsigned long err_addr_cnt; struct eeprom_table_record *err_addr; + unsigned long err_addr_len; u32 err_list_count; struct list_head err_node_list; }; @@ -879,4 +947,13 @@ void amdgpu_ras_del_mca_err_addr(struct ras_err_info *err_info, void amdgpu_ras_set_fed(struct amdgpu_device *adev, bool status); bool amdgpu_ras_get_fed_status(struct amdgpu_device *adev); +bool amdgpu_ras_event_id_is_valid(struct amdgpu_device *adev, u64 id); +u64 amdgpu_ras_acquire_event_id(struct amdgpu_device *adev, enum ras_event_type type); + +int amdgpu_ras_reserve_page(struct amdgpu_device *adev, uint64_t pfn); + +int amdgpu_ras_put_poison_req(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index b12808c0c331..06a62a8a992e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -404,6 +404,22 @@ static int amdgpu_ras_eeprom_correct_header_tag( return res; } +static void amdgpu_ras_set_eeprom_table_version(struct amdgpu_ras_eeprom_control *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + + switch (amdgpu_ip_version(adev, UMC_HWIP, 0)) { + case IP_VERSION(8, 10, 0): + case IP_VERSION(12, 0, 0): + hdr->version = RAS_TABLE_VER_V2_1; + return; + default: + hdr->version = RAS_TABLE_VER_V1; + return; + } +} + /** * amdgpu_ras_eeprom_reset_table -- Reset the RAS EEPROM table * @control: pointer to control structure @@ -423,11 +439,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) mutex_lock(&control->ras_tbl_mutex); hdr->header = RAS_TABLE_HDR_VAL; - if (adev->umc.ras && - adev->umc.ras->set_eeprom_table_version) - adev->umc.ras->set_eeprom_table_version(hdr); - else - hdr->version = RAS_TABLE_VER_V1; + amdgpu_ras_set_eeprom_table_version(control); if (hdr->version == RAS_TABLE_VER_V2_1) { hdr->first_rec_offset = RAS_RECORD_START_V2_1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h index 381101d2bf05..50fcd86e1033 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h @@ -164,4 +164,29 @@ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size) } } +/** + * amdgpu_res_cleared - check if blocks are cleared + * + * @cur: the cursor to extract the block + * + * Check if the @cur block is cleared + */ +static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur) +{ + struct drm_buddy_block *block; + + switch (cur->mem_type) { + case TTM_PL_VRAM: + block = cur->node; + + if (!amdgpu_vram_mgr_is_cleared(block)) + return false; + break; + default: + return false; + } + + return true; +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c index 147100c27c2d..ea4873f6ccd1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c @@ -21,9 +21,6 @@ * */ -#include -#include - #include "amdgpu_reset.h" #include "aldebaran.h" #include "sienna_cichlid.h" @@ -161,105 +158,3 @@ void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain) atomic_set(&reset_domain->in_gpu_reset, 0); up_write(&reset_domain->sem); } - -#ifndef CONFIG_DEV_COREDUMP -void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, - struct amdgpu_reset_context *reset_context) -{ -} -#else -static ssize_t -amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count, - void *data, size_t datalen) -{ - struct drm_printer p; - struct amdgpu_coredump_info *coredump = data; - struct drm_print_iterator iter; - int i; - - iter.data = buffer; - iter.offset = 0; - iter.start = offset; - iter.remain = count; - - p = drm_coredump_printer(&iter); - - drm_printf(&p, "**** AMDGPU Device Coredump ****\n"); - drm_printf(&p, "version: " AMDGPU_COREDUMP_VERSION "\n"); - drm_printf(&p, "kernel: " UTS_RELEASE "\n"); - drm_printf(&p, "module: " KBUILD_MODNAME "\n"); - drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec, - coredump->reset_time.tv_nsec); - - if (coredump->reset_task_info.pid) - drm_printf(&p, "process_name: %s PID: %d\n", - coredump->reset_task_info.process_name, - coredump->reset_task_info.pid); - - if (coredump->ring) { - drm_printf(&p, "\nRing timed out details\n"); - drm_printf(&p, "IP Type: %d Ring Name: %s\n", - coredump->ring->funcs->type, - coredump->ring->name); - } - - if (coredump->reset_vram_lost) - drm_printf(&p, "VRAM is lost due to GPU reset!\n"); - if (coredump->adev->reset_info.num_regs) { - drm_printf(&p, "AMDGPU register dumps:\nOffset: Value:\n"); - - for (i = 0; i < coredump->adev->reset_info.num_regs; i++) - drm_printf(&p, "0x%08x: 0x%08x\n", - coredump->adev->reset_info.reset_dump_reg_list[i], - coredump->adev->reset_info.reset_dump_reg_value[i]); - } - - return count - iter.remain; -} - -static void amdgpu_devcoredump_free(void *data) -{ - kfree(data); -} - -void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, - struct amdgpu_reset_context *reset_context) -{ - struct amdgpu_coredump_info *coredump; - struct drm_device *dev = adev_to_drm(adev); - struct amdgpu_job *job = reset_context->job; - struct drm_sched_job *s_job; - - coredump = kzalloc(sizeof(*coredump), GFP_NOWAIT); - - if (!coredump) { - DRM_ERROR("%s: failed to allocate memory for coredump\n", __func__); - return; - } - - coredump->reset_vram_lost = vram_lost; - - if (reset_context->job && reset_context->job->vm) { - struct amdgpu_task_info *ti; - struct amdgpu_vm *vm = reset_context->job->vm; - - ti = amdgpu_vm_get_task_info_vm(vm); - if (ti) { - coredump->reset_task_info = *ti; - amdgpu_vm_put_task_info(ti); - } - } - - if (job) { - s_job = &job->base; - coredump->ring = to_amdgpu_ring(s_job->sched); - } - - coredump->adev = adev; - - ktime_get_ts64(&coredump->reset_time); - - dev_coredumpm(dev->dev, THIS_MODULE, coredump, 0, GFP_NOWAIT, - amdgpu_devcoredump_read, amdgpu_devcoredump_free); -} -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h index 60522963aaca..b11d190ece53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h @@ -32,6 +32,7 @@ enum AMDGPU_RESET_FLAGS { AMDGPU_NEED_FULL_RESET = 0, AMDGPU_SKIP_HW_RESET = 1, + AMDGPU_SKIP_COREDUMP = 2, }; struct amdgpu_reset_context { @@ -88,19 +89,6 @@ struct amdgpu_reset_domain { atomic_t reset_res; }; -#ifdef CONFIG_DEV_COREDUMP - -#define AMDGPU_COREDUMP_VERSION "1" - -struct amdgpu_coredump_info { - struct amdgpu_device *adev; - struct amdgpu_task_info reset_task_info; - struct timespec64 reset_time; - bool reset_vram_lost; - struct amdgpu_ring *ring; -}; -#endif - int amdgpu_reset_init(struct amdgpu_device *adev); int amdgpu_reset_fini(struct amdgpu_device *adev); @@ -141,9 +129,6 @@ void amdgpu_device_lock_reset_domain(struct amdgpu_reset_domain *reset_domain); void amdgpu_device_unlock_reset_domain(struct amdgpu_reset_domain *reset_domain); -void amdgpu_coredump(struct amdgpu_device *adev, bool vram_lost, - struct amdgpu_reset_context *reset_context); - #define for_each_handler(i, handler, reset_ctl) \ for (i = 0; (i < AMDGPU_RESET_MAX_HANDLERS) && \ (handler = (*reset_ctl->reset_handlers)[i]); \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h index 173a2a308078..b51a82e711df 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h @@ -132,7 +132,7 @@ struct amdgpu_buffer_funcs { uint64_t dst_offset, /* number of byte to transfer */ uint32_t byte_count, - bool tmz); + uint32_t copy_flags); /* maximum bytes in a single operation */ uint32_t fill_max_bytes; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h index ff4435181055..ec9d12f85f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_smuio.h @@ -44,6 +44,7 @@ struct amdgpu_smuio_funcs { u32 (*get_socket_id)(struct amdgpu_device *adev); enum amdgpu_pkg_type (*get_pkg_type)(struct amdgpu_device *adev); bool (*is_host_gpu_xgmi_supported)(struct amdgpu_device *adev); + u64 (*get_gpu_clock_counter)(struct amdgpu_device *adev); }; struct amdgpu_smuio { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fc418e670fda..3749892bf702 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -133,7 +133,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && - amdgpu_bo_in_cpu_visible_vram(abo)) { + amdgpu_res_cpu_visible(adev, bo->resource)) { /* Try evicting to the CPU inaccessible part of VRAM * first, but only set GTT as busy placement, so this @@ -236,7 +236,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); dst_addr += window * AMDGPU_GTT_MAX_TRANSFER_SIZE * 8; amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, - dst_addr, num_bytes, false); + dst_addr, num_bytes, 0); amdgpu_ring_pad_ib(ring, &job->ibs[0]); WARN_ON(job->ibs[0].length_dw > num_dw); @@ -296,6 +296,8 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, struct dma_fence *fence = NULL; int r = 0; + uint32_t copy_flags = 0; + if (!adev->mman.buffer_funcs_enabled) { DRM_ERROR("Trying to move memory with ring turned off.\n"); return -EINVAL; @@ -323,8 +325,11 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, if (r) goto error; - r = amdgpu_copy_buffer(ring, from, to, cur_size, - resv, &next, false, true, tmz); + if (tmz) + copy_flags |= AMDGPU_COPY_FLAGS_TMZ; + + r = amdgpu_copy_buffer(ring, from, to, cur_size, resv, + &next, false, true, copy_flags); if (r) goto error; @@ -378,11 +383,12 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, (abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE)) { struct dma_fence *wipe_fence = NULL; - r = amdgpu_fill_buffer(abo, AMDGPU_POISON, NULL, &wipe_fence, - false); + r = amdgpu_fill_buffer(abo, 0, NULL, &wipe_fence, + false); if (r) { goto error; } else if (wipe_fence) { + amdgpu_vram_mgr_set_cleared(bo->resource); dma_fence_put(fence); fence = wipe_fence; } @@ -403,40 +409,55 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, return r; } +/** + * amdgpu_res_cpu_visible - Check that resource can be accessed by CPU + * @adev: amdgpu device + * @res: the resource to check + * + * Returns: true if the full resource is CPU visible, false otherwise. + */ +bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, + struct ttm_resource *res) +{ + struct amdgpu_res_cursor cursor; + + if (!res) + return false; + + if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT || + res->mem_type == AMDGPU_PL_PREEMPT) + return true; + + if (res->mem_type != TTM_PL_VRAM) + return false; + + amdgpu_res_first(res, 0, res->size, &cursor); + while (cursor.remaining) { + if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size) + return false; + amdgpu_res_next(&cursor, cursor.size); + } + + return true; +} + /* - * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy + * amdgpu_res_copyable - Check that memory can be accessed by ttm_bo_move_memcpy * * Called by amdgpu_bo_move() */ -static bool amdgpu_mem_visible(struct amdgpu_device *adev, - struct ttm_resource *mem) +static bool amdgpu_res_copyable(struct amdgpu_device *adev, + struct ttm_resource *mem) { - u64 mem_size = (u64)mem->size; - struct amdgpu_res_cursor cursor; - u64 end; - - if (mem->mem_type == TTM_PL_SYSTEM || - mem->mem_type == TTM_PL_TT) - return true; - if (mem->mem_type != TTM_PL_VRAM) + if (!amdgpu_res_cpu_visible(adev, mem)) return false; - amdgpu_res_first(mem, 0, mem_size, &cursor); - end = cursor.start + cursor.size; - while (cursor.remaining) { - amdgpu_res_next(&cursor, cursor.size); + /* ttm_resource_ioremap only supports contiguous memory */ + if (mem->mem_type == TTM_PL_VRAM && + !(mem->placement & TTM_PL_FLAG_CONTIGUOUS)) + return false; - if (!cursor.remaining) - break; - - /* ttm_resource_ioremap only supports contiguous memory */ - if (end != cursor.start) - return false; - - end = cursor.start + cursor.size; - } - - return end <= adev->gmc.visible_vram_size; + return true; } /* @@ -529,8 +550,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, if (r) { /* Check that all memory is CPU accessible */ - if (!amdgpu_mem_visible(adev, old_mem) || - !amdgpu_mem_visible(adev, new_mem)) { + if (!amdgpu_res_copyable(adev, old_mem) || + !amdgpu_res_copyable(adev, new_mem)) { pr_err("Move buffer fallback to memcpy unavailable\n"); return r; } @@ -557,7 +578,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - size_t bus_size = (size_t)mem->size; switch (mem->mem_type) { case TTM_PL_SYSTEM: @@ -568,9 +588,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev, break; case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; - /* check if it's visible */ - if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size) - return -EINVAL; if (adev->mman.aper_base_kaddr && mem->placement & TTM_PL_FLAG_CONTIGUOUS) @@ -1477,7 +1494,7 @@ static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo, swap(src_addr, dst_addr); amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, - PAGE_SIZE, false); + PAGE_SIZE, 0); amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]); WARN_ON(job->ibs[0].length_dw > num_dw); @@ -2128,7 +2145,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, struct dma_fence **fence, bool direct_submit, - bool vm_needs_flush, bool tmz) + bool vm_needs_flush, uint32_t copy_flags) { struct amdgpu_device *adev = ring->adev; unsigned int num_loops, num_dw; @@ -2154,8 +2171,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint32_t cur_size_in_bytes = min(byte_count, max_bytes); amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_offset, - dst_offset, cur_size_in_bytes, tmz); - + dst_offset, cur_size_in_bytes, copy_flags); src_offset += cur_size_in_bytes; dst_offset += cur_size_in_bytes; byte_count -= cur_size_in_bytes; @@ -2215,6 +2231,71 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data, return 0; } +/** + * amdgpu_ttm_clear_buffer - clear memory buffers + * @bo: amdgpu buffer object + * @resv: reservation object + * @fence: dma_fence associated with the operation + * + * Clear the memory buffer resource. + * + * Returns: + * 0 for success or a negative error code on failure. + */ +int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, + struct dma_resv *resv, + struct dma_fence **fence) +{ + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + struct amdgpu_res_cursor cursor; + u64 addr; + int r; + + if (!adev->mman.buffer_funcs_enabled) + return -EINVAL; + + if (!fence) + return -EINVAL; + + *fence = dma_fence_get_stub(); + + amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); + + mutex_lock(&adev->mman.gtt_window_lock); + while (cursor.remaining) { + struct dma_fence *next = NULL; + u64 size; + + if (amdgpu_res_cleared(&cursor)) { + amdgpu_res_next(&cursor, cursor.size); + continue; + } + + /* Never clear more than 256MiB at once to avoid timeouts */ + size = min(cursor.size, 256ULL << 20); + + r = amdgpu_ttm_map_buffer(&bo->tbo, bo->tbo.resource, &cursor, + 1, ring, false, &size, &addr); + if (r) + goto err; + + r = amdgpu_ttm_fill_mem(ring, 0, addr, size, resv, + &next, true, true); + if (r) + goto err; + + dma_fence_put(*fence); + *fence = next; + + amdgpu_res_next(&cursor, size); + } +err: + mutex_unlock(&adev->mman.gtt_window_lock); + + return r; +} + int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 65ec82141a8e..b6f53129dea3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -38,8 +38,6 @@ #define AMDGPU_GTT_MAX_TRANSFER_SIZE 512 #define AMDGPU_GTT_NUM_TRANSFER_WINDOWS 2 -#define AMDGPU_POISON 0xd0bed0be - extern const struct attribute_group amdgpu_vram_mgr_attr_group; extern const struct attribute_group amdgpu_gtt_mgr_attr_group; @@ -111,6 +109,8 @@ struct amdgpu_copy_mem { unsigned long offset; }; +#define AMDGPU_COPY_FLAGS_TMZ (1 << 0) + int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size); void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev); int amdgpu_preempt_mgr_init(struct amdgpu_device *adev); @@ -139,6 +139,9 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr, int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr, uint64_t start); +bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, + struct ttm_resource *res); + int amdgpu_ttm_init(struct amdgpu_device *adev); void amdgpu_ttm_fini(struct amdgpu_device *adev); void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, @@ -148,13 +151,16 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, struct dma_fence **fence, bool direct_submit, - bool vm_needs_flush, bool tmz); + bool vm_needs_flush, uint32_t copy_flags); int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, const struct amdgpu_copy_mem *src, const struct amdgpu_copy_mem *dst, uint64_t size, bool tmz, struct dma_resv *resv, struct dma_fence **f); +int amdgpu_ttm_clear_buffer(struct amdgpu_bo *bo, + struct dma_resv *resv, + struct dma_fence **fence); int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 619445760037..105d4de0613a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -125,6 +125,7 @@ enum psp_fw_type { PSP_FW_TYPE_PSP_INTF_DRV, PSP_FW_TYPE_PSP_DBG_DRV, PSP_FW_TYPE_PSP_RAS_DRV, + PSP_FW_TYPE_PSP_IPKEYMGR_DRV, PSP_FW_TYPE_MAX_INDEX, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index 20436f81856a..540e0f066b26 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -21,10 +21,13 @@ * */ +#include #include "amdgpu.h" #include "umc_v6_7.h" #define MAX_UMC_POISON_POLLING_TIME_SYNC 20 //ms +#define MAX_UMC_HASH_STRING_SIZE 256 + static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev, struct ras_err_data *err_data, uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst) @@ -63,6 +66,8 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev, goto out_fini_err_data; } + err_data.err_addr_len = adev->umc.max_ras_err_cnt_per_query; + /* * Translate UMC channel address to Physical address */ @@ -86,7 +91,7 @@ int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev, return ret; } -static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, +void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, void *ras_error_status) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; @@ -118,6 +123,8 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, if(!err_data->err_addr) dev_warn(adev->dev, "Failed to alloc memory for " "umc error address record!\n"); + else + err_data->err_addr_len = adev->umc.max_ras_err_cnt_per_query; /* umc query_ras_error_address is also responsible for clearing * error status @@ -143,6 +150,8 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, if(!err_data->err_addr) dev_warn(adev->dev, "Failed to alloc memory for " "umc error address record!\n"); + else + err_data->err_addr_len = adev->umc.max_ras_err_cnt_per_query; /* umc query_ras_error_address is also responsible for clearing * error status @@ -170,6 +179,7 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, } kfree(err_data->err_addr); + err_data->err_addr = NULL; mutex_unlock(&con->page_retirement_lock); } @@ -177,7 +187,7 @@ static void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, void *ras_error_status, struct amdgpu_iv_entry *entry, - bool reset) + uint32_t reset) { struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -186,9 +196,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, amdgpu_umc_handle_bad_pages(adev, ras_error_status); if (err_data->ue_count && reset) { - /* use mode-2 reset for poison consumption */ - if (!entry) - con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET; + con->gpu_reset_flags |= reset; amdgpu_ras_reset_gpu(adev); } @@ -196,7 +204,7 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev, } int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev, - bool reset, uint32_t timeout_ms) + uint32_t reset, uint32_t timeout_ms) { struct ras_err_data err_data; struct ras_common_if head = { @@ -238,16 +246,16 @@ int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev, if (reset) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - /* use mode-2 reset for poison consumption */ - con->gpu_reset_flags |= AMDGPU_RAS_GPU_RESET_MODE2_RESET; + con->gpu_reset_flags |= reset; amdgpu_ras_reset_gpu(adev); } return 0; } -int amdgpu_umc_poison_handler(struct amdgpu_device *adev, - enum amdgpu_ras_block block, bool reset) +int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset) { int ret = AMDGPU_RAS_SUCCESS; @@ -285,16 +293,14 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, amdgpu_ras_error_data_fini(&err_data); } else { - if (reset) { - amdgpu_umc_bad_page_polling_timeout(adev, - reset, MAX_UMC_POISON_POLLING_TIME_SYNC); - } else { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + amdgpu_ras_put_poison_req(adev, + block, pasid, pasid_fn, data, reset); + atomic_inc(&con->page_retirement_req_cnt); wake_up(&con->page_retirement_wq); - } } } else { if (adev->virt.ops && adev->virt.ops->ras_poison_handler) @@ -307,11 +313,19 @@ int amdgpu_umc_poison_handler(struct amdgpu_device *adev, return ret; } +int amdgpu_umc_poison_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint32_t reset) +{ + return amdgpu_umc_pasid_poison_handler(adev, + block, 0, NULL, NULL, reset); +} + int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, void *ras_error_status, struct amdgpu_iv_entry *entry) { - return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, true); + return amdgpu_umc_do_page_retirement(adev, ras_error_status, entry, + AMDGPU_RAS_GPU_RESET_MODE1_RESET); } int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev) @@ -388,14 +402,20 @@ int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, return 0; } -void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, +int amdgpu_umc_fill_error_record(struct ras_err_data *err_data, uint64_t err_addr, uint64_t retired_page, uint32_t channel_index, uint32_t umc_inst) { - struct eeprom_table_record *err_rec = - &err_data->err_addr[err_data->err_addr_cnt]; + struct eeprom_table_record *err_rec; + + if (!err_data || + !err_data->err_addr || + (err_data->err_addr_cnt >= err_data->err_addr_len)) + return -EINVAL; + + err_rec = &err_data->err_addr[err_data->err_addr_cnt]; err_rec->address = err_addr; /* page frame address is saved */ @@ -407,6 +427,8 @@ void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, err_rec->mcumc_id = umc_inst; err_data->err_addr_cnt++; + + return 0; } int amdgpu_umc_loop_channels(struct amdgpu_device *adev, @@ -439,3 +461,76 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev, return 0; } + +int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev, + uint64_t status, uint64_t ipid, uint64_t addr) +{ + if (adev->umc.ras->update_ecc_status) + return adev->umc.ras->update_ecc_status(adev, + status, ipid, addr); + return 0; +} + +static int amdgpu_umc_uint64_cmp(const void *a, const void *b) +{ + uint64_t *addr_a = (uint64_t *)a; + uint64_t *addr_b = (uint64_t *)b; + + if (*addr_a > *addr_b) + return 1; + else if (*addr_a < *addr_b) + return -1; + else + return 0; +} + +/* Use string hash to avoid logging the same bad pages repeatedly */ +int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev, + uint64_t *pfns, int len, uint64_t *val) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + char buf[MAX_UMC_HASH_STRING_SIZE] = {0}; + int offset = 0, i = 0; + uint64_t hash_val; + + if (!pfns || !len) + return -EINVAL; + + sort(pfns, len, sizeof(uint64_t), amdgpu_umc_uint64_cmp, NULL); + + for (i = 0; i < len; i++) + offset += snprintf(&buf[offset], sizeof(buf) - offset, "%llx", pfns[i]); + + hash_val = siphash(buf, offset, &con->umc_ecc_log.ecc_key); + + *val = hash_val; + + return 0; +} + +int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev, + struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_ecc_log_info *ecc_log; + int ret; + + ecc_log = &con->umc_ecc_log; + + mutex_lock(&ecc_log->lock); + ret = radix_tree_insert(ecc_tree, ecc_err->hash_index, ecc_err); + if (!ret) { + struct ras_err_pages *err_pages = &ecc_err->err_pages; + int i; + + /* Reserve memory */ + for (i = 0; i < err_pages->count; i++) + amdgpu_ras_reserve_page(adev, err_pages->pfn[i]); + + radix_tree_tag_set(ecc_tree, + ecc_err->hash_index, UMC_ECC_NEW_DETECTED_TAG); + } + mutex_unlock(&ecc_log->lock); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 26d2ae498daf..5f50c69c3cec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -52,6 +52,8 @@ #define LOOP_UMC_EACH_NODE_INST_AND_CH(node_inst, umc_inst, ch_inst) \ LOOP_UMC_NODE_INST((node_inst)) LOOP_UMC_INST_AND_CH((umc_inst), (ch_inst)) +/* Page retirement tag */ +#define UMC_ECC_NEW_DETECTED_TAG 0x1 typedef int (*umc_func)(struct amdgpu_device *adev, uint32_t node_inst, uint32_t umc_inst, uint32_t ch_inst, void *data); @@ -66,8 +68,8 @@ struct amdgpu_umc_ras { void *ras_error_status); bool (*check_ecc_err_status)(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, void *ras_error_status); - /* support different eeprom table version for different asic */ - void (*set_eeprom_table_version)(struct amdgpu_ras_eeprom_table_header *hdr); + int (*update_ecc_status)(struct amdgpu_device *adev, + uint64_t status, uint64_t ipid, uint64_t addr); }; struct amdgpu_umc_funcs { @@ -103,11 +105,14 @@ struct amdgpu_umc { int amdgpu_umc_ras_sw_init(struct amdgpu_device *adev); int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block); int amdgpu_umc_poison_handler(struct amdgpu_device *adev, - enum amdgpu_ras_block block, bool reset); + enum amdgpu_ras_block block, uint32_t reset); +int amdgpu_umc_pasid_poison_handler(struct amdgpu_device *adev, + enum amdgpu_ras_block block, uint16_t pasid, + pasid_notify pasid_fn, void *data, uint32_t reset); int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); -void amdgpu_umc_fill_error_record(struct ras_err_data *err_data, +int amdgpu_umc_fill_error_record(struct ras_err_data *err_data, uint64_t err_addr, uint64_t retired_page, uint32_t channel_index, @@ -123,5 +128,15 @@ int amdgpu_umc_loop_channels(struct amdgpu_device *adev, umc_func func, void *data); int amdgpu_umc_bad_page_polling_timeout(struct amdgpu_device *adev, - bool reset, uint32_t timeout_ms); + uint32_t reset, uint32_t timeout_ms); + +int amdgpu_umc_update_ecc_status(struct amdgpu_device *adev, + uint64_t status, uint64_t ipid, uint64_t addr); +int amdgpu_umc_build_pages_hash(struct amdgpu_device *adev, + uint64_t *pfns, int len, uint64_t *val); +int amdgpu_umc_logs_ecc_err(struct amdgpu_device *adev, + struct radix_tree_root *ecc_tree, struct ras_ecc_err *ecc_err); + +void amdgpu_umc_handle_bad_pages(struct amdgpu_device *adev, + void *ras_error_status); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c index 0df97c3e3a70..e01c1c8e64c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c @@ -774,6 +774,9 @@ static int umsch_mm_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend) + return 0; + return umsch_mm_test(adev); } @@ -875,6 +878,8 @@ static const struct amd_ip_funcs umsch_mm_v4_0_ip_funcs = { .hw_fini = umsch_mm_hw_fini, .suspend = umsch_mm_suspend, .resume = umsch_mm_resume, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version umsch_mm_v4_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 59acf424a078..968ca2c84ef7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -743,7 +743,8 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t created = 0; uint32_t allocated = 0; uint32_t tmp, handle = 0; - uint32_t *size = &tmp; + uint32_t dummy = 0xffffffff; + uint32_t *size = &dummy; unsigned int idx; int i, r = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index 9c514a606a2f..677eb141554e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -93,7 +93,7 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work); int amdgpu_vcn_early_init(struct amdgpu_device *adev) { - char ucode_prefix[30]; + char ucode_prefix[25]; char fw_name[40]; int r, i; @@ -185,7 +185,10 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev) if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8); - if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { + if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) { + fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)); + log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log); + } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) { fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)); log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log); } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index a418393d89ec..9f06def236fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -454,6 +454,16 @@ struct amdgpu_vcn_rb_metadata { uint8_t pad[26]; }; +struct amdgpu_vcn5_fw_shared { + uint32_t present_flag_0; + uint8_t pad[12]; + struct amdgpu_fw_shared_unified_queue_struct sq; + uint8_t pad1[8]; + struct amdgpu_fw_shared_fw_logging fw_log; + struct amdgpu_fw_shared_rb_setup rb_setup; + uint8_t pad2[4]; +}; + #define VCN_BLOCK_ENCODE_DISABLE_MASK 0x80 #define VCN_BLOCK_DECODE_DISABLE_MASK 0x40 #define VCN_BLOCK_QUEUE_DISABLE_MASK 0xC0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 7a4eae36778a..54ab51a4ada7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -32,6 +32,7 @@ #include "amdgpu.h" #include "amdgpu_ras.h" +#include "amdgpu_reset.h" #include "vi.h" #include "soc15.h" #include "nv.h" @@ -424,7 +425,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) return -EINVAL; if (pf2vf_info->size > 1024) { - DRM_ERROR("invalid pf2vf message size\n"); + dev_err(adev->dev, "invalid pf2vf message size: 0x%x\n", pf2vf_info->size); return -EINVAL; } @@ -435,7 +436,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, adev->virt.fw_reserve.checksum_key, checksum); if (checksum != checkval) { - DRM_ERROR("invalid pf2vf message\n"); + dev_err(adev->dev, + "invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n", + checksum, checkval); return -EINVAL; } @@ -449,7 +452,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) adev->virt.fw_reserve.p_pf2vf, pf2vf_info->size, 0, checksum); if (checksum != checkval) { - DRM_ERROR("invalid pf2vf message\n"); + dev_err(adev->dev, + "invalid pf2vf message: header checksum=0x%x calculated checksum=0x%x\n", + checksum, checkval); return -EINVAL; } @@ -485,7 +490,7 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev) ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->uuid; break; default: - DRM_ERROR("invalid pf2vf version\n"); + dev_err(adev->dev, "invalid pf2vf version: 0x%x\n", pf2vf_info->version); return -EINVAL; } @@ -571,6 +576,11 @@ static int amdgpu_virt_write_vf2pf_data(struct amdgpu_device *adev) vf2pf_info->decode_usage = 0; vf2pf_info->dummy_page_addr = (uint64_t)adev->dummy_page_addr; + vf2pf_info->mes_info_addr = (uint64_t)adev->mes.resource_1_gpu_addr; + + if (adev->mes.resource_1) { + vf2pf_info->mes_info_size = adev->mes.resource_1->tbo.base.size; + } vf2pf_info->checksum = amd_sriov_msg_checksum( vf2pf_info, vf2pf_info->header.size, 0, 0); @@ -584,8 +594,22 @@ static void amdgpu_virt_update_vf2pf_work_item(struct work_struct *work) int ret; ret = amdgpu_virt_read_pf2vf_data(adev); - if (ret) + if (ret) { + adev->virt.vf2pf_update_retry_cnt++; + if ((adev->virt.vf2pf_update_retry_cnt >= AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT) && + amdgpu_sriov_runtime(adev) && !amdgpu_in_reset(adev)) { + amdgpu_ras_set_fed(adev, true); + if (amdgpu_reset_domain_schedule(adev->reset_domain, + &adev->virt.flr_work)) + return; + else + dev_err(adev->dev, "Failed to queue work! at %s", __func__); + } + goto out; + } + + adev->virt.vf2pf_update_retry_cnt = 0; amdgpu_virt_write_vf2pf_data(adev); out: @@ -606,6 +630,7 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) adev->virt.fw_reserve.p_pf2vf = NULL; adev->virt.fw_reserve.p_vf2pf = NULL; adev->virt.vf2pf_update_interval_ms = 0; + adev->virt.vf2pf_update_retry_cnt = 0; if (adev->mman.fw_vram_usage_va && adev->mman.drv_vram_usage_va) { DRM_WARN("Currently fw_vram and drv_vram should not have values at the same time!"); @@ -705,12 +730,6 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev) adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE; } - if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID) - /* VF MMIO access (except mailbox range) from CPU - * will be blocked during sriov runtime - */ - adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT; - /* we have the ability to check now */ if (amdgpu_sriov_vf(adev)) { switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 3f59b7b5523f..642f1fd287d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -52,6 +52,8 @@ /* tonga/fiji use this offset */ #define mmBIF_IOV_FUNC_IDENTIFIER 0x1503 +#define AMDGPU_VF2PF_UPDATE_MAX_RETRY_LIMIT 5 + enum amdgpu_sriov_vf_mode { SRIOV_VF_MODE_BARE_METAL = 0, SRIOV_VF_MODE_ONE_VF, @@ -130,6 +132,8 @@ enum AMDGIM_FEATURE_FLAG { AMDGIM_FEATURE_AV1_SUPPORT = (1 << 6), /* VCN RB decouple */ AMDGIM_FEATURE_VCN_RB_DECOUPLE = (1 << 7), + /* MES info */ + AMDGIM_FEATURE_MES_INFO_ENABLE = (1 << 8), }; enum AMDGIM_REG_ACCESS_FLAG { @@ -257,6 +261,7 @@ struct amdgpu_virt { /* vf2pf message */ struct delayed_work vf2pf_work; uint32_t vf2pf_update_interval_ms; + int vf2pf_update_retry_cnt; /* multimedia bandwidth config */ bool is_mm_bw_enabled; @@ -332,6 +337,8 @@ static inline bool is_virtual_machine(void) ((adev)->virt.gim_feature & AMDGIM_FEATURE_AV1_SUPPORT) #define amdgpu_sriov_is_vcn_rb_decouple(adev) \ ((adev)->virt.gim_feature & AMDGIM_FEATURE_VCN_RB_DECOUPLE) +#define amdgpu_sriov_is_mes_info_enable(adev) \ + ((adev)->virt.gim_feature & AMDGIM_FEATURE_MES_INFO_ENABLE) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c index 8baa2e0935cc..e30eecd02ae1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c @@ -658,6 +658,8 @@ static const struct amd_ip_funcs amdgpu_vkms_ip_funcs = { .soft_reset = amdgpu_vkms_soft_reset, .set_clockgating_state = amdgpu_vkms_set_clockgating_state, .set_powergating_state = amdgpu_vkms_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version amdgpu_vkms_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4299ce386322..4e2391c83d7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -885,6 +885,44 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence, kfree(tlb_cb); } +/** + * amdgpu_vm_tlb_flush - prepare TLB flush + * + * @params: parameters for update + * @fence: input fence to sync TLB flush with + * @tlb_cb: the callback structure + * + * Increments the tlb sequence to make sure that future CS execute a VM flush. + */ +static void +amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params, + struct dma_fence **fence, + struct amdgpu_vm_tlb_seq_struct *tlb_cb) +{ + struct amdgpu_vm *vm = params->vm; + + if (!fence || !*fence) + return; + + tlb_cb->vm = vm; + if (!dma_fence_add_callback(*fence, &tlb_cb->cb, + amdgpu_vm_tlb_seq_cb)) { + dma_fence_put(vm->last_tlb_flush); + vm->last_tlb_flush = dma_fence_get(*fence); + } else { + amdgpu_vm_tlb_seq_cb(NULL, &tlb_cb->cb); + } + + /* Prepare a TLB flush fence to be attached to PTs */ + if (!params->unlocked && vm->is_compute_context) { + amdgpu_vm_tlb_fence_create(params->adev, vm, fence); + + /* Makes sure no PD/PT is freed before the flush */ + dma_resv_add_fence(vm->root.bo->tbo.base.resv, *fence, + DMA_RESV_USAGE_BOOKKEEP); + } +} + /** * amdgpu_vm_update_range - update a range in the vm page table * @@ -916,8 +954,8 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct ttm_resource *res, dma_addr_t *pages_addr, struct dma_fence **fence) { - struct amdgpu_vm_update_params params; struct amdgpu_vm_tlb_seq_struct *tlb_cb; + struct amdgpu_vm_update_params params; struct amdgpu_res_cursor cursor; enum amdgpu_sync_mode sync_mode; int r, idx; @@ -927,8 +965,8 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, tlb_cb = kmalloc(sizeof(*tlb_cb), GFP_KERNEL); if (!tlb_cb) { - r = -ENOMEM; - goto error_unlock; + drm_dev_exit(idx); + return -ENOMEM; } /* Vega20+XGMI where PTEs get inadvertently cached in L2 texture cache, @@ -948,7 +986,9 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, params.immediate = immediate; params.pages_addr = pages_addr; params.unlocked = unlocked; + params.needs_flush = flush_tlb; params.allow_override = allow_override; + INIT_LIST_HEAD(¶ms.tlb_flush_waitlist); /* Implicitly sync to command submissions in the same VM before * unmapping. Sync to moving fences before mapping. @@ -1031,24 +1071,18 @@ int amdgpu_vm_update_range(struct amdgpu_device *adev, struct amdgpu_vm *vm, } r = vm->update_funcs->commit(¶ms, fence); + if (r) + goto error_free; - if (flush_tlb || params.table_freed) { - tlb_cb->vm = vm; - if (fence && *fence && - !dma_fence_add_callback(*fence, &tlb_cb->cb, - amdgpu_vm_tlb_seq_cb)) { - dma_fence_put(vm->last_tlb_flush); - vm->last_tlb_flush = dma_fence_get(*fence); - } else { - amdgpu_vm_tlb_seq_cb(NULL, &tlb_cb->cb); - } + if (params.needs_flush) { + amdgpu_vm_tlb_flush(¶ms, fence, tlb_cb); tlb_cb = NULL; } + amdgpu_vm_pt_free_list(adev, ¶ms); + error_free: kfree(tlb_cb); - -error_unlock: amdgpu_vm_eviction_unlock(vm); drm_dev_exit(idx); return r; @@ -1613,6 +1647,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, trace_amdgpu_vm_bo_map(bo_va, mapping); } +/* Validate operation parameters to prevent potential abuse */ +static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev, + struct amdgpu_bo *bo, + uint64_t saddr, + uint64_t offset, + uint64_t size) +{ + uint64_t tmp, lpfn; + + if (saddr & AMDGPU_GPU_PAGE_MASK + || offset & AMDGPU_GPU_PAGE_MASK + || size & AMDGPU_GPU_PAGE_MASK) + return -EINVAL; + + if (check_add_overflow(saddr, size, &tmp) + || check_add_overflow(offset, size, &tmp) + || size == 0 /* which also leads to end < begin */) + return -EINVAL; + + /* make sure object fit at this offset */ + if (bo && offset + size > amdgpu_bo_size(bo)) + return -EINVAL; + + /* Ensure last pfn not exceed max_pfn */ + lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT; + if (lpfn >= adev->vm_manager.max_pfn) + return -EINVAL; + + return 0; +} + /** * amdgpu_vm_bo_map - map bo inside a vm * @@ -1639,21 +1704,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, struct amdgpu_bo *bo = bo_va->base.bo; struct amdgpu_vm *vm = bo_va->base.vm; uint64_t eaddr; + int r; - /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) - return -EINVAL; - if (saddr + size <= saddr || offset + size <= offset) - return -EINVAL; - - /* make sure object fit at this offset */ - eaddr = saddr + size - 1; - if ((bo && offset + size > amdgpu_bo_size(bo)) || - (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) - return -EINVAL; + r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size); + if (r) + return r; saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr); if (tmp) { @@ -1706,17 +1764,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, uint64_t eaddr; int r; - /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) - return -EINVAL; - if (saddr + size <= saddr || offset + size <= offset) - return -EINVAL; - - /* make sure object fit at this offset */ - eaddr = saddr + size - 1; - if ((bo && offset + size > amdgpu_bo_size(bo)) || - (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) - return -EINVAL; + r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size); + if (r) + return r; /* Allocate all the needed memory */ mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); @@ -1730,7 +1780,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, } saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; mapping->start = saddr; mapping->last = eaddr; @@ -1817,10 +1867,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *before, *after, *tmp, *next; LIST_HEAD(removed); uint64_t eaddr; + int r; + + r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size); + if (r) + return r; - eaddr = saddr + size - 1; saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; /* Allocate all the needed memory */ before = kzalloc(sizeof(*before), GFP_KERNEL); @@ -2391,6 +2445,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, mutex_init(&vm->eviction_lock); vm->evicting = false; + vm->tlb_fence_context = dma_fence_context_alloc(1); r = amdgpu_vm_pt_create(adev, vm, adev->vm_manager.root_level, false, &root, xcp_id); @@ -2924,6 +2979,14 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev, if (vm && status) { vm->fault_info.addr = addr; vm->fault_info.status = status; + /* + * Update the fault information globally for later usage + * when vm could be stale or freed. + */ + adev->vm_manager.fault_info.addr = addr; + adev->vm_manager.fault_info.vmhub = vmhub; + adev->vm_manager.fault_info.status = status; + if (AMDGPU_IS_GFXHUB(vmhub)) { vm->fault_info.vmhub = AMDGPU_VMHUB_TYPE_GFX; vm->fault_info.vmhub |= diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 047ec1930d12..54d7da396de0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -257,15 +257,20 @@ struct amdgpu_vm_update_params { unsigned int num_dw_left; /** - * @table_freed: return true if page table is freed when updating + * @needs_flush: true whenever we need to invalidate the TLB */ - bool table_freed; + bool needs_flush; /** * @allow_override: true for memory that is not uncached: allows MTYPE * to be overridden for NUMA local memory. */ bool allow_override; + + /** + * @tlb_flush_waitlist: temporary storage for BOs until tlb_flush + */ + struct list_head tlb_flush_waitlist; }; struct amdgpu_vm_update_funcs { @@ -342,6 +347,7 @@ struct amdgpu_vm { atomic64_t tlb_seq; struct dma_fence *last_tlb_flush; atomic64_t kfd_last_flushed_seq; + uint64_t tlb_fence_context; /* How many times we had to re-generate the page tables */ uint64_t generation; @@ -422,6 +428,8 @@ struct amdgpu_vm_manager { * look up VM of a page fault */ struct xarray pasids; + /* Global registration of recent page fault information */ + struct amdgpu_vm_fault_info fault_info; }; struct amdgpu_bo_va_mapping; @@ -544,6 +552,8 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params, uint64_t start, uint64_t end, uint64_t dst, uint64_t flags); void amdgpu_vm_pt_free_work(struct work_struct *work); +void amdgpu_vm_pt_free_list(struct amdgpu_device *adev, + struct amdgpu_vm_update_params *params); #if defined(CONFIG_DEBUG_FS) void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m); @@ -609,5 +619,8 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device *adev, uint64_t addr, uint32_t status, unsigned int vmhub); +void amdgpu_vm_tlb_fence_create(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct dma_fence **fence); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c index 6e31621452de..3895bd7d176a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c @@ -108,7 +108,9 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p, static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p, struct dma_fence **fence) { - /* Flush HDP */ + if (p->needs_flush) + atomic64_inc(&p->vm->tlb_seq); + mb(); amdgpu_device_flush_hdp(p->adev, NULL); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c index 124389a6bf48..7fdd306a48a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c @@ -622,40 +622,58 @@ void amdgpu_vm_pt_free_work(struct work_struct *work) } /** - * amdgpu_vm_pt_free_dfs - free PD/PT levels + * amdgpu_vm_pt_free_list - free PD/PT levels * * @adev: amdgpu device structure - * @vm: amdgpu vm structure - * @start: optional cursor where to start freeing PDs/PTs - * @unlocked: vm resv unlock status + * @params: see amdgpu_vm_update_params definition * - * Free the page directory or page table level and all sub levels. + * Free the page directory objects saved in the flush list */ -static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_vm_pt_cursor *start, - bool unlocked) +void amdgpu_vm_pt_free_list(struct amdgpu_device *adev, + struct amdgpu_vm_update_params *params) { - struct amdgpu_vm_pt_cursor cursor; - struct amdgpu_vm_bo_base *entry; + struct amdgpu_vm_bo_base *entry, *next; + struct amdgpu_vm *vm = params->vm; + bool unlocked = params->unlocked; + + if (list_empty(¶ms->tlb_flush_waitlist)) + return; if (unlocked) { spin_lock(&vm->status_lock); - for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) - list_move(&entry->vm_status, &vm->pt_freed); - - if (start) - list_move(&start->entry->vm_status, &vm->pt_freed); + list_splice_init(¶ms->tlb_flush_waitlist, &vm->pt_freed); spin_unlock(&vm->status_lock); schedule_work(&vm->pt_free_work); return; } - for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) + list_for_each_entry_safe(entry, next, ¶ms->tlb_flush_waitlist, vm_status) amdgpu_vm_pt_free(entry); +} - if (start) - amdgpu_vm_pt_free(start->entry); +/** + * amdgpu_vm_pt_add_list - add PD/PT level to the flush list + * + * @params: parameters for the update + * @cursor: first PT entry to start DF search from, non NULL + * + * This list will be freed after TLB flush. + */ +static void amdgpu_vm_pt_add_list(struct amdgpu_vm_update_params *params, + struct amdgpu_vm_pt_cursor *cursor) +{ + struct amdgpu_vm_pt_cursor seek; + struct amdgpu_vm_bo_base *entry; + + spin_lock(¶ms->vm->status_lock); + for_each_amdgpu_vm_pt_dfs_safe(params->adev, params->vm, cursor, seek, entry) { + if (entry && entry->bo) + list_move(&entry->vm_status, ¶ms->tlb_flush_waitlist); + } + + /* enter start node now */ + list_move(&cursor->entry->vm_status, ¶ms->tlb_flush_waitlist); + spin_unlock(¶ms->vm->status_lock); } /** @@ -667,7 +685,13 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev, */ void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - amdgpu_vm_pt_free_dfs(adev, vm, NULL, false); + struct amdgpu_vm_pt_cursor cursor; + struct amdgpu_vm_bo_base *entry; + + for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry) { + if (entry) + amdgpu_vm_pt_free(entry); + } } /** @@ -972,10 +996,8 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params, while (cursor.pfn < frag_start) { /* Make sure previous mapping is freed */ if (cursor.entry->bo) { - params->table_freed = true; - amdgpu_vm_pt_free_dfs(adev, params->vm, - &cursor, - params->unlocked); + params->needs_flush = true; + amdgpu_vm_pt_add_list(params, &cursor); } amdgpu_vm_pt_next(adev, &cursor); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c index 349416e176a1..66e8a016126b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c @@ -126,6 +126,10 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p, WARN_ON(ib->length_dw == 0); amdgpu_ring_pad_ib(ring, ib); + + if (p->needs_flush) + atomic64_inc(&p->vm->tlb_seq); + WARN_ON(ib->length_dw > p->num_dw_left); f = amdgpu_job_submit(p->job); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_tlb_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_tlb_fence.c new file mode 100644 index 000000000000..51cddfa3f1e8 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_tlb_fence.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "amdgpu.h" +#include "amdgpu_vm.h" +#include "amdgpu_gmc.h" + +struct amdgpu_tlb_fence { + struct dma_fence base; + struct amdgpu_device *adev; + struct dma_fence *dependency; + struct work_struct work; + spinlock_t lock; + uint16_t pasid; + +}; + +static const char *amdgpu_tlb_fence_get_driver_name(struct dma_fence *fence) +{ + return "amdgpu tlb fence"; +} + +static const char *amdgpu_tlb_fence_get_timeline_name(struct dma_fence *f) +{ + return "amdgpu tlb timeline"; +} + +static void amdgpu_tlb_fence_work(struct work_struct *work) +{ + struct amdgpu_tlb_fence *f = container_of(work, typeof(*f), work); + int r; + + if (f->dependency) { + dma_fence_wait(f->dependency, false); + dma_fence_put(f->dependency); + f->dependency = NULL; + } + + r = amdgpu_gmc_flush_gpu_tlb_pasid(f->adev, f->pasid, 2, true, 0); + if (r) { + dev_err(f->adev->dev, "TLB flush failed for PASID %d.\n", + f->pasid); + dma_fence_set_error(&f->base, r); + } + + dma_fence_signal(&f->base); + dma_fence_put(&f->base); +} + +static const struct dma_fence_ops amdgpu_tlb_fence_ops = { + .use_64bit_seqno = true, + .get_driver_name = amdgpu_tlb_fence_get_driver_name, + .get_timeline_name = amdgpu_tlb_fence_get_timeline_name +}; + +void amdgpu_vm_tlb_fence_create(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct dma_fence **fence) +{ + struct amdgpu_tlb_fence *f; + + f = kmalloc(sizeof(*f), GFP_KERNEL); + if (!f) { + /* + * We can't fail since the PDEs and PTEs are already updated, so + * just block for the dependency and execute the TLB flush + */ + if (*fence) + dma_fence_wait(*fence, false); + + amdgpu_gmc_flush_gpu_tlb_pasid(adev, vm->pasid, 2, true, 0); + *fence = dma_fence_get_stub(); + return; + } + + f->adev = adev; + f->dependency = *fence; + f->pasid = vm->pasid; + INIT_WORK(&f->work, amdgpu_tlb_fence_work); + spin_lock_init(&f->lock); + + dma_fence_init(&f->base, &amdgpu_tlb_fence_ops, &f->lock, + vm->tlb_fence_context, atomic64_read(&vm->tlb_seq)); + + /* TODO: We probably need a separate wq here */ + dma_fence_get(&f->base); + schedule_work(&f->work); + + *fence = &f->base; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c index 6695481f870f..c23d97d34b7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c @@ -205,7 +205,7 @@ int amdgpu_vpe_configure_dpm(struct amdgpu_vpe *vpe) dpm_ctl &= 0xfffffffe; /* Disable DPM */ WREG32(vpe_get_reg_offset(vpe, 0, vpe->regs.dpm_enable), dpm_ctl); dev_dbg(adev->dev, "%s: disable vpe dpm\n", __func__); - return 0; + return -EINVAL; } int amdgpu_vpe_psp_update_sram(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 8db880244324..6c30eceec896 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -450,6 +450,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, { struct amdgpu_vram_mgr *mgr = to_vram_mgr(man); struct amdgpu_device *adev = to_amdgpu_device(mgr); + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); u64 vis_usage = 0, max_bytes, min_block_size; struct amdgpu_vram_mgr_resource *vres; u64 size, remaining_size, lpfn, fpfn; @@ -468,7 +469,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, if (tbo->type != ttm_bo_type_kernel) max_bytes -= AMDGPU_VM_RESERVED_VRAM; - if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) { pages_per_block = ~0ul; } else { #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -477,7 +478,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, /* default to 2MB */ pages_per_block = 2UL << (20UL - PAGE_SHIFT); #endif - pages_per_block = max_t(uint32_t, pages_per_block, + pages_per_block = max_t(u32, pages_per_block, tbo->page_alignment); } @@ -498,9 +499,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, if (place->flags & TTM_PL_FLAG_TOPDOWN) vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION; - if (place->flags & TTM_PL_FLAG_CONTIGUOUS) + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) vres->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION; + if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED) + vres->flags |= DRM_BUDDY_CLEAR_ALLOCATION; + if (fpfn || lpfn != mgr->mm.size) /* Allocate blocks in desired range */ vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; @@ -514,21 +518,31 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, else min_block_size = mgr->default_page_size; - BUG_ON(min_block_size < mm->chunk_size); - /* Limit maximum size to 2GiB due to SG table limitations */ size = min(remaining_size, 2ULL << 30); if ((size >= (u64)pages_per_block << PAGE_SHIFT) && - !(size & (((u64)pages_per_block << PAGE_SHIFT) - 1))) + !(size & (((u64)pages_per_block << PAGE_SHIFT) - 1))) min_block_size = (u64)pages_per_block << PAGE_SHIFT; + BUG_ON(min_block_size < mm->chunk_size); + r = drm_buddy_alloc_blocks(mm, fpfn, lpfn, size, min_block_size, &vres->blocks, vres->flags); + + if (unlikely(r == -ENOSPC) && pages_per_block == ~0ul && + !(place->flags & TTM_PL_FLAG_CONTIGUOUS)) { + vres->flags &= ~DRM_BUDDY_CONTIGUOUS_ALLOCATION; + pages_per_block = max_t(u32, 2UL << (20UL - PAGE_SHIFT), + tbo->page_alignment); + + continue; + } + if (unlikely(r)) goto error_free_blocks; @@ -571,7 +585,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, return 0; error_free_blocks: - drm_buddy_free_list(mm, &vres->blocks); + drm_buddy_free_list(mm, &vres->blocks, 0); mutex_unlock(&mgr->lock); error_fini: ttm_resource_fini(man, &vres->base); @@ -604,7 +618,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man, amdgpu_vram_mgr_do_reserve(man); - drm_buddy_free_list(mm, &vres->blocks); + drm_buddy_free_list(mm, &vres->blocks, vres->flags); mutex_unlock(&mgr->lock); atomic64_sub(vis_usage, &mgr->vis_usage); @@ -912,7 +926,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) kfree(rsv); list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) { - drm_buddy_free_list(&mgr->mm, &rsv->allocated); + drm_buddy_free_list(&mgr->mm, &rsv->allocated, 0); kfree(rsv); } if (!adev->gmc.is_app_apu) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h index 0e04e42cf809..b256cbc2bc27 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -53,10 +53,20 @@ static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) return (u64)PAGE_SIZE << drm_buddy_block_order(block); } +static inline bool amdgpu_vram_mgr_is_cleared(struct drm_buddy_block *block) +{ + return drm_buddy_block_is_clear(block); +} + static inline struct amdgpu_vram_mgr_resource * to_amdgpu_vram_mgr_resource(struct ttm_resource *res) { return container_of(res, struct amdgpu_vram_mgr_resource, base); } +static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res) +{ + to_amdgpu_vram_mgr_resource(res)->flags |= DRM_BUDDY_CLEARED; +} + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 20d51f6c9bb8..dd2ec48cf5c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -1035,15 +1035,16 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) return 0; } -static int xgmi_v6_4_0_aca_bank_generate_report(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data) +static int xgmi_v6_4_0_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, + enum aca_smu_type type, void *data) { struct amdgpu_device *adev = handle->adev; + struct aca_bank_info info; const char *error_str; - u64 status; + u64 status, count; int ret, ext_error_code; - ret = aca_bank_info_decode(bank, &report->info); + ret = aca_bank_info_decode(bank, &info); if (ret) return ret; @@ -1055,15 +1056,28 @@ static int xgmi_v6_4_0_aca_bank_generate_report(struct aca_handle *handle, struc if (error_str) dev_info(adev->dev, "%s detected\n", error_str); - if ((type == ACA_ERROR_TYPE_UE && ext_error_code == 0) || - (type == ACA_ERROR_TYPE_CE && ext_error_code == 6)) - report->count[type] = ACA_REG__MISC0__ERRCNT(bank->regs[ACA_REG_IDX_MISC0]); + count = ACA_REG__MISC0__ERRCNT(bank->regs[ACA_REG_IDX_MISC0]); - return 0; + switch (type) { + case ACA_SMU_TYPE_UE: + if (ext_error_code != 0 && ext_error_code != 9) + count = 0ULL; + + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE, count); + break; + case ACA_SMU_TYPE_CE: + count = ext_error_code == 6 ? count : 0ULL; + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, count); + break; + default: + return -EINVAL; + } + + return ret; } static const struct aca_bank_ops xgmi_v6_4_0_aca_bank_ops = { - .aca_bank_generate_report = xgmi_v6_4_0_aca_bank_generate_report, + .aca_bank_parser = xgmi_v6_4_0_aca_bank_parser, }; static const struct aca_info xgmi_v6_4_0_aca_info = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 1592c63b3099..a3bfc16de6d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -44,6 +44,7 @@ struct amdgpu_hive_info { struct amdgpu_reset_domain *reset_domain; atomic_t ras_recovery; + struct ras_event_manager event_mgr; }; struct amdgpu_pcs_ras_field { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h index 51a14f6d93bd..fb2b394bb9c5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgv_sriovmsg.h @@ -94,7 +94,8 @@ union amd_sriov_msg_feature_flags { uint32_t reg_indirect_acc : 1; uint32_t av1_support : 1; uint32_t vcn_rb_decouple : 1; - uint32_t reserved : 24; + uint32_t mes_info_enable : 1; + uint32_t reserved : 23; } flags; uint32_t all; }; @@ -157,7 +158,7 @@ struct amd_sriov_msg_pf2vf_info_header { uint32_t reserved[2]; }; -#define AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE (48) +#define AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE (49) struct amd_sriov_msg_pf2vf_info { /* header contains size and version */ struct amd_sriov_msg_pf2vf_info_header header; @@ -208,6 +209,8 @@ struct amd_sriov_msg_pf2vf_info { struct amd_sriov_msg_uuid_info uuid_info; /* PCIE atomic ops support flag */ uint32_t pcie_atomic_ops_support_flags; + /* Portion of GPU memory occupied by VF. MAX value is 65535, but set to uint32_t to maintain alignment with reserved size */ + uint32_t gpu_capacity; /* reserved */ uint32_t reserved[256 - AMD_SRIOV_MSG_PF2VF_INFO_FILLED_SIZE]; }; @@ -221,7 +224,7 @@ struct amd_sriov_msg_vf2pf_info_header { uint32_t reserved[2]; }; -#define AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE (70) +#define AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE (73) struct amd_sriov_msg_vf2pf_info { /* header contains size and version */ struct amd_sriov_msg_vf2pf_info_header header; @@ -265,7 +268,9 @@ struct amd_sriov_msg_vf2pf_info { uint32_t version; } ucode_info[AMD_SRIOV_MSG_RESERVE_UCODE]; uint64_t dummy_page_addr; - + /* FB allocated for guest MES to record UQ info */ + uint64_t mes_info_addr; + uint32_t mes_info_size; /* reserved */ uint32_t reserved[256 - AMD_SRIOV_MSG_VF2PF_INFO_FILLED_SIZE]; }; diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c index d6f808acfb17..414ea3f560a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c @@ -62,6 +62,11 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev) adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1; } +static bool aqua_vanjaram_xcp_vcn_shared(struct amdgpu_device *adev) +{ + return (adev->xcp_mgr->num_xcps > adev->vcn.num_vcn_inst); +} + static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, uint32_t inst_idx, struct amdgpu_ring *ring) { @@ -87,7 +92,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, case AMDGPU_RING_TYPE_VCN_ENC: case AMDGPU_RING_TYPE_VCN_JPEG: ip_blk = AMDGPU_XCP_VCN; - if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) + if (aqua_vanjaram_xcp_vcn_shared(adev)) inst_mask = 1 << (inst_idx * 2); break; default: @@ -140,10 +145,12 @@ static int aqua_vanjaram_xcp_sched_list_update( aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id); - /* VCN is shared by two partitions under CPX MODE */ + /* VCN may be shared by two partitions under CPX MODE in certain + * configs. + */ if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC || - ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && - adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) + ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && + aqua_vanjaram_xcp_vcn_shared(adev)) aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1); } @@ -623,7 +630,7 @@ static int aqua_vanjaram_xcp_mgr_init(struct amdgpu_device *adev) int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev) { - u32 mask, inst_mask = adev->sdma.sdma_mask; + u32 mask, avail_inst, inst_mask = adev->sdma.sdma_mask; int ret, i; /* generally 1 AID supports 4 instances */ @@ -635,7 +642,9 @@ int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev) for (mask = (1 << adev->sdma.num_inst_per_aid) - 1; inst_mask; inst_mask >>= adev->sdma.num_inst_per_aid, ++i) { - if ((inst_mask & mask) == mask) + avail_inst = inst_mask & mask; + if (avail_inst == mask || avail_inst == 0x3 || + avail_inst == 0xc) adev->aid_mask |= (1 << i); } diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index 72362df352f6..d552e013354c 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -1243,6 +1243,7 @@ static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index, ectx.ps_size = params_size; ectx.abort = false; ectx.last_jump = 0; + ectx.last_jump_jiffies = 0; if (ws) { ectx.ws = kcalloc(4, ws, GFP_KERNEL); ectx.ws_size = ws; diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index a3a643254d7a..cf1d5d462b67 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1375,14 +1375,14 @@ static int cik_asic_pci_config_reset(struct amdgpu_device *adev) return r; } -static bool cik_asic_supports_baco(struct amdgpu_device *adev) +static int cik_asic_supports_baco(struct amdgpu_device *adev) { switch (adev->asic_type) { case CHIP_BONAIRE: case CHIP_HAWAII: return amdgpu_dpm_is_baco_supported(adev); default: - return false; + return 0; } } @@ -2210,6 +2210,8 @@ static const struct amd_ip_funcs cik_common_ip_funcs = { .soft_reset = cik_common_soft_reset, .set_clockgating_state = cik_common_set_clockgating_state, .set_powergating_state = cik_common_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ip_block_version cik_common_ip_block = diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index f24e34dc33d1..576baa9dbb0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -435,6 +435,8 @@ static const struct amd_ip_funcs cik_ih_ip_funcs = { .soft_reset = cik_ih_soft_reset, .set_clockgating_state = cik_ih_set_clockgating_state, .set_powergating_state = cik_ih_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs cik_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index a3fccc4c1f43..6948ebda0fa2 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1228,6 +1228,8 @@ static const struct amd_ip_funcs cik_sdma_ip_funcs = { .soft_reset = cik_sdma_soft_reset, .set_clockgating_state = cik_sdma_set_clockgating_state, .set_powergating_state = cik_sdma_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = { @@ -1290,7 +1292,7 @@ static void cik_sdma_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: is this a secure operation + * @copy_flags: unused * * Copy GPU buffers using the DMA engine (CIK). * Used by the amdgpu ttm implementation to move pages if @@ -1300,7 +1302,7 @@ static void cik_sdma_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PACKET(SDMA_OPCODE_COPY, SDMA_COPY_SUB_OPCODE_LINEAR, 0); ib->ptr[ib->length_dw++] = byte_count; diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index c19681492efa..072643787384 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -433,6 +433,8 @@ static const struct amd_ip_funcs cz_ih_ip_funcs = { .soft_reset = cz_ih_soft_reset, .set_clockgating_state = cz_ih_set_clockgating_state, .set_powergating_state = cz_ih_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs cz_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 221af054d874..b44fce44c066 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3333,6 +3333,8 @@ static const struct amd_ip_funcs dce_v10_0_ip_funcs = { .soft_reset = dce_v10_0_soft_reset, .set_clockgating_state = dce_v10_0_set_clockgating_state, .set_powergating_state = dce_v10_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static void diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 69e8b0db6cf7..80b2e7f79acf 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3464,6 +3464,8 @@ static const struct amd_ip_funcs dce_v11_0_ip_funcs = { .soft_reset = dce_v11_0_soft_reset, .set_clockgating_state = dce_v11_0_set_clockgating_state, .set_powergating_state = dce_v11_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static void diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index 60d40201fdd1..db20012600f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -3154,6 +3154,8 @@ static const struct amd_ip_funcs dce_v6_0_ip_funcs = { .soft_reset = dce_v6_0_soft_reset, .set_clockgating_state = dce_v6_0_set_clockgating_state, .set_powergating_state = dce_v6_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static void diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 5a5fcc45e452..5b56100ec902 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -3242,6 +3242,8 @@ static const struct amd_ip_funcs dce_v8_0_ip_funcs = { .soft_reset = dce_v8_0_soft_reset, .set_clockgating_state = dce_v8_0_set_clockgating_state, .set_powergating_state = dce_v8_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static void diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index f90905ef32c7..536287ddd2ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -276,6 +276,99 @@ MODULE_FIRMWARE("amdgpu/gc_10_3_7_mec.bin"); MODULE_FIRMWARE("amdgpu/gc_10_3_7_mec2.bin"); MODULE_FIRMWARE("amdgpu/gc_10_3_7_rlc.bin"); +static const struct amdgpu_hwip_reg_entry gc_reg_list_10_1[] = { + SOC15_REG_ENTRY_STR(GC, 0, mmGRBM_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmGRBM_STATUS2), + SOC15_REG_ENTRY_STR(GC, 0, mmGRBM_STATUS3), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_STALLED_STAT1), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_STALLED_STAT2), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPC_STALLED_STAT1), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPF_STALLED_STAT1), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_BUSY_STAT), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPC_BUSY_STAT), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPF_BUSY_STAT), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPC_BUSY_STAT2), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPF_BUSY_STAT2), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPF_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_GFX_ERROR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_GFX_HPD_STATUS0), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB_BASE), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB_RPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB_WPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB0_BASE), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB0_RPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB0_WPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB1_BASE), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB1_RPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB1_WPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB2_BASE), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB2_WPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_RB2_WPTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB1_CMD_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB2_CMD_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB1_CMD_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB2_CMD_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB1_BASE_LO), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB1_BASE_HI), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB1_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB2_BASE_LO), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB2_BASE_HI), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_IB2_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB1_BASE_LO), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB1_BASE_HI), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB1_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB2_BASE_LO), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB2_BASE_HI), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_IB2_BUFSZ), + SOC15_REG_ENTRY_STR(GC, 0, mmCPF_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmCPC_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmCPG_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmGDS_PROTECTION_FAULT), + SOC15_REG_ENTRY_STR(GC, 0, mmGDS_VM_PROTECTION_FAULT), + SOC15_REG_ENTRY_STR(GC, 0, mmIA_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmIA_UTCL1_STATUS_2), + SOC15_REG_ENTRY_STR(GC, 0, mmPA_CL_CNTL_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmRMI_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmSQC_DCACHE_UTCL0_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmSQC_ICACHE_UTCL0_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmSQG_UTCL0_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmTCP_UTCL0_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmWD_UTCL1_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL), + SOC15_REG_ENTRY_STR(GC, 0, mmGCVM_L2_PROTECTION_FAULT_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_DEBUG), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MEC_CNTL), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MES_CNTL), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CE_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MEC1_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MEC2_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MES_DEBUG_INTERRUPT_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_MES_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_ME_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_PFP_INSTR_PNTR), + SOC15_REG_ENTRY_STR(GC, 0, mmCP_CPC_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_STAT), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_COMMAND), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_MESSAGE), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_ARGUMENT_1), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_ARGUMENT_2), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_ARGUMENT_3), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_ARGUMENT_4), + SOC15_REG_ENTRY_STR(GC, 0, mmSMU_RLC_RESPONSE), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SAFE_MODE), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SMU_SAFE_MODE), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_RLCS_GPM_STAT_2), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_SPP_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_RLCS_BOOTLOAD_STATUS), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_INT_STAT), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_GPM_GENERAL_6), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_GPM_DEBUG_INST_A), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_GPM_DEBUG_INST_B), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_GPM_DEBUG_INST_ADDR), + SOC15_REG_ENTRY_STR(GC, 0, mmRLC_LX6_CORE_PDEBUG_INST) +}; + static const struct soc15_reg_golden golden_settings_gc_10_1[] = { SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_CPF_CLK_CTRL, 0xfcff8fff, 0xf8000100), @@ -3964,7 +4057,7 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) { - char fw_name[40]; + char fw_name[53]; char ucode_prefix[30]; const char *wks = ""; int err; @@ -4490,6 +4583,22 @@ static int gfx_v10_0_compute_ring_init(struct amdgpu_device *adev, int ring_id, hw_prio, NULL); } +static void gfx_v10_0_alloc_dump_mem(struct amdgpu_device *adev) +{ + uint32_t reg_count = ARRAY_SIZE(gc_reg_list_10_1); + uint32_t *ptr; + + ptr = kcalloc(reg_count, sizeof(uint32_t), GFP_KERNEL); + if (ptr == NULL) { + DRM_ERROR("Failed to allocate memory for IP Dump\n"); + adev->gfx.ip_dump = NULL; + adev->gfx.reg_count = 0; + } else { + adev->gfx.ip_dump = ptr; + adev->gfx.reg_count = reg_count; + } +} + static int gfx_v10_0_sw_init(void *handle) { int i, j, k, r, ring_id = 0; @@ -4518,7 +4627,7 @@ static int gfx_v10_0_sw_init(void *handle) case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 7): adev->gfx.me.num_me = 1; - adev->gfx.me.num_pipe_per_me = 1; + adev->gfx.me.num_pipe_per_me = 2; adev->gfx.me.num_queue_per_pipe = 1; adev->gfx.mec.num_mec = 2; adev->gfx.mec.num_pipe_per_mec = 4; @@ -4642,6 +4751,8 @@ static int gfx_v10_0_sw_init(void *handle) gfx_v10_0_gpu_early_init(adev); + gfx_v10_0_alloc_dump_mem(adev); + return 0; } @@ -4694,6 +4805,8 @@ static int gfx_v10_0_sw_fini(void *handle) gfx_v10_0_free_microcode(adev); + kfree(adev->gfx.ip_dump); + return 0; } @@ -8317,7 +8430,7 @@ static void gfx_v10_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) } reg_mem_engine = 0; } else { - ref_and_mask = nbio_hf_reg->ref_and_mask_cp0; + ref_and_mask = nbio_hf_reg->ref_and_mask_cp0 << ring->pipe; reg_mem_engine = 1; /* pfp */ } @@ -9154,6 +9267,36 @@ static void gfx_v10_0_emit_mem_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, gcr_cntl); /* GCR_CNTL */ } +static void gfx_v10_ip_print(void *handle, struct drm_printer *p) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + uint32_t i; + uint32_t reg_count = ARRAY_SIZE(gc_reg_list_10_1); + + if (!adev->gfx.ip_dump) + return; + + for (i = 0; i < reg_count; i++) + drm_printf(p, "%-50s \t 0x%08x\n", + gc_reg_list_10_1[i].reg_name, + adev->gfx.ip_dump[i]); +} + +static void gfx_v10_ip_dump(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + uint32_t i; + uint32_t reg_count = ARRAY_SIZE(gc_reg_list_10_1); + + if (!adev->gfx.ip_dump) + return; + + amdgpu_gfx_off_ctrl(adev, false); + for (i = 0; i < reg_count; i++) + adev->gfx.ip_dump[i] = RREG32(SOC15_REG_ENTRY_OFFSET(gc_reg_list_10_1[i])); + amdgpu_gfx_off_ctrl(adev, true); +} + static const struct amd_ip_funcs gfx_v10_0_ip_funcs = { .name = "gfx_v10_0", .early_init = gfx_v10_0_early_init, @@ -9170,6 +9313,8 @@ static const struct amd_ip_funcs gfx_v10_0_ip_funcs = { .set_clockgating_state = gfx_v10_0_set_clockgating_state, .set_powergating_state = gfx_v10_0_set_powergating_state, .get_clockgating_state = gfx_v10_0_get_clockgating_state, + .dump_ip_state = gfx_v10_ip_dump, + .print_ip_state = gfx_v10_ip_print, }; static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = { @@ -9186,7 +9331,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = { 7 + /* PIPELINE_SYNC */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* VM_FLUSH */ + 4 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ 20 + /* GDS switch */ 4 + /* double SWITCH_BUFFER, @@ -9276,7 +9421,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = { 7 + /* gfx_v10_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v10_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */ .emit_ib = gfx_v10_0_ring_emit_ib_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 1770e496c1b7..ad6431013c73 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -510,7 +510,7 @@ static void gfx_v11_0_check_fw_cp_gfx_shadow(struct amdgpu_device *adev) static int gfx_v11_0_init_microcode(struct amdgpu_device *adev) { char fw_name[40]; - char ucode_prefix[30]; + char ucode_prefix[25]; int err; const struct rlc_firmware_header_v2_0 *rlc_hdr; uint16_t version_major; @@ -1635,7 +1635,7 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev) active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa)); } - active_rb_bitmap |= global_active_rb_bitmap; + active_rb_bitmap &= global_active_rb_bitmap; adev->gfx.config.backend_enable_mask = active_rb_bitmap; adev->gfx.config.num_rbs = hweight32(active_rb_bitmap); } @@ -4506,14 +4506,11 @@ static int gfx_v11_0_soft_reset(void *handle) gfx_v11_0_set_safe_mode(adev, 0); + mutex_lock(&adev->srbm_mutex); for (i = 0; i < adev->gfx.mec.num_mec; ++i) { for (j = 0; j < adev->gfx.mec.num_queue_per_pipe; j++) { for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) { - tmp = RREG32_SOC15(GC, 0, regGRBM_GFX_CNTL); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, MEID, i); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, QUEUEID, j); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, PIPEID, k); - WREG32_SOC15(GC, 0, regGRBM_GFX_CNTL, tmp); + soc21_grbm_select(adev, i, k, j, 0); WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 0x2); WREG32_SOC15(GC, 0, regSPI_COMPUTE_QUEUE_RESET, 0x1); @@ -4523,16 +4520,14 @@ static int gfx_v11_0_soft_reset(void *handle) for (i = 0; i < adev->gfx.me.num_me; ++i) { for (j = 0; j < adev->gfx.me.num_queue_per_pipe; j++) { for (k = 0; k < adev->gfx.me.num_pipe_per_me; k++) { - tmp = RREG32_SOC15(GC, 0, regGRBM_GFX_CNTL); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, MEID, i); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, QUEUEID, j); - tmp = REG_SET_FIELD(tmp, GRBM_GFX_CNTL, PIPEID, k); - WREG32_SOC15(GC, 0, regGRBM_GFX_CNTL, tmp); + soc21_grbm_select(adev, i, k, j, 0); WREG32_SOC15(GC, 0, regCP_GFX_HQD_DEQUEUE_REQUEST, 0x1); } } } + soc21_grbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); /* Try to acquire the gfx mutex before access to CP_VMID_RESET */ r = gfx_v11_0_request_gfx_index_mutex(adev, 1); @@ -5465,6 +5460,7 @@ static void gfx_v11_0_ring_emit_vm_flush(struct amdgpu_ring *ring, /* Make sure that we can't skip the SET_Q_MODE packets when the VM * changed in any way. */ + ring->set_q_mode_offs = 0; ring->set_q_mode_ptr = NULL; } @@ -6173,6 +6169,8 @@ static const struct amd_ip_funcs gfx_v11_0_ip_funcs = { .set_clockgating_state = gfx_v11_0_set_clockgating_state, .set_powergating_state = gfx_v11_0_set_powergating_state, .get_clockgating_state = gfx_v11_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = { @@ -6191,7 +6189,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = { 7 + /* PIPELINE_SYNC */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* VM_FLUSH */ + 4 + /* VM_FLUSH */ 8 + /* FENCE for VM_FLUSH */ 20 + /* GDS switch */ 5 + /* COND_EXEC */ @@ -6277,7 +6275,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = { 7 + /* gfx_v11_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v11_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */ .emit_ib = gfx_v11_0_ring_emit_ib_compute, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c index 34f9211b2679..d0992ce9fb47 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c @@ -3457,6 +3457,8 @@ static const struct amd_ip_funcs gfx_v6_0_ip_funcs = { .soft_reset = gfx_v6_0_soft_reset, .set_clockgating_state = gfx_v6_0_set_clockgating_state, .set_powergating_state = gfx_v6_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 86a4865b1ae5..541dbd70d8c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c @@ -4977,6 +4977,8 @@ static const struct amd_ip_funcs gfx_v7_0_ip_funcs = { .soft_reset = gfx_v7_0_soft_reset, .set_clockgating_state = gfx_v7_0_set_clockgating_state, .set_powergating_state = gfx_v7_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 202ddda57f98..2f0e72caee1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -6878,6 +6878,8 @@ static const struct amd_ip_funcs gfx_v8_0_ip_funcs = { .set_clockgating_state = gfx_v8_0_set_clockgating_state, .set_powergating_state = gfx_v8_0_set_powergating_state, .get_clockgating_state = gfx_v8_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 6f97a6d0e6d0..3c8c5abf35ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1249,7 +1249,7 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev) static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev, char *chip_name) { - char fw_name[30]; + char fw_name[50]; int err; snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_pfp.bin", chip_name); @@ -1282,7 +1282,7 @@ static int gfx_v9_0_init_cp_gfx_microcode(struct amdgpu_device *adev, static int gfx_v9_0_init_rlc_microcode(struct amdgpu_device *adev, char *chip_name) { - char fw_name[30]; + char fw_name[53]; int err; const struct rlc_firmware_header_v2_0 *rlc_hdr; uint16_t version_major; @@ -1337,7 +1337,7 @@ static bool gfx_v9_0_load_mec2_fw_bin_support(struct amdgpu_device *adev) static int gfx_v9_0_init_cp_compute_microcode(struct amdgpu_device *adev, char *chip_name) { - char fw_name[30]; + char fw_name[50]; int err; if (amdgpu_sriov_vf(adev) && (adev->asic_type == CHIP_ALDEBARAN)) @@ -6856,6 +6856,8 @@ static const struct amd_ip_funcs gfx_v9_0_ip_funcs = { .set_clockgating_state = gfx_v9_0_set_clockgating_state, .set_powergating_state = gfx_v9_0_set_powergating_state, .get_clockgating_state = gfx_v9_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = { @@ -6981,7 +6983,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */ 7 + /* gfx_v9_0_emit_mem_sync */ 5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */ @@ -7019,7 +7020,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { 7 + /* gfx_v9_0_ring_emit_pipeline_sync */ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 + SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + - 2 + /* gfx_v9_0_ring_emit_vm_flush */ 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */ .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */ .emit_fence = gfx_v9_0_ring_emit_fence_kiq, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c index 065b2bd5f5a6..3f4fd2f08163 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c @@ -1909,18 +1909,7 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev) mutex_unlock(&adev->grbm_idx_mutex); } -static bool gfx_v9_4_2_query_uctl2_poison_status(struct amdgpu_device *adev) -{ - u32 status = 0; - struct amdgpu_vmhub *hub; - hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; - status = RREG32(hub->vm_l2_pro_fault_status); - /* reset page fault status */ - WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); - - return REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); -} struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops = { .query_ras_error_count = &gfx_v9_4_2_query_ras_error_count, @@ -1934,5 +1923,4 @@ struct amdgpu_gfx_ras gfx_v9_4_2_ras = { .hw_ops = &gfx_v9_4_2_ras_ops, }, .enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer, - .query_utcl2_poison_status = gfx_v9_4_2_query_uctl2_poison_status, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c index b53c8fd4e8cf..7b16e8cca86a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c @@ -431,16 +431,16 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev, static int gfx_v9_4_3_init_microcode(struct amdgpu_device *adev) { - const char *chip_name; + char ucode_prefix[15]; int r; - chip_name = "gc_9_4_3"; + amdgpu_ucode_ip_version_decode(adev, GC_HWIP, ucode_prefix, sizeof(ucode_prefix)); - r = gfx_v9_4_3_init_rlc_microcode(adev, chip_name); + r = gfx_v9_4_3_init_rlc_microcode(adev, ucode_prefix); if (r) return r; - r = gfx_v9_4_3_init_cp_compute_microcode(adev, chip_name); + r = gfx_v9_4_3_init_cp_compute_microcode(adev, ucode_prefix); if (r) return r; @@ -680,38 +680,44 @@ static const struct amdgpu_gfx_funcs gfx_v9_4_3_gfx_funcs = { .ih_node_to_logical_xcc = &gfx_v9_4_3_ih_to_xcc_inst, }; -static int gfx_v9_4_3_aca_bank_generate_report(struct aca_handle *handle, - struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data) +static int gfx_v9_4_3_aca_bank_parser(struct aca_handle *handle, + struct aca_bank *bank, enum aca_smu_type type, + void *data) { - u64 status, misc0; + struct aca_bank_info info; + u64 misc0; u32 instlo; int ret; - status = bank->regs[ACA_REG_IDX_STATUS]; - if ((type == ACA_ERROR_TYPE_UE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_FAULT) || - (type == ACA_ERROR_TYPE_CE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_CE)) { + ret = aca_bank_info_decode(bank, &info); + if (ret) + return ret; - ret = aca_bank_info_decode(bank, &report->info); - if (ret) - return ret; + /* NOTE: overwrite info.die_id with xcd id for gfx */ + instlo = ACA_REG__IPID__INSTANCEIDLO(bank->regs[ACA_REG_IDX_IPID]); + instlo &= GENMASK(31, 1); + info.die_id = instlo == mmSMNAID_XCD0_MCA_SMU ? 0 : 1; - /* NOTE: overwrite info.die_id with xcd id for gfx */ - instlo = ACA_REG__IPID__INSTANCEIDLO(bank->regs[ACA_REG_IDX_IPID]); - instlo &= GENMASK(31, 1); - report->info.die_id = instlo == mmSMNAID_XCD0_MCA_SMU ? 0 : 1; + misc0 = bank->regs[ACA_REG_IDX_MISC0]; - misc0 = bank->regs[ACA_REG_IDX_MISC0]; - report->count[type] = ACA_REG__MISC0__ERRCNT(misc0); + switch (type) { + case ACA_SMU_TYPE_UE: + ret = aca_error_cache_log_bank_error(handle, &info, + ACA_ERROR_TYPE_UE, 1ULL); + break; + case ACA_SMU_TYPE_CE: + ret = aca_error_cache_log_bank_error(handle, &info, + ACA_ERROR_TYPE_CE, ACA_REG__MISC0__ERRCNT(misc0)); + break; + default: + return -EINVAL; } - return 0; + return ret; } static bool gfx_v9_4_3_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, void *data) + enum aca_smu_type type, void *data) { u32 instlo; @@ -730,7 +736,7 @@ static bool gfx_v9_4_3_aca_bank_is_valid(struct aca_handle *handle, struct aca_b } static const struct aca_bank_ops gfx_v9_4_3_aca_bank_ops = { - .aca_bank_generate_report = gfx_v9_4_3_aca_bank_generate_report, + .aca_bank_parser = gfx_v9_4_3_aca_bank_parser, .aca_bank_is_valid = gfx_v9_4_3_aca_bank_is_valid, }; @@ -2398,10 +2404,10 @@ gfx_v9_4_3_xcc_update_coarse_grain_clock_gating(struct amdgpu_device *adev, if (def != data) WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGTT_MGCG_OVERRIDE, data); - /* enable cgcg FSM(0x0000363F) */ + /* CGCG Hysteresis: 400us */ def = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL); - data = (0x36 + data = (0x2710 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) | RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) @@ -2410,10 +2416,10 @@ gfx_v9_4_3_xcc_update_coarse_grain_clock_gating(struct amdgpu_device *adev, if (def != data) WREG32_SOC15(GC, GET_INST(GC, xcc_id), regRLC_CGCG_CGLS_CTRL, data); - /* set IDLE_POLL_COUNT(0x00900100) */ + /* set IDLE_POLL_COUNT(0x33450100)*/ def = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_RB_WPTR_POLL_CNTL); data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) | - (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT); + (0x3345 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT); if (def != data) WREG32_SOC15(GC, GET_INST(GC, xcc_id), regCP_RB_WPTR_POLL_CNTL, data); } else { @@ -4010,6 +4016,8 @@ static const struct amd_ip_funcs gfx_v9_4_3_ip_funcs = { .set_clockgating_state = gfx_v9_4_3_set_clockgating_state, .set_powergating_state = gfx_v9_4_3_set_powergating_state, .get_clockgating_state = gfx_v9_4_3_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs gfx_v9_4_3_ring_funcs_compute = { diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index 22175da0e16a..d200310d1731 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -443,6 +443,22 @@ static void gfxhub_v1_0_init(struct amdgpu_device *adev) mmVM_INVALIDATE_ENG0_ADDR_RANGE_LO32; } +static bool gfxhub_v1_0_query_utcl2_poison_status(struct amdgpu_device *adev, + int xcc_id) +{ + u32 status = 0; + struct amdgpu_vmhub *hub; + + if (amdgpu_ip_version(adev, GC_HWIP, 0) != IP_VERSION(9, 4, 2)) + return false; + + hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; + status = RREG32(hub->vm_l2_pro_fault_status); + /* reset page fault status */ + WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); + + return REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); +} const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs = { .get_mc_fb_offset = gfxhub_v1_0_get_mc_fb_offset, @@ -452,4 +468,5 @@ const struct amdgpu_gfxhub_funcs gfxhub_v1_0_funcs = { .set_fault_enable_default = gfxhub_v1_0_set_fault_enable_default, .init = gfxhub_v1_0_init, .get_xgmi_info = gfxhub_v1_1_get_xgmi_info, + .query_utcl2_poison_status = gfxhub_v1_0_query_utcl2_poison_status, }; diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c index 49aecdcee006..77df8c9cbad2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c @@ -620,6 +620,20 @@ static int gfxhub_v1_2_get_xgmi_info(struct amdgpu_device *adev) return 0; } +static bool gfxhub_v1_2_query_utcl2_poison_status(struct amdgpu_device *adev, + int xcc_id) +{ + u32 fed, status; + + status = RREG32_SOC15(GC, GET_INST(GC, xcc_id), regVM_L2_PROTECTION_FAULT_STATUS); + fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); + /* reset page fault status */ + WREG32_P(SOC15_REG_OFFSET(GC, GET_INST(GC, xcc_id), + regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + + return fed; +} + const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = { .get_mc_fb_offset = gfxhub_v1_2_get_mc_fb_offset, .setup_vm_pt_regs = gfxhub_v1_2_setup_vm_pt_regs, @@ -628,6 +642,7 @@ const struct amdgpu_gfxhub_funcs gfxhub_v1_2_funcs = { .set_fault_enable_default = gfxhub_v1_2_set_fault_enable_default, .init = gfxhub_v1_2_init, .get_xgmi_info = gfxhub_v1_2_get_xgmi_info, + .query_utcl2_poison_status = gfxhub_v1_2_query_utcl2_poison_status, }; static int gfxhub_v1_2_xcp_resume(void *handle, uint32_t inst_mask) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 23b478639921..3e38d8bfcb69 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -1115,6 +1115,8 @@ static const struct amd_ip_funcs gmc_v6_0_ip_funcs = { .soft_reset = gmc_v6_0_soft_reset, .set_clockgating_state = gmc_v6_0_set_clockgating_state, .set_powergating_state = gmc_v6_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_gmc_funcs gmc_v6_0_gmc_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 3da7b6a2b00d..85df8fc81065 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1354,6 +1354,8 @@ static const struct amd_ip_funcs gmc_v7_0_ip_funcs = { .soft_reset = gmc_v7_0_soft_reset, .set_clockgating_state = gmc_v7_0_set_clockgating_state, .set_powergating_state = gmc_v7_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_gmc_funcs gmc_v7_0_gmc_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index d20e5f20ee31..fc97757e33d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1717,6 +1717,8 @@ static const struct amd_ip_funcs gmc_v8_0_ip_funcs = { .set_clockgating_state = gmc_v8_0_set_clockgating_state, .set_powergating_state = gmc_v8_0_set_powergating_state, .get_clockgating_state = gmc_v8_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_gmc_funcs gmc_v8_0_gmc_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 47b63a4ce68b..c4ec1358f3aa 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -548,7 +548,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, { bool retry_fault = !!(entry->src_data[1] & 0x80); bool write_fault = !!(entry->src_data[1] & 0x20); - uint32_t status = 0, cid = 0, rw = 0; + uint32_t status = 0, cid = 0, rw = 0, fed = 0; struct amdgpu_task_info *task_info; struct amdgpu_vmhub *hub; const char *mmhub_cid; @@ -664,6 +664,13 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, status = RREG32(hub->vm_l2_pro_fault_status); cid = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, CID); rw = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, RW); + fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); + + /* for fed error, kfd will handle it, return directly */ + if (fed && amdgpu_ras_is_poison_mode_supported(adev) && + (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(9, 4, 2))) + return 0; + WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); amdgpu_vm_update_fault_cache(adev, entry->pasid, addr, status, vmhub); @@ -1450,7 +1457,6 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) adev->umc.channel_offs = UMC_V12_0_PER_CHANNEL_OFFSET; adev->umc.active_mask = adev->aid_mask; adev->umc.retire_unit = UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL; - adev->umc.channel_idx_tbl = &umc_v12_0_channel_idx_tbl[0][0][0]; if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu) adev->umc.ras = &umc_v12_0_ras; break; diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 2c02ae69883d..07984f7c3ae7 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -425,6 +425,8 @@ static const struct amd_ip_funcs iceland_ih_ip_funcs = { .soft_reset = iceland_ih_soft_reset, .set_clockgating_state = iceland_ih_set_clockgating_state, .set_powergating_state = iceland_ih_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs iceland_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c index ad4ad39f128f..3cb64c8f7175 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_0.c @@ -346,6 +346,21 @@ static int ih_v6_0_irq_init(struct amdgpu_device *adev) DELAY, 3); WREG32_SOC15(OSSSYS, 0, regIH_MSI_STORM_CTRL, tmp); + /* Redirect the interrupts to IH RB1 for dGPU */ + if (adev->irq.ih1.ring_size) { + tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_INDEX, INDEX, 0); + WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX, tmp); + + tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, CLIENT_ID, 0xa); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, SOURCE_ID, 0x0); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, + SOURCE_ID_MATCH_ENABLE, 0x1); + + WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA, tmp); + } + pci_set_master(adev->pdev); /* enable interrupts */ @@ -549,8 +564,15 @@ static int ih_v6_0_sw_init(void *handle) adev->irq.ih.use_doorbell = true; adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1; - adev->irq.ih1.ring_size = 0; - adev->irq.ih2.ring_size = 0; + if (!(adev->flags & AMD_IS_APU)) { + r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, IH_RING_SIZE, + use_bus_addr); + if (r) + return r; + + adev->irq.ih1.use_doorbell = true; + adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1; + } /* initialize ih control register offset */ ih_v6_0_init_register_offset(adev); @@ -748,6 +770,8 @@ static const struct amd_ip_funcs ih_v6_0_ip_funcs = { .set_clockgating_state = ih_v6_0_set_clockgating_state, .set_powergating_state = ih_v6_0_set_powergating_state, .get_clockgating_state = ih_v6_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs ih_v6_0_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c index b8da0fc29378..0fbf5fa7b0f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v6_1.c @@ -346,6 +346,21 @@ static int ih_v6_1_irq_init(struct amdgpu_device *adev) DELAY, 3); WREG32_SOC15(OSSSYS, 0, regIH_MSI_STORM_CTRL, tmp); + /* Redirect the interrupts to IH RB1 for dGPU */ + if (adev->irq.ih1.ring_size) { + tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_INDEX, INDEX, 0); + WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_INDEX, tmp); + + tmp = RREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, CLIENT_ID, 0xa); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, SOURCE_ID, 0x0); + tmp = REG_SET_FIELD(tmp, IH_RING1_CLIENT_CFG_DATA, + SOURCE_ID_MATCH_ENABLE, 0x1); + + WREG32_SOC15(OSSSYS, 0, regIH_RING1_CLIENT_CFG_DATA, tmp); + } + pci_set_master(adev->pdev); /* enable interrupts */ @@ -550,8 +565,15 @@ static int ih_v6_1_sw_init(void *handle) adev->irq.ih.use_doorbell = true; adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1; - adev->irq.ih1.ring_size = 0; - adev->irq.ih2.ring_size = 0; + if (!(adev->flags & AMD_IS_APU)) { + r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, IH_RING_SIZE, + use_bus_addr); + if (r) + return r; + + adev->irq.ih1.use_doorbell = true; + adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1; + } /* initialize ih control register offset */ ih_v6_1_init_register_offset(adev); @@ -753,6 +775,8 @@ static const struct amd_ip_funcs ih_v6_1_ip_funcs = { .set_clockgating_state = ih_v6_1_set_clockgating_state, .set_powergating_state = ih_v6_1_set_powergating_state, .get_clockgating_state = ih_v6_1_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs ih_v6_1_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c index 7aed96fa10a9..aa6235dd4f2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/ih_v7_0.c @@ -749,6 +749,8 @@ static const struct amd_ip_funcs ih_v7_0_ip_funcs = { .set_clockgating_state = ih_v7_0_set_clockgating_state, .set_powergating_state = ih_v7_0_set_powergating_state, .get_clockgating_state = ih_v7_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs ih_v7_0_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c index 1c8116d75f63..ef3e42f6b841 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c @@ -759,6 +759,8 @@ static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v2_0_set_clockgating_state, .set_powergating_state = jpeg_v2_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v2_0_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index 99cd49ee8ef6..afeaf3c64e27 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c @@ -632,6 +632,8 @@ static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v2_5_set_clockgating_state, .set_powergating_state = jpeg_v2_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = { @@ -652,6 +654,8 @@ static const struct amd_ip_funcs jpeg_v2_6_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v2_5_set_clockgating_state, .set_powergating_state = jpeg_v2_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v2_5_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index a92481da60cd..1c7cf4800bf7 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -557,6 +557,8 @@ static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v3_0_set_clockgating_state, .set_powergating_state = jpeg_v3_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v3_0_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c index 88ea58d5c4ab..237fe5df5a8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c @@ -719,6 +719,8 @@ static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v4_0_set_clockgating_state, .set_powergating_state = jpeg_v4_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v4_0_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c index 32caeb37cef9..d66af11aa66c 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c @@ -1053,6 +1053,8 @@ static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v4_0_3_set_clockgating_state, .set_powergating_state = jpeg_v4_0_3_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c index edf5bcdd2bc9..da6bb9022b80 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c @@ -762,6 +762,8 @@ static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v4_0_5_set_clockgating_state, .set_powergating_state = jpeg_v4_0_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c index e70200f97555..64c856bfe0cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c @@ -513,6 +513,8 @@ static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = jpeg_v5_0_0_set_clockgating_state, .set_powergating_state = jpeg_v5_0_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c index 1e5ad1e08d2a..a626bf904926 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c @@ -1176,6 +1176,8 @@ static const struct amd_ip_funcs mes_v10_1_ip_funcs = { .hw_fini = mes_v10_1_hw_fini, .suspend = mes_v10_1_suspend, .resume = mes_v10_1_resume, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version mes_v10_1_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 072c478665ad..0d1407f25005 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -100,18 +100,76 @@ static const struct amdgpu_ring_funcs mes_v11_0_ring_funcs = { .insert_nop = amdgpu_ring_insert_nop, }; +static const char *mes_v11_0_opcodes[] = { + "SET_HW_RSRC", + "SET_SCHEDULING_CONFIG", + "ADD_QUEUE", + "REMOVE_QUEUE", + "PERFORM_YIELD", + "SET_GANG_PRIORITY_LEVEL", + "SUSPEND", + "RESUME", + "RESET", + "SET_LOG_BUFFER", + "CHANGE_GANG_PRORITY", + "QUERY_SCHEDULER_STATUS", + "PROGRAM_GDS", + "SET_DEBUG_VMID", + "MISC", + "UPDATE_ROOT_PAGE_TABLE", + "AMD_LOG", +}; + +static const char *mes_v11_0_misc_opcodes[] = { + "WRITE_REG", + "INV_GART", + "QUERY_STATUS", + "READ_REG", + "WAIT_REG_MEM", + "SET_SHADER_DEBUGGER", +}; + +static const char *mes_v11_0_get_op_string(union MESAPI__MISC *x_pkt) +{ + const char *op_str = NULL; + + if (x_pkt->header.opcode < ARRAY_SIZE(mes_v11_0_opcodes)) + op_str = mes_v11_0_opcodes[x_pkt->header.opcode]; + + return op_str; +} + +static const char *mes_v11_0_get_misc_op_string(union MESAPI__MISC *x_pkt) +{ + const char *op_str = NULL; + + if ((x_pkt->header.opcode == MES_SCH_API_MISC) && + (x_pkt->opcode < ARRAY_SIZE(mes_v11_0_misc_opcodes))) + op_str = mes_v11_0_misc_opcodes[x_pkt->opcode]; + + return op_str; +} + static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, void *pkt, int size, int api_status_off) { int ndw = size / 4; signed long r; - union MESAPI__ADD_QUEUE *x_pkt = pkt; + union MESAPI__MISC *x_pkt = pkt; struct MES_API_STATUS *api_status; struct amdgpu_device *adev = mes->adev; struct amdgpu_ring *ring = &mes->ring; unsigned long flags; - signed long timeout = adev->usec_timeout; + signed long timeout = 3000000; /* 3000 ms */ + const char *op_str, *misc_op_str; + u32 fence_offset; + u64 fence_gpu_addr; + u64 *fence_ptr; + int ret; + + if (x_pkt->header.opcode >= MES_SCH_API_MAX) + return -EINVAL; if (amdgpu_emu_mode) { timeout *= 100; @@ -121,27 +179,52 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes, } BUG_ON(size % 4 != 0); + ret = amdgpu_device_wb_get(adev, &fence_offset); + if (ret) + return ret; + fence_gpu_addr = + adev->wb.gpu_addr + (fence_offset * 4); + fence_ptr = (u64 *)&adev->wb.wb[fence_offset]; + *fence_ptr = 0; + spin_lock_irqsave(&mes->ring_lock, flags); if (amdgpu_ring_alloc(ring, ndw)) { spin_unlock_irqrestore(&mes->ring_lock, flags); + amdgpu_device_wb_free(adev, fence_offset); return -ENOMEM; } api_status = (struct MES_API_STATUS *)((char *)pkt + api_status_off); - api_status->api_completion_fence_addr = mes->ring.fence_drv.gpu_addr; - api_status->api_completion_fence_value = ++mes->ring.fence_drv.sync_seq; + api_status->api_completion_fence_addr = fence_gpu_addr; + api_status->api_completion_fence_value = 1; amdgpu_ring_write_multiple(ring, pkt, ndw); amdgpu_ring_commit(ring); spin_unlock_irqrestore(&mes->ring_lock, flags); - DRM_DEBUG("MES msg=%d was emitted\n", x_pkt->header.opcode); + op_str = mes_v11_0_get_op_string(x_pkt); + misc_op_str = mes_v11_0_get_misc_op_string(x_pkt); - r = amdgpu_fence_wait_polling(ring, ring->fence_drv.sync_seq, - timeout); + if (misc_op_str) + dev_dbg(adev->dev, "MES msg=%s (%s) was emitted\n", op_str, misc_op_str); + else if (op_str) + dev_dbg(adev->dev, "MES msg=%s was emitted\n", op_str); + else + dev_dbg(adev->dev, "MES msg=%d was emitted\n", x_pkt->header.opcode); + + r = amdgpu_mes_fence_wait_polling(fence_ptr, (u64)1, timeout); + amdgpu_device_wb_free(adev, fence_offset); if (r < 1) { - DRM_ERROR("MES failed to response msg=%d\n", - x_pkt->header.opcode); + + if (misc_op_str) + dev_err(adev->dev, "MES failed to respond to msg=%s (%s)\n", + op_str, misc_op_str); + else if (op_str) + dev_err(adev->dev, "MES failed to respond to msg=%s\n", + op_str); + else + dev_err(adev->dev, "MES failed to respond to msg=%d\n", + x_pkt->header.opcode); while (halt_if_hws_hang) schedule(); @@ -411,14 +494,47 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.enable_reg_active_poll = 1; mes_set_hw_res_pkt.enable_level_process_quantum_check = 1; mes_set_hw_res_pkt.oversubscription_timer = 50; - mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; - mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr; + if (amdgpu_mes_log_enable) { + mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; + mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = + mes->event_log_gpu_addr; + } return mes_v11_0_submit_pkt_and_poll_completion(mes, &mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt), offsetof(union MESAPI_SET_HW_RESOURCES, api_status)); } +static int mes_v11_0_set_hw_resources_1(struct amdgpu_mes *mes) +{ + int size = 128 * PAGE_SIZE; + int ret = 0; + struct amdgpu_device *adev = mes->adev; + union MESAPI_SET_HW_RESOURCES_1 mes_set_hw_res_pkt; + memset(&mes_set_hw_res_pkt, 0, sizeof(mes_set_hw_res_pkt)); + + mes_set_hw_res_pkt.header.type = MES_API_TYPE_SCHEDULER; + mes_set_hw_res_pkt.header.opcode = MES_SCH_API_SET_HW_RSRC_1; + mes_set_hw_res_pkt.header.dwsize = API_FRAME_SIZE_IN_DWORDS; + mes_set_hw_res_pkt.enable_mes_info_ctx = 1; + + ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &mes->resource_1, + &mes->resource_1_gpu_addr, + &mes->resource_1_addr); + if (ret) { + dev_err(adev->dev, "(%d) failed to create mes resource_1 bo\n", ret); + return ret; + } + + mes_set_hw_res_pkt.mes_info_ctx_mc_addr = mes->resource_1_gpu_addr; + mes_set_hw_res_pkt.mes_info_ctx_size = mes->resource_1->tbo.base.size; + return mes_v11_0_submit_pkt_and_poll_completion(mes, + &mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt), + offsetof(union MESAPI_SET_HW_RESOURCES_1, api_status)); +} + static const struct amdgpu_mes_funcs mes_v11_0_funcs = { .add_hw_queue = mes_v11_0_add_hw_queue, .remove_hw_queue = mes_v11_0_remove_hw_queue, @@ -1200,6 +1316,14 @@ static int mes_v11_0_hw_init(void *handle) if (r) goto failure; + if (amdgpu_sriov_is_mes_info_enable(adev)) { + r = mes_v11_0_set_hw_resources_1(&adev->mes); + if (r) { + DRM_ERROR("failed mes_v11_0_set_hw_resources_1, r=%d\n", r); + goto failure; + } + } + r = mes_v11_0_query_sched_status(&adev->mes); if (r) { DRM_ERROR("MES is busy\n"); @@ -1223,6 +1347,11 @@ static int mes_v11_0_hw_init(void *handle) static int mes_v11_0_hw_fini(void *handle) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (amdgpu_sriov_is_mes_info_enable(adev)) { + amdgpu_bo_free_kernel(&adev->mes.resource_1, &adev->mes.resource_1_gpu_addr, + &adev->mes.resource_1_addr); + } return 0; } @@ -1288,6 +1417,8 @@ static const struct amd_ip_funcs mes_v11_0_ip_funcs = { .hw_fini = mes_v11_0_hw_fini, .suspend = mes_v11_0_suspend, .resume = mes_v11_0_resume, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version mes_v11_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c index c0fc44cdd658..7a1ff298417a 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_8.c @@ -559,6 +559,20 @@ static void mmhub_v1_8_get_clockgating(struct amdgpu_device *adev, u64 *flags) } +static bool mmhub_v1_8_query_utcl2_poison_status(struct amdgpu_device *adev, + int hub_inst) +{ + u32 fed, status; + + status = RREG32_SOC15(MMHUB, hub_inst, regVM_L2_PROTECTION_FAULT_STATUS); + fed = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); + /* reset page fault status */ + WREG32_P(SOC15_REG_OFFSET(MMHUB, hub_inst, + regVM_L2_PROTECTION_FAULT_STATUS), 1, ~1); + + return fed; +} + const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs = { .get_fb_location = mmhub_v1_8_get_fb_location, .init = mmhub_v1_8_init, @@ -568,6 +582,7 @@ const struct amdgpu_mmhub_funcs mmhub_v1_8_funcs = { .setup_vm_pt_regs = mmhub_v1_8_setup_vm_pt_regs, .set_clockgating = mmhub_v1_8_set_clockgating, .get_clockgating = mmhub_v1_8_get_clockgating, + .query_utcl2_poison_status = mmhub_v1_8_query_utcl2_poison_status, }; static const struct amdgpu_ras_err_status_reg_entry mmhub_v1_8_ce_reg_list[] = { @@ -706,28 +721,32 @@ static const struct amdgpu_ras_block_hw_ops mmhub_v1_8_ras_hw_ops = { .reset_ras_error_count = mmhub_v1_8_reset_ras_error_count, }; -static int mmhub_v1_8_aca_bank_generate_report(struct aca_handle *handle, - struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data) +static int mmhub_v1_8_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, + enum aca_smu_type type, void *data) { - u64 status, misc0; + struct aca_bank_info info; + u64 misc0; int ret; - status = bank->regs[ACA_REG_IDX_STATUS]; - if ((type == ACA_ERROR_TYPE_UE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_FAULT) || - (type == ACA_ERROR_TYPE_CE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_CE)) { + ret = aca_bank_info_decode(bank, &info); + if (ret) + return ret; - ret = aca_bank_info_decode(bank, &report->info); - if (ret) - return ret; - - misc0 = bank->regs[ACA_REG_IDX_MISC0]; - report->count[type] = ACA_REG__MISC0__ERRCNT(misc0); + misc0 = bank->regs[ACA_REG_IDX_MISC0]; + switch (type) { + case ACA_SMU_TYPE_UE: + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE, + 1ULL); + break; + case ACA_SMU_TYPE_CE: + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + ACA_REG__MISC0__ERRCNT(misc0)); + break; + default: + return -EINVAL; } - return 0; + return ret; } /* reference to smu driver if header file */ @@ -741,7 +760,7 @@ static int mmhub_v1_8_err_codes[] = { }; static bool mmhub_v1_8_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, void *data) + enum aca_smu_type type, void *data) { u32 instlo; @@ -760,7 +779,7 @@ static bool mmhub_v1_8_aca_bank_is_valid(struct aca_handle *handle, struct aca_b } static const struct aca_bank_ops mmhub_v1_8_aca_bank_ops = { - .aca_bank_generate_report = mmhub_v1_8_aca_bank_generate_report, + .aca_bank_parser = mmhub_v1_8_aca_bank_parser, .aca_bank_is_valid = mmhub_v1_8_aca_bank_is_valid, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index a2bd2c3b1ef9..0c7275bca8f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -276,6 +276,8 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) timeout -= 10; } while (timeout > 1); + dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n"); + flr_done: atomic_set(&adev->reset_domain->in_gpu_reset, 0); up_write(&adev->reset_domain->sem); diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 77f5b55decf9..aba00d961627 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -309,6 +309,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) timeout -= 10; } while (timeout > 1); + dev_warn(adev->dev, "waiting IDH_FLR_NOTIFICATION_CMPL timeout\n"); + flr_done: atomic_set(&adev->reset_domain->in_gpu_reset, 0); up_write(&adev->reset_domain->sem); @@ -444,7 +446,6 @@ static void xgpu_nv_ras_poison_handler(struct amdgpu_device *adev, amdgpu_virt_fini_data_exchange(adev); xgpu_nv_send_access_requests_with_param(adev, IDH_RAS_POISON, block, 0, 0); - amdgpu_virt_init_data_exchange(adev); } } diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 4178f4e5dad7..b281462093f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -713,6 +713,8 @@ static const struct amd_ip_funcs navi10_ih_ip_funcs = { .set_clockgating_state = navi10_ih_set_clockgating_state, .set_powergating_state = navi10_ih_set_powergating_state, .get_clockgating_state = navi10_ih_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs navi10_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 4d7976b77767..12e54047bf79 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -110,7 +110,7 @@ static const struct amdgpu_video_codec_info sc_video_codecs_decode_array_vcn0[] {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; @@ -121,7 +121,7 @@ static const struct amdgpu_video_codec_info sc_video_codecs_decode_array_vcn1[] {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, }; @@ -199,7 +199,7 @@ static const struct amdgpu_video_codec_info yc_video_codecs_decode_array[] = { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; @@ -1131,4 +1131,6 @@ static const struct amd_ip_funcs nv_common_ip_funcs = { .set_clockgating_state = nv_common_set_clockgating_state, .set_powergating_state = nv_common_set_powergating_state, .get_clockgating_state = nv_common_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c index 78a95f8f370b..f08a32c18694 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v14_0.c @@ -169,7 +169,8 @@ static int psp_v14_0_bootloader_load_intf_drv(struct psp_context *psp) static int psp_v14_0_bootloader_load_dbg_drv(struct psp_context *psp) { - return psp_v14_0_bootloader_load_component(psp, &psp->dbg_drv, PSP_BL__LOAD_DBGDRV); + /* dbg_drv was renamed to had_drv in psp v14 */ + return psp_v14_0_bootloader_load_component(psp, &psp->dbg_drv, PSP_BL__LOAD_HADDRV); } static int psp_v14_0_bootloader_load_ras_drv(struct psp_context *psp) @@ -177,6 +178,10 @@ static int psp_v14_0_bootloader_load_ras_drv(struct psp_context *psp) return psp_v14_0_bootloader_load_component(psp, &psp->ras_drv, PSP_BL__LOAD_RASDRV); } +static int psp_v14_0_bootloader_load_ipkeymgr_drv(struct psp_context *psp) +{ + return psp_v14_0_bootloader_load_component(psp, &psp->ipkeymgr_drv, PSP_BL__LOAD_IPKEYMGRDRV); +} static int psp_v14_0_bootloader_load_sos(struct psp_context *psp) { @@ -653,6 +658,7 @@ static const struct psp_funcs psp_v14_0_funcs = { .bootloader_load_intf_drv = psp_v14_0_bootloader_load_intf_drv, .bootloader_load_dbg_drv = psp_v14_0_bootloader_load_dbg_drv, .bootloader_load_ras_drv = psp_v14_0_bootloader_load_ras_drv, + .bootloader_load_ipkeymgr_drv = psp_v14_0_bootloader_load_ipkeymgr_drv, .bootloader_load_sos = psp_v14_0_bootloader_load_sos, .ring_create = psp_v14_0_ring_create, .ring_stop = psp_v14_0_ring_stop, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index 07e19caf2bc1..ac8a9b9b3e52 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -1113,6 +1113,8 @@ static const struct amd_ip_funcs sdma_v2_4_ip_funcs = { .soft_reset = sdma_v2_4_soft_reset, .set_clockgating_state = sdma_v2_4_set_clockgating_state, .set_powergating_state = sdma_v2_4_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = { @@ -1176,7 +1178,7 @@ static void sdma_v2_4_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: unused + * @copy_flags: unused * * Copy GPU buffers using the DMA engine (VI). * Used by the amdgpu ttm implementation to move pages if @@ -1186,7 +1188,7 @@ static void sdma_v2_4_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 2ad615be4bb3..b8ebdc4ae6f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -1553,6 +1553,8 @@ static const struct amd_ip_funcs sdma_v3_0_ip_funcs = { .set_clockgating_state = sdma_v3_0_set_clockgating_state, .set_powergating_state = sdma_v3_0_set_powergating_state, .get_clockgating_state = sdma_v3_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = { @@ -1616,7 +1618,7 @@ static void sdma_v3_0_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: unused + * @copy_flags: unused * * Copy GPU buffers using the DMA engine (VI). * Used by the amdgpu ttm implementation to move pages if @@ -1626,7 +1628,7 @@ static void sdma_v3_0_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 43775cb67ff5..101038395c3b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2021,6 +2021,9 @@ static int sdma_v4_0_process_trap_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: SDMA trap\n"); instance = sdma_v4_0_irq_id_to_seq(entry->client_id); + if (instance < 0) + return instance; + switch (entry->ring_id) { case 0: amdgpu_fence_process(&adev->sdma.instance[instance].ring); @@ -2448,7 +2451,7 @@ static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: if a secure copy should be used + * @copy_flags: copy flags for the buffers * * Copy GPU buffers using the DMA engine (VEGA10/12). * Used by the amdgpu ttm implementation to move pages if @@ -2458,11 +2461,11 @@ static void sdma_v4_0_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | - SDMA_PKT_COPY_LINEAR_HEADER_TMZ(tmz ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 34237a1b1f2e..341b24d8320b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -368,7 +368,8 @@ static void sdma_v4_4_2_ring_emit_hdp_flush(struct amdgpu_ring *ring) u32 ref_and_mask = 0; const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg; - ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me; + ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 + << (ring->me % adev->sdma.num_inst_per_aid); sdma_v4_4_2_wait_reg_mem(ring, 0, 1, adev->nbio.funcs->get_hdp_flush_done_offset(adev), @@ -1602,19 +1603,9 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev, u32 sdma_cntl; sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL); - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, - DRAM_ECC_INT_ENABLE, 0); - WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); - break; - /* sdma ecc interrupt is enabled by default - * driver doesn't need to do anything to - * enable the interrupt */ - case AMDGPU_IRQ_STATE_ENABLE: - default: - break; - } + sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, DRAM_ECC_INT_ENABLE, + state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0); + WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); return 0; } @@ -1954,7 +1945,7 @@ static void sdma_v4_4_2_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: if a secure copy should be used + * @copy_flags: copy flags for the buffers * * Copy GPU buffers using the DMA engine. * Used by the amdgpu ttm implementation to move pages if @@ -1964,11 +1955,11 @@ static void sdma_v4_4_2_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | - SDMA_PKT_COPY_LINEAR_HEADER_TMZ(tmz ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); @@ -2189,35 +2180,39 @@ static const struct amdgpu_ras_block_hw_ops sdma_v4_4_2_ras_hw_ops = { .reset_ras_error_count = sdma_v4_4_2_reset_ras_error_count, }; -static int sdma_v4_4_2_aca_bank_generate_report(struct aca_handle *handle, - struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data) +static int sdma_v4_4_2_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, + enum aca_smu_type type, void *data) { - u64 status, misc0; + struct aca_bank_info info; + u64 misc0; int ret; - status = bank->regs[ACA_REG_IDX_STATUS]; - if ((type == ACA_ERROR_TYPE_UE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_FAULT) || - (type == ACA_ERROR_TYPE_CE && - ACA_REG__STATUS__ERRORCODEEXT(status) == ACA_EXTERROR_CODE_CE)) { + ret = aca_bank_info_decode(bank, &info); + if (ret) + return ret; - ret = aca_bank_info_decode(bank, &report->info); - if (ret) - return ret; - - misc0 = bank->regs[ACA_REG_IDX_MISC0]; - report->count[type] = ACA_REG__MISC0__ERRCNT(misc0); + misc0 = bank->regs[ACA_REG_IDX_MISC0]; + switch (type) { + case ACA_SMU_TYPE_UE: + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_UE, + 1ULL); + break; + case ACA_SMU_TYPE_CE: + ret = aca_error_cache_log_bank_error(handle, &info, ACA_ERROR_TYPE_CE, + ACA_REG__MISC0__ERRCNT(misc0)); + break; + default: + return -EINVAL; } - return 0; + return ret; } /* CODE_SDMA0 - CODE_SDMA4, reference to smu driver if header file */ static int sdma_v4_4_2_err_codes[] = { 33, 34, 35, 36 }; static bool sdma_v4_4_2_aca_bank_is_valid(struct aca_handle *handle, struct aca_bank *bank, - enum aca_error_type type, void *data) + enum aca_smu_type type, void *data) { u32 instlo; @@ -2236,7 +2231,7 @@ static bool sdma_v4_4_2_aca_bank_is_valid(struct aca_handle *handle, struct aca_ } static const struct aca_bank_ops sdma_v4_4_2_aca_bank_ops = { - .aca_bank_generate_report = sdma_v4_4_2_aca_bank_generate_report, + .aca_bank_parser = sdma_v4_4_2_aca_bank_parser, .aca_bank_is_valid = sdma_v4_4_2_aca_bank_is_valid, }; diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index 883e8a1b8a40..b7d33d78bce0 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -999,7 +999,8 @@ static int sdma_v5_0_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 20); if (r) { DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + if (!ring->is_mes_queue) + amdgpu_device_wb_free(adev, index); return r; } @@ -1805,7 +1806,7 @@ static void sdma_v5_0_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: if a secure copy should be used + * @copy_flags: copy flags for the buffers * * Copy GPU buffers using the DMA engine (NAVI10). * Used by the amdgpu ttm implementation to move pages if @@ -1815,11 +1816,11 @@ static void sdma_v5_0_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | - SDMA_PKT_COPY_LINEAR_HEADER_TMZ(tmz ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c index 42f4bd250def..cc9e961f0078 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c @@ -280,17 +280,21 @@ static void sdma_v5_2_ring_emit_hdp_flush(struct amdgpu_ring *ring) u32 ref_and_mask = 0; const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg; - ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me; + if (ring->me > 1) { + amdgpu_asic_flush_hdp(adev, ring); + } else { + ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me; - amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) | - SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) | - SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */ - amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2); - amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2); - amdgpu_ring_write(ring, ref_and_mask); /* reference */ - amdgpu_ring_write(ring, ref_and_mask); /* mask */ - amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) | - SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ + amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) | + SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) | + SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */ + amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2); + amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2); + amdgpu_ring_write(ring, ref_and_mask); /* reference */ + amdgpu_ring_write(ring, ref_and_mask); /* mask */ + amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) | + SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */ + } } /** @@ -835,7 +839,8 @@ static int sdma_v5_2_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 20); if (r) { DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + if (!ring->is_mes_queue) + amdgpu_device_wb_free(adev, index); return r; } @@ -1747,7 +1752,7 @@ static void sdma_v5_2_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: if a secure copy should be used + * @copy_flags: copy flags for the buffers * * Copy GPU buffers using the DMA engine. * Used by the amdgpu ttm implementation to move pages if @@ -1757,11 +1762,11 @@ static void sdma_v5_2_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | - SDMA_PKT_COPY_LINEAR_HEADER_TMZ(tmz ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c index 361835a61f2e..c833b6b8373b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c @@ -507,6 +507,13 @@ static int sdma_v6_0_gfx_resume(struct amdgpu_device *adev) /* set minor_ptr_update to 0 after wptr programed */ WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_QUEUE0_MINOR_PTR_UPDATE), 0); + /* Set up sdma hang watchdog */ + temp = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_WATCHDOG_CNTL)); + /* 100ms per unit */ + temp = REG_SET_FIELD(temp, SDMA0_WATCHDOG_CNTL, QUEUE_HANG_COUNT, + max(adev->usec_timeout/100000, 1)); + WREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_WATCHDOG_CNTL), temp); + /* Set up RESP_MODE to non-copy addresses */ temp = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_UTCL1_CNTL)); temp = REG_SET_FIELD(temp, SDMA0_UTCL1_CNTL, RESP_MODE, 3); @@ -854,7 +861,8 @@ static int sdma_v6_0_ring_test_ring(struct amdgpu_ring *ring) r = amdgpu_ring_alloc(ring, 5); if (r) { DRM_ERROR("amdgpu: dma failed to lock ring %d (%d).\n", ring->idx, r); - amdgpu_device_wb_free(adev, index); + if (!ring->is_mes_queue) + amdgpu_device_wb_free(adev, index); return r; } @@ -1567,7 +1575,7 @@ static void sdma_v6_0_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: if a secure copy should be used + * @copy_flags: copy flags for the buffers * * Copy GPU buffers using the DMA engine. * Used by the amdgpu ttm implementation to move pages if @@ -1577,11 +1585,11 @@ static void sdma_v6_0_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_COPY) | SDMA_PKT_COPY_LINEAR_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR) | - SDMA_PKT_COPY_LINEAR_HEADER_TMZ(tmz ? 1 : 0); + SDMA_PKT_COPY_LINEAR_HEADER_TMZ((copy_flags & AMDGPU_COPY_FLAGS_TMZ) ? 1 : 0); ib->ptr[ib->length_dw++] = byte_count - 1; ib->ptr[ib->length_dw++] = 0; /* src/dst endian swap */ ib->ptr[ib->length_dw++] = lower_32_bits(src_offset); diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index 23e4ef4fff7c..85235470e872 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1409,9 +1409,9 @@ static int si_gpu_pci_config_reset(struct amdgpu_device *adev) return r; } -static bool si_asic_supports_baco(struct amdgpu_device *adev) +static int si_asic_supports_baco(struct amdgpu_device *adev) { - return false; + return 0; } static enum amd_reset_method @@ -2706,6 +2706,8 @@ static const struct amd_ip_funcs si_common_ip_funcs = { .soft_reset = si_common_soft_reset, .set_clockgating_state = si_common_set_clockgating_state, .set_powergating_state = si_common_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ip_block_version si_common_ip_block = diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c index 9aa0e11ee673..11db5b755832 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dma.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c @@ -708,6 +708,8 @@ static const struct amd_ip_funcs si_dma_ip_funcs = { .soft_reset = si_dma_soft_reset, .set_clockgating_state = si_dma_set_clockgating_state, .set_powergating_state = si_dma_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs si_dma_ring_funcs = { @@ -761,7 +763,7 @@ static void si_dma_set_irq_funcs(struct amdgpu_device *adev) * @src_offset: src GPU address * @dst_offset: dst GPU address * @byte_count: number of bytes to xfer - * @tmz: is this a secure operation + * @copy_flags: unused * * Copy GPU buffers using the DMA engine (VI). * Used by the amdgpu ttm implementation to move pages if @@ -771,7 +773,7 @@ static void si_dma_emit_copy_buffer(struct amdgpu_ib *ib, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - bool tmz) + uint32_t copy_flags) { ib->ptr[ib->length_dw++] = DMA_PACKET(DMA_PACKET_COPY, 1, 0, 0, byte_count); diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c index cada9f300a7f..5237395e4fab 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c @@ -296,6 +296,8 @@ static const struct amd_ip_funcs si_ih_ip_funcs = { .soft_reset = si_ih_soft_reset, .set_clockgating_state = si_ih_set_clockgating_state, .set_powergating_state = si_ih_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs si_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c index 93f6772d1b24..481217c32d85 100644 --- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c +++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c @@ -92,7 +92,7 @@ static int sienna_cichlid_mode2_suspend_ip(struct amdgpu_device *adev) adev->ip_blocks[i].status.hw = false; } - return r; + return 0; } static int diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.c b/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.c new file mode 100644 index 000000000000..2a51a70d4846 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.c @@ -0,0 +1,62 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "smuio_v14_0_2.h" +#include "smuio/smuio_14_0_2_offset.h" +#include "smuio/smuio_14_0_2_sh_mask.h" +#include + +static u32 smuio_v14_0_2_get_rom_index_offset(struct amdgpu_device *adev) +{ + return SOC15_REG_OFFSET(SMUIO, 0, regROM_INDEX); +} + +static u32 smuio_v14_0_2_get_rom_data_offset(struct amdgpu_device *adev) +{ + return SOC15_REG_OFFSET(SMUIO, 0, regROM_DATA); +} + +static u64 smuio_v14_0_2_get_gpu_clock_counter(struct amdgpu_device *adev) +{ + u64 clock; + u64 clock_counter_lo, clock_counter_hi_pre, clock_counter_hi_after; + + preempt_disable(); + clock_counter_hi_pre = (u64)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); + clock_counter_lo = (u64)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); + /* the clock counter may be udpated during polling the counters */ + clock_counter_hi_after = (u64)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); + if (clock_counter_hi_pre != clock_counter_hi_after) + clock_counter_lo = (u64)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); + preempt_enable(); + + clock = clock_counter_lo | (clock_counter_hi_after << 32ULL); + + return clock; +} + +const struct amdgpu_smuio_funcs smuio_v14_0_2_funcs = { + .get_rom_index_offset = smuio_v14_0_2_get_rom_index_offset, + .get_rom_data_offset = smuio_v14_0_2_get_rom_data_offset, + .get_gpu_clock_counter = smuio_v14_0_2_get_gpu_clock_counter, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.h b/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.h new file mode 100644 index 000000000000..6e617f832d90 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/smuio_v14_0_2.h @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SMUIO_V14_0_2_H__ +#define __SMUIO_V14_0_2_H__ + +#include "soc15_common.h" + +extern const struct amdgpu_smuio_funcs smuio_v14_0_2_funcs; + +#endif /* __SMUIO_V14_0_2_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index dec81ccf6240..170f02e96717 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -143,7 +143,7 @@ static const struct amdgpu_video_codec_info rn_video_codecs_decode_array[] = {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, }; @@ -156,7 +156,7 @@ static const struct amdgpu_video_codecs rn_video_codecs_decode = static const struct amdgpu_video_codec_info vcn_4_0_3_video_codecs_decode_array[] = { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; @@ -502,7 +502,7 @@ static int soc15_asic_baco_reset(struct amdgpu_device *adev) static enum amd_reset_method soc15_asic_reset_method(struct amdgpu_device *adev) { - bool baco_reset = false; + int baco_reset = 0; bool connected_to_cpu = false; struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -540,7 +540,7 @@ soc15_asic_reset_method(struct amdgpu_device *adev) */ if (ras && adev->ras_enabled && adev->pm.fw_version <= 0x283400) - baco_reset = false; + baco_reset = 0; } else { baco_reset = amdgpu_dpm_is_baco_supported(adev); } @@ -620,7 +620,7 @@ static int soc15_asic_reset(struct amdgpu_device *adev) } } -static bool soc15_supports_baco(struct amdgpu_device *adev) +static int soc15_supports_baco(struct amdgpu_device *adev) { switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { case IP_VERSION(9, 0, 0): @@ -628,13 +628,13 @@ static bool soc15_supports_baco(struct amdgpu_device *adev) if (adev->asic_type == CHIP_VEGA20) { if (adev->psp.sos.fw_version >= 0x80067) return amdgpu_dpm_is_baco_supported(adev); - return false; + return 0; } else { return amdgpu_dpm_is_baco_supported(adev); } break; default: - return false; + return 0; } } @@ -1501,4 +1501,6 @@ static const struct amd_ip_funcs soc15_common_ip_funcs = { .set_clockgating_state = soc15_common_set_clockgating_state, .set_powergating_state = soc15_common_set_powergating_state, .get_clockgating_state= soc15_common_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.h b/drivers/gpu/drm/amd/amdgpu/soc15.h index 1444b7765e4b..282584a48be0 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.h +++ b/drivers/gpu/drm/amd/amdgpu/soc15.h @@ -88,6 +88,8 @@ struct soc15_ras_field_entry { }; #define SOC15_REG_ENTRY(ip, inst, reg) ip##_HWIP, inst, reg##_BASE_IDX, reg +#define SOC15_REG_ENTRY_STR(ip, inst, reg) \ + { ip##_HWIP, inst, reg##_BASE_IDX, reg, #reg } #define SOC15_REG_ENTRY_OFFSET(entry) (adev->reg_offset[entry.hwip][entry.inst][entry.seg] + entry.reg_offset) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 581a3bd11481..fb6797467571 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -72,7 +72,7 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_encode_vcn1 = { static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_decode_array_vcn0[] = { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1, 8192, 4352, 0)}, }; @@ -80,7 +80,7 @@ static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_decode_array_ static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_decode_array_vcn1[] = { {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 8192, 4352, 186)}, - {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)}, + {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 16384, 16384, 0)}, {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 8192, 4352, 0)}, }; @@ -457,10 +457,8 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev) { switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { case IP_VERSION(11, 0, 0): - return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC); case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 3): - return false; default: return true; } @@ -722,7 +720,10 @@ static int soc21_common_early_init(void *handle) AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_GFX_PG; - adev->external_rev_id = adev->rev_id + 0x1; + if (adev->rev_id == 0) + adev->external_rev_id = 0x1; + else + adev->external_rev_id = adev->rev_id + 0x10; break; case IP_VERSION(11, 5, 1): adev->cg_flags = @@ -869,10 +870,35 @@ static int soc21_common_suspend(void *handle) return soc21_common_hw_fini(adev); } +static bool soc21_need_reset_on_resume(struct amdgpu_device *adev) +{ + u32 sol_reg1, sol_reg2; + + /* Will reset for the following suspend abort cases. + * 1) Only reset dGPU side. + * 2) S3 suspend got aborted and TOS is active. + */ + if (!(adev->flags & AMD_IS_APU) && adev->in_s3 && + !adev->suspend_complete) { + sol_reg1 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81); + msleep(100); + sol_reg2 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81); + + return (sol_reg1 != sol_reg2); + } + + return false; +} + static int soc21_common_resume(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (soc21_need_reset_on_resume(adev)) { + dev_info(adev->dev, "S3 suspend aborted, resetting..."); + soc21_asic_reset(adev); + } + return soc21_common_hw_init(adev); } @@ -959,4 +985,6 @@ static const struct amd_ip_funcs soc21_common_ip_funcs = { .set_clockgating_state = soc21_common_set_clockgating_state, .set_powergating_state = soc21_common_set_powergating_state, .get_clockgating_state = soc21_common_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; diff --git a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h index 056d4df8fa1f..3ac56a9645eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h +++ b/drivers/gpu/drm/amd/amdgpu/ta_ras_if.h @@ -146,6 +146,7 @@ struct ta_ras_mca_addr { uint32_t ch_inst; uint32_t umc_inst; uint32_t node_inst; + uint32_t socket_id; }; struct ta_ras_phy_addr { diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 450b6e831509..24d49d813607 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -486,6 +486,8 @@ static const struct amd_ip_funcs tonga_ih_ip_funcs = { .post_soft_reset = tonga_ih_post_soft_reset, .set_clockgating_state = tonga_ih_set_clockgating_state, .set_powergating_state = tonga_ih_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ih_funcs tonga_ih_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c index 77af4e25ff46..bfe61d86ee6c 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.c @@ -28,27 +28,7 @@ #include "umc/umc_12_0_0_sh_mask.h" #include "mp/mp_13_0_6_sh_mask.h" -const uint32_t - umc_v12_0_channel_idx_tbl[] - [UMC_V12_0_UMC_INSTANCE_NUM] - [UMC_V12_0_CHANNEL_INSTANCE_NUM] = { - {{3, 7, 11, 15, 2, 6, 10, 14}, {1, 5, 9, 13, 0, 4, 8, 12}, - {19, 23, 27, 31, 18, 22, 26, 30}, {17, 21, 25, 29, 16, 20, 24, 28}}, - {{47, 43, 39, 35, 46, 42, 38, 34}, {45, 41, 37, 33, 44, 40, 36, 32}, - {63, 59, 55, 51, 62, 58, 54, 50}, {61, 57, 53, 49, 60, 56, 52, 48}}, - {{79, 75, 71, 67, 78, 74, 70, 66}, {77, 73, 69, 65, 76, 72, 68, 64}, - {95, 91, 87, 83, 94, 90, 86, 82}, {93, 89, 85, 81, 92, 88, 84, 80}}, - {{99, 103, 107, 111, 98, 102, 106, 110}, {97, 101, 105, 109, 96, 100, 104, 108}, - {115, 119, 123, 127, 114, 118, 122, 126}, {113, 117, 121, 125, 112, 116, 120, 124}} - }; - -/* mapping of MCA error address to normalized address */ -static const uint32_t umc_v12_0_ma2na_mapping[] = { - 0, 5, 6, 8, 9, 14, 12, 13, - 10, 11, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, - 24, 7, 29, 30, -}; +#define MAX_ECC_NUM_PER_RETIREMENT 32 static inline uint64_t get_umc_v12_0_reg_offset(struct amdgpu_device *adev, uint32_t node_inst, @@ -192,99 +172,22 @@ static void umc_v12_0_query_ras_error_count(struct amdgpu_device *adev, umc_v12_0_reset_error_count(adev); } -static bool umc_v12_0_bit_wise_xor(uint32_t val) -{ - bool result = 0; - int i; - - for (i = 0; i < 32; i++) - result = result ^ ((val >> i) & 0x1); - - return result; -} - -static void umc_v12_0_mca_addr_to_pa(struct amdgpu_device *adev, - uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst, - uint32_t node_inst, - struct ta_ras_query_address_output *addr_out) -{ - uint32_t channel_index, i; - uint64_t na, soc_pa; - uint32_t bank_hash0, bank_hash1, bank_hash2, bank_hash3, col, row; - uint32_t bank0, bank1, bank2, bank3, bank; - - bank_hash0 = (err_addr >> UMC_V12_0_MCA_B0_BIT) & 0x1ULL; - bank_hash1 = (err_addr >> UMC_V12_0_MCA_B1_BIT) & 0x1ULL; - bank_hash2 = (err_addr >> UMC_V12_0_MCA_B2_BIT) & 0x1ULL; - bank_hash3 = (err_addr >> UMC_V12_0_MCA_B3_BIT) & 0x1ULL; - col = (err_addr >> 1) & 0x1fULL; - row = (err_addr >> 10) & 0x3fffULL; - - /* apply bank hash algorithm */ - bank0 = - bank_hash0 ^ (UMC_V12_0_XOR_EN0 & - (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR0) ^ - (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR0)))); - bank1 = - bank_hash1 ^ (UMC_V12_0_XOR_EN1 & - (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR1) ^ - (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR1)))); - bank2 = - bank_hash2 ^ (UMC_V12_0_XOR_EN2 & - (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR2) ^ - (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR2)))); - bank3 = - bank_hash3 ^ (UMC_V12_0_XOR_EN3 & - (umc_v12_0_bit_wise_xor(col & UMC_V12_0_COL_XOR3) ^ - (umc_v12_0_bit_wise_xor(row & UMC_V12_0_ROW_XOR3)))); - - bank = bank0 | (bank1 << 1) | (bank2 << 2) | (bank3 << 3); - err_addr &= ~0x3c0ULL; - err_addr |= (bank << UMC_V12_0_MCA_B0_BIT); - - na = 0x0; - /* convert mca error address to normalized address */ - for (i = 1; i < ARRAY_SIZE(umc_v12_0_ma2na_mapping); i++) - na |= ((err_addr >> i) & 0x1ULL) << umc_v12_0_ma2na_mapping[i]; - - channel_index = - adev->umc.channel_idx_tbl[node_inst * adev->umc.umc_inst_num * - adev->umc.channel_inst_num + - umc_inst * adev->umc.channel_inst_num + - ch_inst]; - /* translate umc channel address to soc pa, 3 parts are included */ - soc_pa = ADDR_OF_32KB_BLOCK(na) | - ADDR_OF_256B_BLOCK(channel_index) | - OFFSET_IN_256B_BLOCK(na); - - /* the umc channel bits are not original values, they are hashed */ - UMC_V12_0_SET_CHANNEL_HASH(channel_index, soc_pa); - - addr_out->pa.pa = soc_pa; - addr_out->pa.bank = bank; - addr_out->pa.channel_idx = channel_index; -} - static void umc_v12_0_convert_error_address(struct amdgpu_device *adev, - struct ras_err_data *err_data, uint64_t err_addr, - uint32_t ch_inst, uint32_t umc_inst, - uint32_t node_inst) + struct ras_err_data *err_data, + struct ta_ras_query_address_input *addr_in) { uint32_t col, row, row_xor, bank, channel_index; - uint64_t soc_pa, retired_page, column; - struct ta_ras_query_address_input addr_in; + uint64_t soc_pa, retired_page, column, err_addr; struct ta_ras_query_address_output addr_out; - addr_in.addr_type = TA_RAS_MCA_TO_PA; - addr_in.ma.err_addr = err_addr; - addr_in.ma.ch_inst = ch_inst; - addr_in.ma.umc_inst = umc_inst; - addr_in.ma.node_inst = node_inst; + err_addr = addr_in->ma.err_addr; + addr_in->addr_type = TA_RAS_MCA_TO_PA; + if (psp_ras_query_address(&adev->psp, addr_in, &addr_out)) { + dev_warn(adev->dev, "Failed to query RAS physical address for 0x%llx", + err_addr); - if (psp_ras_query_address(&adev->psp, &addr_in, &addr_out)) - /* fallback to old path if fail to get pa from psp */ - umc_v12_0_mca_addr_to_pa(adev, err_addr, ch_inst, umc_inst, - node_inst, &addr_out); + return; + } soc_pa = addr_out.pa.pa; bank = addr_out.pa.bank; @@ -309,7 +212,7 @@ static void umc_v12_0_convert_error_address(struct amdgpu_device *adev, "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n", retired_page, row, col, bank, channel_index); amdgpu_umc_fill_error_record(err_data, err_addr, - retired_page, channel_index, umc_inst); + retired_page, channel_index, addr_in->ma.umc_inst); /* shift R13 bit */ retired_page ^= (0x1ULL << UMC_V12_0_PA_R13_BIT); @@ -317,18 +220,79 @@ static void umc_v12_0_convert_error_address(struct amdgpu_device *adev, "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n", retired_page, row_xor, col, bank, channel_index); amdgpu_umc_fill_error_record(err_data, err_addr, - retired_page, channel_index, umc_inst); + retired_page, channel_index, addr_in->ma.umc_inst); } } +static int umc_v12_0_convert_err_addr(struct amdgpu_device *adev, + struct ta_ras_query_address_input *addr_in, + uint64_t *pfns, int len) +{ + uint32_t col, row, row_xor, bank, channel_index; + uint64_t soc_pa, retired_page, column, err_addr; + struct ta_ras_query_address_output addr_out; + uint32_t pos = 0; + + err_addr = addr_in->ma.err_addr; + addr_in->addr_type = TA_RAS_MCA_TO_PA; + if (psp_ras_query_address(&adev->psp, addr_in, &addr_out)) { + dev_warn(adev->dev, "Failed to query RAS physical address for 0x%llx", + err_addr); + return 0; + } + + soc_pa = addr_out.pa.pa; + bank = addr_out.pa.bank; + channel_index = addr_out.pa.channel_idx; + + col = (err_addr >> 1) & 0x1fULL; + row = (err_addr >> 10) & 0x3fffULL; + row_xor = row ^ (0x1ULL << 13); + /* clear [C3 C2] in soc physical address */ + soc_pa &= ~(0x3ULL << UMC_V12_0_PA_C2_BIT); + /* clear [C4] in soc physical address */ + soc_pa &= ~(0x1ULL << UMC_V12_0_PA_C4_BIT); + + /* loop for all possibilities of [C4 C3 C2] */ + for (column = 0; column < UMC_V12_0_NA_MAP_PA_NUM; column++) { + retired_page = soc_pa | ((column & 0x3) << UMC_V12_0_PA_C2_BIT); + retired_page |= (((column & 0x4) >> 2) << UMC_V12_0_PA_C4_BIT); + + if (pos >= len) + return 0; + pfns[pos++] = retired_page >> AMDGPU_GPU_PAGE_SHIFT; + + /* include column bit 0 and 1 */ + col &= 0x3; + col |= (column << 2); + dev_info(adev->dev, + "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n", + retired_page, row, col, bank, channel_index); + + /* shift R13 bit */ + retired_page ^= (0x1ULL << UMC_V12_0_PA_R13_BIT); + + if (pos >= len) + return 0; + pfns[pos++] = retired_page >> AMDGPU_GPU_PAGE_SHIFT; + + dev_info(adev->dev, + "Error Address(PA):0x%-10llx Row:0x%-4x Col:0x%-2x Bank:0x%x Channel:0x%x\n", + retired_page, row_xor, col, bank, channel_index); + } + + return pos; +} + static int umc_v12_0_query_error_address(struct amdgpu_device *adev, uint32_t node_inst, uint32_t umc_inst, uint32_t ch_inst, void *data) { + struct ras_err_data *err_data = (struct ras_err_data *)data; + struct ta_ras_query_address_input addr_in; uint64_t mc_umc_status_addr; uint64_t mc_umc_status, err_addr; uint64_t mc_umc_addrt0; - struct ras_err_data *err_data = (struct ras_err_data *)data; uint64_t umc_reg_offset = get_umc_v12_0_reg_offset(adev, node_inst, umc_inst, ch_inst); @@ -357,8 +321,19 @@ static int umc_v12_0_query_error_address(struct amdgpu_device *adev, err_addr = REG_GET_FIELD(err_addr, MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); - umc_v12_0_convert_error_address(adev, err_data, err_addr, - ch_inst, umc_inst, node_inst); + if (!adev->aid_mask && + adev->smuio.funcs && + adev->smuio.funcs->get_socket_id) + addr_in.ma.socket_id = adev->smuio.funcs->get_socket_id(adev); + else + addr_in.ma.socket_id = 0; + + addr_in.ma.err_addr = err_addr; + addr_in.ma.ch_inst = ch_inst; + addr_in.ma.umc_inst = umc_inst; + addr_in.ma.node_inst = node_inst; + + umc_v12_0_convert_error_address(adev, err_data, &addr_in); } /* clear umc status */ @@ -401,13 +376,20 @@ static int umc_v12_0_err_cnt_init_per_channel(struct amdgpu_device *adev, return 0; } +#ifdef TO_BE_REMOVED static void umc_v12_0_ecc_info_query_ras_error_count(struct amdgpu_device *adev, void *ras_error_status) { + struct ras_query_context qctx; + + memset(&qctx, 0, sizeof(qctx)); + qctx.event_id = amdgpu_ras_acquire_event_id(adev, amdgpu_ras_intr_triggered() ? + RAS_EVENT_TYPE_ISR : RAS_EVENT_TYPE_INVALID); + amdgpu_mca_smu_log_ras_error(adev, - AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_CE, ras_error_status); + AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_CE, ras_error_status, &qctx); amdgpu_mca_smu_log_ras_error(adev, - AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_UE, ras_error_status); + AMDGPU_RAS_BLOCK__UMC, AMDGPU_MCA_ERROR_TYPE_UE, ras_error_status, &qctx); } static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *adev, @@ -418,12 +400,16 @@ static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *ade struct ras_err_info *err_info; struct ras_err_addr *mca_err_addr, *tmp; struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + struct ta_ras_query_address_input addr_in; for_each_ras_error(err_node, err_data) { err_info = &err_node->err_info; if (list_empty(&err_info->err_addr_list)) continue; + addr_in.ma.node_inst = err_info->mcm_info.die_id; + addr_in.ma.socket_id = err_info->mcm_info.socket_id; + list_for_each_entry_safe(mca_err_addr, tmp, &err_info->err_addr_list, node) { mc_umc_status = mca_err_addr->err_status; if (mc_umc_status && @@ -439,6 +425,10 @@ static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *ade MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); InstanceIdLo = REG_GET_FIELD(mca_ipid, MCMP1_IPIDT0, InstanceIdLo); + addr_in.ma.err_addr = err_addr; + addr_in.ma.ch_inst = MCA_IPID_LO_2_UMC_CH(InstanceIdLo); + addr_in.ma.umc_inst = MCA_IPID_LO_2_UMC_INST(InstanceIdLo); + dev_info(adev->dev, "UMC:IPID:0x%llx, aid:%d, inst:%d, ch:%d, err_addr:0x%llx\n", mca_ipid, err_info->mcm_info.die_id, @@ -447,10 +437,7 @@ static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *ade err_addr); umc_v12_0_convert_error_address(adev, - err_data, err_addr, - MCA_IPID_LO_2_UMC_CH(InstanceIdLo), - MCA_IPID_LO_2_UMC_INST(InstanceIdLo), - err_info->mcm_info.die_id); + err_data, &addr_in); } /* Delete error address node from list and free memory */ @@ -458,6 +445,7 @@ static void umc_v12_0_ecc_info_query_ras_error_address(struct amdgpu_device *ade } } } +#endif static bool umc_v12_0_check_ecc_err_status(struct amdgpu_device *adev, enum amdgpu_mca_error_type type, void *ras_error_status) @@ -498,43 +486,49 @@ const struct amdgpu_ras_block_hw_ops umc_v12_0_ras_hw_ops = { .query_ras_error_address = umc_v12_0_query_ras_error_address, }; -static int umc_v12_0_aca_bank_generate_report(struct aca_handle *handle, struct aca_bank *bank, enum aca_error_type type, - struct aca_bank_report *report, void *data) +static int umc_v12_0_aca_bank_parser(struct aca_handle *handle, struct aca_bank *bank, + enum aca_smu_type type, void *data) { struct amdgpu_device *adev = handle->adev; - u64 status; + struct aca_bank_info info; + enum aca_error_type err_type; + u64 status, count; + u32 ext_error_code; int ret; - ret = aca_bank_info_decode(bank, &report->info); + status = bank->regs[ACA_REG_IDX_STATUS]; + if (umc_v12_0_is_deferred_error(adev, status)) + err_type = ACA_ERROR_TYPE_DEFERRED; + else if (umc_v12_0_is_uncorrectable_error(adev, status)) + err_type = ACA_ERROR_TYPE_UE; + else if (umc_v12_0_is_correctable_error(adev, status)) + err_type = ACA_ERROR_TYPE_CE; + else + return 0; + + ret = aca_bank_info_decode(bank, &info); if (ret) return ret; - status = bank->regs[ACA_REG_IDX_STATUS]; - switch (type) { - case ACA_ERROR_TYPE_UE: - if (umc_v12_0_is_uncorrectable_error(adev, status)) { - report->count[type] = 1; - } - break; - case ACA_ERROR_TYPE_CE: - if (umc_v12_0_is_correctable_error(adev, status)) { - report->count[type] = 1; - } - break; - default: - return -EINVAL; - } + amdgpu_umc_update_ecc_status(adev, + bank->regs[ACA_REG_IDX_STATUS], + bank->regs[ACA_REG_IDX_IPID], + bank->regs[ACA_REG_IDX_ADDR]); - return 0; + ext_error_code = ACA_REG__STATUS__ERRORCODEEXT(status); + count = ext_error_code == 0 ? + ACA_REG__MISC0__ERRCNT(bank->regs[ACA_REG_IDX_MISC0]) : 1ULL; + + return aca_error_cache_log_bank_error(handle, &info, err_type, count); } static const struct aca_bank_ops umc_v12_0_aca_bank_ops = { - .aca_bank_generate_report = umc_v12_0_aca_bank_generate_report, + .aca_bank_parser = umc_v12_0_aca_bank_parser, }; const struct aca_info umc_v12_0_aca_info = { .hwip = ACA_HWIP_TYPE_UMC, - .mask = ACA_ERROR_UE_MASK | ACA_ERROR_CE_MASK, + .mask = ACA_ERROR_UE_MASK | ACA_ERROR_CE_MASK | ACA_ERROR_DEFERRED_MASK, .bank_ops = &umc_v12_0_aca_bank_ops, }; @@ -554,6 +548,152 @@ static int umc_v12_0_ras_late_init(struct amdgpu_device *adev, struct ras_common return 0; } +static int umc_v12_0_update_ecc_status(struct amdgpu_device *adev, + uint64_t status, uint64_t ipid, uint64_t addr) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + uint16_t hwid, mcatype; + struct ta_ras_query_address_input addr_in; + uint64_t page_pfn[UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL]; + uint64_t err_addr, hash_val = 0; + struct ras_ecc_err *ecc_err; + int count; + int ret; + + hwid = REG_GET_FIELD(ipid, MCMP1_IPIDT0, HardwareID); + mcatype = REG_GET_FIELD(ipid, MCMP1_IPIDT0, McaType); + + if ((hwid != MCA_UMC_HWID_V12_0) || (mcatype != MCA_UMC_MCATYPE_V12_0)) + return 0; + + if (!status) + return 0; + + if (!umc_v12_0_is_deferred_error(adev, status)) + return 0; + + err_addr = REG_GET_FIELD(addr, + MCA_UMC_UMC0_MCUMC_ADDRT0, ErrorAddr); + + dev_info(adev->dev, + "UMC:IPID:0x%llx, socket:%llu, aid:%llu, inst:%llu, ch:%llu, err_addr:0x%llx\n", + ipid, + MCA_IPID_2_SOCKET_ID(ipid), + MCA_IPID_2_DIE_ID(ipid), + MCA_IPID_2_UMC_INST(ipid), + MCA_IPID_2_UMC_CH(ipid), + err_addr); + + memset(page_pfn, 0, sizeof(page_pfn)); + + memset(&addr_in, 0, sizeof(addr_in)); + addr_in.ma.err_addr = err_addr; + addr_in.ma.ch_inst = MCA_IPID_2_UMC_CH(ipid); + addr_in.ma.umc_inst = MCA_IPID_2_UMC_INST(ipid); + addr_in.ma.node_inst = MCA_IPID_2_DIE_ID(ipid); + addr_in.ma.socket_id = MCA_IPID_2_SOCKET_ID(ipid); + + count = umc_v12_0_convert_err_addr(adev, + &addr_in, page_pfn, ARRAY_SIZE(page_pfn)); + if (count <= 0) { + dev_warn(adev->dev, "Fail to convert error address! count:%d\n", count); + return 0; + } + + ret = amdgpu_umc_build_pages_hash(adev, + page_pfn, count, &hash_val); + if (ret) { + dev_err(adev->dev, "Fail to build error pages hash\n"); + return ret; + } + + ecc_err = kzalloc(sizeof(*ecc_err), GFP_KERNEL); + if (!ecc_err) + return -ENOMEM; + + ecc_err->err_pages.pfn = kcalloc(count, sizeof(*ecc_err->err_pages.pfn), GFP_KERNEL); + if (!ecc_err->err_pages.pfn) { + kfree(ecc_err); + return -ENOMEM; + } + + memcpy(ecc_err->err_pages.pfn, page_pfn, count * sizeof(*ecc_err->err_pages.pfn)); + ecc_err->err_pages.count = count; + + ecc_err->hash_index = hash_val; + ecc_err->status = status; + ecc_err->ipid = ipid; + ecc_err->addr = addr; + + ret = amdgpu_umc_logs_ecc_err(adev, &con->umc_ecc_log.de_page_tree, ecc_err); + if (ret) { + if (ret == -EEXIST) + con->umc_ecc_log.de_updated = true; + else + dev_err(adev->dev, "Fail to log ecc error! ret:%d\n", ret); + + kfree(ecc_err->err_pages.pfn); + kfree(ecc_err); + return ret; + } + + con->umc_ecc_log.de_updated = true; + + return 0; +} + +static int umc_v12_0_fill_error_record(struct amdgpu_device *adev, + struct ras_ecc_err *ecc_err, void *ras_error_status) +{ + struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status; + uint32_t i = 0; + int ret = 0; + + if (!err_data || !ecc_err) + return -EINVAL; + + for (i = 0; i < ecc_err->err_pages.count; i++) { + ret = amdgpu_umc_fill_error_record(err_data, + ecc_err->addr, + ecc_err->err_pages.pfn[i] << AMDGPU_GPU_PAGE_SHIFT, + MCA_IPID_2_UMC_CH(ecc_err->ipid), + MCA_IPID_2_UMC_INST(ecc_err->ipid)); + if (ret) + break; + } + + err_data->de_count++; + + return ret; +} + +static void umc_v12_0_query_ras_ecc_err_addr(struct amdgpu_device *adev, + void *ras_error_status) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct ras_ecc_err *entries[MAX_ECC_NUM_PER_RETIREMENT]; + struct radix_tree_root *ecc_tree; + int new_detected, ret, i; + + ecc_tree = &con->umc_ecc_log.de_page_tree; + + mutex_lock(&con->umc_ecc_log.lock); + new_detected = radix_tree_gang_lookup_tag(ecc_tree, (void **)entries, + 0, ARRAY_SIZE(entries), UMC_ECC_NEW_DETECTED_TAG); + for (i = 0; i < new_detected; i++) { + if (!entries[i]) + continue; + + ret = umc_v12_0_fill_error_record(adev, entries[i], ras_error_status); + if (ret) { + dev_err(adev->dev, "Fail to fill umc error record, ret:%d\n", ret); + break; + } + radix_tree_tag_clear(ecc_tree, entries[i]->hash_index, UMC_ECC_NEW_DETECTED_TAG); + } + mutex_unlock(&con->umc_ecc_log.lock); +} + struct amdgpu_umc_ras umc_v12_0_ras = { .ras_block = { .hw_ops = &umc_v12_0_ras_hw_ops, @@ -561,8 +701,8 @@ struct amdgpu_umc_ras umc_v12_0_ras = { }, .err_cnt_init = umc_v12_0_err_cnt_init, .query_ras_poison_mode = umc_v12_0_query_ras_poison_mode, - .ecc_info_query_ras_error_count = umc_v12_0_ecc_info_query_ras_error_count, - .ecc_info_query_ras_error_address = umc_v12_0_ecc_info_query_ras_error_address, + .ecc_info_query_ras_error_address = umc_v12_0_query_ras_ecc_err_addr, .check_ecc_err_status = umc_v12_0_check_ecc_err_status, + .update_ecc_status = umc_v12_0_update_ecc_status, }; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h index 5973bfb14fce..b4974793850b 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h +++ b/drivers/gpu/drm/amd/amdgpu/umc_v12_0.h @@ -55,83 +55,38 @@ #define UMC_V12_0_NA_MAP_PA_NUM 8 /* R13 bit shift should be considered, double the number */ #define UMC_V12_0_BAD_PAGE_NUM_PER_CHANNEL (UMC_V12_0_NA_MAP_PA_NUM * 2) -/* bank bits in MCA error address */ -#define UMC_V12_0_MCA_B0_BIT 6 -#define UMC_V12_0_MCA_B1_BIT 7 -#define UMC_V12_0_MCA_B2_BIT 8 -#define UMC_V12_0_MCA_B3_BIT 9 + /* column bits in SOC physical address */ #define UMC_V12_0_PA_C2_BIT 15 #define UMC_V12_0_PA_C4_BIT 21 /* row bits in SOC physical address */ #define UMC_V12_0_PA_R13_BIT 35 -/* channel index bits in SOC physical address */ -#define UMC_V12_0_PA_CH4_BIT 12 -#define UMC_V12_0_PA_CH5_BIT 13 -#define UMC_V12_0_PA_CH6_BIT 14 -/* bank hash settings */ -#define UMC_V12_0_XOR_EN0 1 -#define UMC_V12_0_XOR_EN1 1 -#define UMC_V12_0_XOR_EN2 1 -#define UMC_V12_0_XOR_EN3 1 -#define UMC_V12_0_COL_XOR0 0x0 -#define UMC_V12_0_COL_XOR1 0x0 -#define UMC_V12_0_COL_XOR2 0x800 -#define UMC_V12_0_COL_XOR3 0x1000 -#define UMC_V12_0_ROW_XOR0 0x11111 -#define UMC_V12_0_ROW_XOR1 0x22222 -#define UMC_V12_0_ROW_XOR2 0x4444 -#define UMC_V12_0_ROW_XOR3 0x8888 - -/* channel hash settings */ -#define UMC_V12_0_HASH_4K 0 -#define UMC_V12_0_HASH_64K 1 -#define UMC_V12_0_HASH_2M 1 -#define UMC_V12_0_HASH_1G 1 -#define UMC_V12_0_HASH_1T 1 - -/* XOR some bits of PA into CH4~CH6 bits (bits 12~14 of PA), - * hash bit is only effective when related setting is enabled - */ -#define UMC_V12_0_CHANNEL_HASH_CH4(channel_idx, pa) ((((channel_idx) >> 5) & 0x1) ^ \ - (((pa) >> 20) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \ - (((pa) >> 27) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \ - (((pa) >> 34) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \ - (((pa) >> 41) & 0x1ULL & UMC_V12_0_HASH_1T)) -#define UMC_V12_0_CHANNEL_HASH_CH5(channel_idx, pa) ((((channel_idx) >> 6) & 0x1) ^ \ - (((pa) >> 21) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \ - (((pa) >> 28) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \ - (((pa) >> 35) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \ - (((pa) >> 42) & 0x1ULL & UMC_V12_0_HASH_1T)) -#define UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) ((((channel_idx) >> 4) & 0x1) ^ \ - (((pa) >> 19) & 0x1ULL & UMC_V12_0_HASH_64K) ^ \ - (((pa) >> 26) & 0x1ULL & UMC_V12_0_HASH_2M) ^ \ - (((pa) >> 33) & 0x1ULL & UMC_V12_0_HASH_1G) ^ \ - (((pa) >> 40) & 0x1ULL & UMC_V12_0_HASH_1T) ^ \ - (((pa) >> 47) & 0x1ULL & UMC_V12_0_HASH_4K)) -#define UMC_V12_0_SET_CHANNEL_HASH(channel_idx, pa) do { \ - (pa) &= ~(0x7ULL << UMC_V12_0_PA_CH4_BIT); \ - (pa) |= (UMC_V12_0_CHANNEL_HASH_CH4(channel_idx, pa) << UMC_V12_0_PA_CH4_BIT); \ - (pa) |= (UMC_V12_0_CHANNEL_HASH_CH5(channel_idx, pa) << UMC_V12_0_PA_CH5_BIT); \ - (pa) |= (UMC_V12_0_CHANNEL_HASH_CH6(channel_idx, pa) << UMC_V12_0_PA_CH6_BIT); \ - } while (0) +#define MCA_UMC_HWID_V12_0 0x96 +#define MCA_UMC_MCATYPE_V12_0 0x0 #define MCA_IPID_LO_2_UMC_CH(_ipid_lo) (((((_ipid_lo) >> 20) & 0x1) * 4) + \ (((_ipid_lo) >> 12) & 0xF)) #define MCA_IPID_LO_2_UMC_INST(_ipid_lo) (((_ipid_lo) >> 21) & 0x7) +#define MCA_IPID_2_DIE_ID(ipid) ((REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi) >> 2) & 0x03) + +#define MCA_IPID_2_UMC_CH(ipid) \ + (MCA_IPID_LO_2_UMC_CH(REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo))) + +#define MCA_IPID_2_UMC_INST(ipid) \ + (MCA_IPID_LO_2_UMC_INST(REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo))) + +#define MCA_IPID_2_SOCKET_ID(ipid) \ + (((REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdLo) & 0x1) << 2) | \ + (REG_GET_FIELD(ipid, MCMP1_IPIDT0, InstanceIdHi) & 0x03)) + bool umc_v12_0_is_deferred_error(struct amdgpu_device *adev, uint64_t mc_umc_status); bool umc_v12_0_is_uncorrectable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); bool umc_v12_0_is_correctable_error(struct amdgpu_device *adev, uint64_t mc_umc_status); typedef bool (*check_error_type_func)(struct amdgpu_device *adev, uint64_t mc_umc_status); -extern const uint32_t - umc_v12_0_channel_idx_tbl[] - [UMC_V12_0_UMC_INSTANCE_NUM] - [UMC_V12_0_CHANNEL_INSTANCE_NUM]; - extern struct amdgpu_umc_ras umc_v12_0_ras; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c index c4c77257710c..a32f87992f20 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c @@ -442,11 +442,6 @@ static void umc_v8_10_ecc_info_query_ras_error_address(struct amdgpu_device *ade umc_v8_10_ecc_info_query_error_address, ras_error_status); } -static void umc_v8_10_set_eeprom_table_version(struct amdgpu_ras_eeprom_table_header *hdr) -{ - hdr->version = RAS_TABLE_VER_V2_1; -} - const struct amdgpu_ras_block_hw_ops umc_v8_10_ras_hw_ops = { .query_ras_error_count = umc_v8_10_query_ras_error_count, .query_ras_error_address = umc_v8_10_query_ras_error_address, @@ -460,5 +455,4 @@ struct amdgpu_umc_ras umc_v8_10_ras = { .query_ras_poison_mode = umc_v8_10_query_ras_poison_mode, .ecc_info_query_ras_error_count = umc_v8_10_ecc_info_query_ras_error_count, .ecc_info_query_ras_error_address = umc_v8_10_ecc_info_query_ras_error_address, - .set_eeprom_table_version = umc_v8_10_set_eeprom_table_version, }; diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c index 84368cf1e175..bd57896ab85d 100644 --- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c @@ -225,6 +225,8 @@ static int umsch_mm_v4_0_ring_start(struct amdgpu_umsch_mm *umsch) WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_SIZE, ring->ring_size); + ring->wptr = 0; + data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE); data &= ~(VCN_RB_ENABLE__AUDIO_RB_EN_MASK); WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data); diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c index a6006f231c65..805d6662c88b 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v3_1.c @@ -819,6 +819,8 @@ static const struct amd_ip_funcs uvd_v3_1_ip_funcs = { .soft_reset = uvd_v3_1_soft_reset, .set_clockgating_state = uvd_v3_1_set_clockgating_state, .set_powergating_state = uvd_v3_1_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version uvd_v3_1_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c index 1aa09ad7bbe3..3f19c606f4de 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c @@ -769,6 +769,8 @@ static const struct amd_ip_funcs uvd_v4_2_ip_funcs = { .soft_reset = uvd_v4_2_soft_reset, .set_clockgating_state = uvd_v4_2_set_clockgating_state, .set_powergating_state = uvd_v4_2_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c index f8b229b75435..efd903c21d48 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c @@ -877,6 +877,8 @@ static const struct amd_ip_funcs uvd_v5_0_ip_funcs = { .set_clockgating_state = uvd_v5_0_set_clockgating_state, .set_powergating_state = uvd_v5_0_set_powergating_state, .get_clockgating_state = uvd_v5_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index a9a6880f44e3..495de5068455 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -1545,6 +1545,8 @@ static const struct amd_ip_funcs uvd_v6_0_ip_funcs = { .set_clockgating_state = uvd_v6_0_set_clockgating_state, .set_powergating_state = uvd_v6_0_set_powergating_state, .get_clockgating_state = uvd_v6_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c index a08e7abca423..66fada199bda 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c @@ -626,6 +626,8 @@ static const struct amd_ip_funcs vce_v2_0_ip_funcs = { .soft_reset = vce_v2_0_soft_reset, .set_clockgating_state = vce_v2_0_set_clockgating_state, .set_powergating_state = vce_v2_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index f4760748d349..32517c364cf7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -913,6 +913,8 @@ static const struct amd_ip_funcs vce_v3_0_ip_funcs = { .set_clockgating_state = vce_v3_0_set_clockgating_state, .set_powergating_state = vce_v3_0_set_powergating_state, .get_clockgating_state = vce_v3_0_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c index aaceecd558cf..cb253bd3a2a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c @@ -1902,6 +1902,8 @@ static const struct amd_ip_funcs vcn_v1_0_ip_funcs = { .post_soft_reset = NULL /* vcn_v1_0_post_soft_reset */, .set_clockgating_state = vcn_v1_0_set_clockgating_state, .set_powergating_state = vcn_v1_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c index e357d8cf0c01..f18fd61c435e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c @@ -2008,6 +2008,8 @@ static const struct amd_ip_funcs vcn_v2_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v2_0_set_clockgating_state, .set_powergating_state = vcn_v2_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 1cd8a94b0fbc..baec14bde2a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1901,6 +1901,8 @@ static const struct amd_ip_funcs vcn_v2_5_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v2_5_set_clockgating_state, .set_powergating_state = vcn_v2_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amd_ip_funcs vcn_v2_6_ip_funcs = { @@ -1921,6 +1923,8 @@ static const struct amd_ip_funcs vcn_v2_6_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v2_5_set_clockgating_state, .set_powergating_state = vcn_v2_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v2_5_ip_block = diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 8f82fb887e9c..6b31cf4b8aac 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -359,6 +359,7 @@ static int vcn_v3_0_hw_init(void *handle) } } + return 0; done: if (!r) DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", @@ -2230,6 +2231,8 @@ static const struct amd_ip_funcs vcn_v3_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v3_0_set_clockgating_state, .set_powergating_state = vcn_v3_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v3_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 832d15f7b5f6..ac1b8ead03b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -288,6 +288,7 @@ static int vcn_v4_0_hw_init(void *handle) } } + return 0; done: if (!r) DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", @@ -2130,6 +2131,8 @@ static const struct amd_ip_funcs vcn_v4_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v4_0_set_clockgating_state, .set_powergating_state = vcn_v4_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v4_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c index 203fa988322b..2279d8fce03d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c @@ -1660,6 +1660,8 @@ static const struct amd_ip_funcs vcn_v4_0_3_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v4_0_3_set_clockgating_state, .set_powergating_state = vcn_v4_0_3_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v4_0_3_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c index 501e53e69f2a..81fb99729f37 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c @@ -237,6 +237,7 @@ static int vcn_v4_0_5_hw_init(void *handle) goto done; } + return 0; done: if (!r) DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", @@ -1752,6 +1753,8 @@ static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v4_0_5_set_clockgating_state, .set_powergating_state = vcn_v4_0_5_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v4_0_5_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c index bc60c554eb32..851975b5ce29 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c @@ -95,7 +95,7 @@ static int vcn_v5_0_0_sw_init(void *handle) return r; for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; if (adev->vcn.harvest_config & (1 << i)) continue; @@ -154,7 +154,7 @@ static int vcn_v5_0_0_sw_fini(void *handle) if (drm_dev_enter(adev_to_drm(adev), &idx)) { for (i = 0; i < adev->vcn.num_vcn_inst; i++) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; if (adev->vcn.harvest_config & (1 << i)) continue; @@ -203,6 +203,7 @@ static int vcn_v5_0_0_hw_init(void *handle) goto done; } + return 0; done: if (!r) DRM_INFO("VCN decode and encode initialized successfully(under %s).\n", @@ -334,7 +335,7 @@ static void vcn_v5_0_0_mc_resume(struct amdgpu_device *adev, int inst) upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr)); WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0); WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0, - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared))); + AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared))); } /** @@ -438,7 +439,7 @@ static void vcn_v5_0_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_i VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect); WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0), - AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect); + AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared)), 0, indirect); /* VCN global tiling registers */ WREG32_SOC24_DPG_MODE(inst_idx, SOC24_DPG_MODE_OFFSET( @@ -615,7 +616,7 @@ static void vcn_v5_0_0_enable_clock_gating(struct amdgpu_device *adev, int inst) */ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; + volatile struct amdgpu_vcn5_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr; struct amdgpu_ring *ring; uint32_t tmp; @@ -712,7 +713,7 @@ static int vcn_v5_0_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, b */ static int vcn_v5_0_0_start(struct amdgpu_device *adev) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; struct amdgpu_ring *ring; uint32_t tmp; int i, j, k, r; @@ -893,7 +894,7 @@ static void vcn_v5_0_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) */ static int vcn_v5_0_0_stop(struct amdgpu_device *adev) { - volatile struct amdgpu_vcn4_fw_shared *fw_shared; + volatile struct amdgpu_vcn5_fw_shared *fw_shared; uint32_t tmp; int i, r = 0; @@ -1328,6 +1329,8 @@ static const struct amd_ip_funcs vcn_v5_0_0_ip_funcs = { .post_soft_reset = NULL, .set_clockgating_state = vcn_v5_0_0_set_clockgating_state, .set_powergating_state = vcn_v5_0_0_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version vcn_v5_0_0_ip_block = { diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 1a98812981f4..d39c670f6220 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -897,7 +897,7 @@ static int vi_asic_pci_config_reset(struct amdgpu_device *adev) return r; } -static bool vi_asic_supports_baco(struct amdgpu_device *adev) +static int vi_asic_supports_baco(struct amdgpu_device *adev) { switch (adev->asic_type) { case CHIP_FIJI: @@ -908,14 +908,14 @@ static bool vi_asic_supports_baco(struct amdgpu_device *adev) case CHIP_TOPAZ: return amdgpu_dpm_is_baco_supported(adev); default: - return false; + return 0; } } static enum amd_reset_method vi_asic_reset_method(struct amdgpu_device *adev) { - bool baco_reset; + int baco_reset; if (amdgpu_reset_method == AMD_RESET_METHOD_LEGACY || amdgpu_reset_method == AMD_RESET_METHOD_BACO) @@ -935,7 +935,7 @@ vi_asic_reset_method(struct amdgpu_device *adev) baco_reset = amdgpu_dpm_is_baco_supported(adev); break; default: - baco_reset = false; + baco_reset = 0; break; } @@ -2058,6 +2058,8 @@ static const struct amd_ip_funcs vi_common_ip_funcs = { .set_clockgating_state = vi_common_set_clockgating_state, .set_powergating_state = vi_common_set_powergating_state, .get_clockgating_state = vi_common_get_clockgating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; static const struct amdgpu_ip_block_version vi_common_ip_block = diff --git a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c index 769eb8f7bb3c..09315dd5a1ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/vpe_v6_1.c @@ -144,6 +144,12 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe) WREG32(vpe_get_reg_offset(vpe, j, regVPEC_CNTL), ret); } + /* setup collaborate mode */ + vpe_v6_1_set_collaborate_mode(vpe, true); + /* setup DPM */ + if (amdgpu_vpe_configure_dpm(vpe)) + dev_warn(adev->dev, "VPE failed to enable DPM\n"); + /* * For VPE 6.1.1, still only need to add master's offset, and psp will apply it to slave as well. * Here use instance 0 as master. @@ -159,11 +165,7 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe) adev->vpe.cmdbuf_cpu_addr[0] = f32_offset; adev->vpe.cmdbuf_cpu_addr[1] = f32_cntl; - amdgpu_vpe_psp_update_sram(adev); - vpe_v6_1_set_collaborate_mode(vpe, true); - amdgpu_vpe_configure_dpm(vpe); - - return 0; + return amdgpu_vpe_psp_update_sram(adev); } vpe_hdr = (const struct vpe_firmware_header_v1_0 *)adev->vpe.fw->data; @@ -196,8 +198,6 @@ static int vpe_v6_1_load_microcode(struct amdgpu_vpe *vpe) } vpe_v6_1_halt(vpe, false); - vpe_v6_1_set_collaborate_mode(vpe, true); - amdgpu_vpe_configure_dpm(vpe); return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index f9631f4b1a02..6b713fb0b818 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -371,6 +371,11 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, err = -EINVAL; goto err_wptr_map_gart; } + if (dev->adev != amdgpu_ttm_adev(wptr_bo->tbo.bdev)) { + pr_err("Queue memory allocated to wrong device\n"); + err = -EINVAL; + goto err_wptr_map_gart; + } err = amdgpu_amdkfd_map_gtt_bo_to_gart(wptr_bo); if (err) { @@ -779,8 +784,8 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp, * nodes, but not more than args->num_of_nodes as that is * the amount of memory allocated by user */ - pa = kzalloc((sizeof(struct kfd_process_device_apertures) * - args->num_of_nodes), GFP_KERNEL); + pa = kcalloc(args->num_of_nodes, sizeof(struct kfd_process_device_apertures), + GFP_KERNEL); if (!pa) return -ENOMEM; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 041ec3de55e7..9596bca57212 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -435,12 +435,12 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf) if (!f2g) { if (amdgpu_ip_version(adev, GC_HWIP, 0)) - dev_err(kfd_device, + dev_info(kfd_device, "GC IP %06x %s not supported in kfd\n", amdgpu_ip_version(adev, GC_HWIP, 0), vf ? "VF" : ""); else - dev_err(kfd_device, "%s %s not supported in kfd\n", + dev_info(kfd_device, "%s %s not supported in kfd\n", amdgpu_asic_name[adev->asic_type], vf ? "VF" : ""); return NULL; } @@ -960,7 +960,6 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) { struct kfd_node *node; int i; - int count; if (!kfd->init_complete) return; @@ -968,12 +967,10 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) /* for runtime suspend, skip locking kfd */ if (!run_pm) { mutex_lock(&kfd_processes_mutex); - count = ++kfd_locked; - mutex_unlock(&kfd_processes_mutex); - /* For first KFD device suspend all the KFD processes */ - if (count == 1) + if (++kfd_locked == 1) kfd_suspend_all_processes(); + mutex_unlock(&kfd_processes_mutex); } for (i = 0; i < kfd->num_nodes; i++) { @@ -984,7 +981,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) { - int ret, count, i; + int ret, i; if (!kfd->init_complete) return 0; @@ -998,12 +995,10 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) /* for runtime resume, skip unlocking kfd */ if (!run_pm) { mutex_lock(&kfd_processes_mutex); - count = --kfd_locked; - mutex_unlock(&kfd_processes_mutex); - - WARN_ONCE(count < 0, "KFD suspend / resume ref. error"); - if (count == 0) + if (--kfd_locked == 0) ret = kfd_resume_all_processes(); + WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error"); + mutex_unlock(&kfd_processes_mutex); } return ret; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index f4d395e38683..c08b6ee25289 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1997,10 +1997,10 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, * check those fields */ mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]; - if (mqd_mgr->read_doorbell_id(dqm->packet_mgr.priv_queue->queue->mqd)) { - dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n"); + if (mqd_mgr->check_preemption_failed(mqd_mgr, dqm->packet_mgr.priv_queue->queue->mqd)) { while (halt_if_hws_hang) schedule(); + kfd_hws_hang(dqm); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c index 40a21be6c07c..8e0d0356e810 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c @@ -134,6 +134,7 @@ static void event_interrupt_poison_consumption(struct kfd_node *dev, { enum amdgpu_ras_block block = 0; int old_poison, ret = -EINVAL; + uint32_t reset = 0; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); if (!p) @@ -153,6 +154,8 @@ static void event_interrupt_poison_consumption(struct kfd_node *dev, case SOC15_IH_CLIENTID_UTCL2: ret = kfd_dqm_evict_pasid(dev->dqm, pasid); block = AMDGPU_RAS_BLOCK__GFX; + if (ret) + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; break; case SOC15_IH_CLIENTID_SDMA0: case SOC15_IH_CLIENTID_SDMA1: @@ -160,6 +163,7 @@ static void event_interrupt_poison_consumption(struct kfd_node *dev, case SOC15_IH_CLIENTID_SDMA3: case SOC15_IH_CLIENTID_SDMA4: block = AMDGPU_RAS_BLOCK__SDMA; + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; break; default: break; @@ -170,17 +174,16 @@ static void event_interrupt_poison_consumption(struct kfd_node *dev, /* resetting queue passes, do page retirement without gpu reset * resetting queue fails, fallback to gpu reset solution */ - if (!ret) { + if (!ret) dev_warn(dev->adev->dev, "RAS poison consumption, unmap queue flow succeeded: client id %d\n", client_id); - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, false); - } else { + else dev_warn(dev->adev->dev, "RAS poison consumption, fall back to gpu reset flow: client id %d\n", client_id); - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, true); - } + + amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, reset); } static bool event_interrupt_isr_v10(struct kfd_node *dev, @@ -368,10 +371,25 @@ static void event_interrupt_wq_v10(struct kfd_node *dev, client_id == SOC15_IH_CLIENTID_UTCL2) { struct kfd_vm_fault_info info = {0}; uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry); + uint32_t node_id = SOC15_NODEID_FROM_IH_ENTRY(ih_ring_entry); + uint32_t vmid_type = SOC15_VMID_TYPE_FROM_IH_ENTRY(ih_ring_entry); + int hub_inst = 0; struct kfd_hsa_memory_exception_data exception_data; - if (client_id == SOC15_IH_CLIENTID_UTCL2 && - amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev)) { + /* gfxhub */ + if (!vmid_type && dev->adev->gfx.funcs->ih_node_to_logical_xcc) { + hub_inst = dev->adev->gfx.funcs->ih_node_to_logical_xcc(dev->adev, + node_id); + if (hub_inst < 0) + hub_inst = 0; + } + + /* mmhub */ + if (vmid_type && client_id == SOC15_IH_CLIENTID_VMC) + hub_inst = node_id / 4; + + if (amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev, + hub_inst, vmid_type)) { event_interrupt_poison_consumption(dev, pasid, client_id); return; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c index fe2ad0c0de95..f524a55eee11 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c @@ -193,6 +193,7 @@ static void event_interrupt_poison_consumption_v11(struct kfd_node *dev, { enum amdgpu_ras_block block = 0; int ret = -EINVAL; + uint32_t reset = 0; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); if (!p) @@ -212,10 +213,13 @@ static void event_interrupt_poison_consumption_v11(struct kfd_node *dev, if (dev->dqm->ops.reset_queues) ret = dev->dqm->ops.reset_queues(dev->dqm, pasid); block = AMDGPU_RAS_BLOCK__GFX; + if (ret) + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; break; case SOC21_INTSRC_SDMA_ECC: default: block = AMDGPU_RAS_BLOCK__GFX; + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; break; } @@ -223,10 +227,7 @@ static void event_interrupt_poison_consumption_v11(struct kfd_node *dev, /* resetting queue passes, do page retirement without gpu reset resetting queue fails, fallback to gpu reset solution */ - if (!ret) - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, false); - else - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, true); + amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, reset); } static bool event_interrupt_isr_v11(struct kfd_node *dev, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index c4c6a29052ac..e1c21d250611 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -144,7 +144,8 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev, uint16_t pasid, uint16_t client_id) { enum amdgpu_ras_block block = 0; - int old_poison, ret = -EINVAL; + int old_poison; + uint32_t reset = 0; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); if (!p) @@ -162,8 +163,13 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev, case SOC15_IH_CLIENTID_SE2SH: case SOC15_IH_CLIENTID_SE3SH: case SOC15_IH_CLIENTID_UTCL2: - ret = kfd_dqm_evict_pasid(dev->dqm, pasid); block = AMDGPU_RAS_BLOCK__GFX; + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; + break; + case SOC15_IH_CLIENTID_VMC: + case SOC15_IH_CLIENTID_VMC1: + block = AMDGPU_RAS_BLOCK__MMHUB; + reset = AMDGPU_RAS_GPU_RESET_MODE1_RESET; break; case SOC15_IH_CLIENTID_SDMA0: case SOC15_IH_CLIENTID_SDMA1: @@ -171,27 +177,21 @@ static void event_interrupt_poison_consumption_v9(struct kfd_node *dev, case SOC15_IH_CLIENTID_SDMA3: case SOC15_IH_CLIENTID_SDMA4: block = AMDGPU_RAS_BLOCK__SDMA; + reset = AMDGPU_RAS_GPU_RESET_MODE2_RESET; break; default: - break; + dev_warn(dev->adev->dev, + "client %d does not support poison consumption\n", client_id); + return; } kfd_signal_poison_consumed_event(dev, pasid); - /* resetting queue passes, do page retirement without gpu reset - * resetting queue fails, fallback to gpu reset solution - */ - if (!ret) { - dev_warn(dev->adev->dev, - "RAS poison consumption, unmap queue flow succeeded: client id %d\n", - client_id); - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, false); - } else { - dev_warn(dev->adev->dev, - "RAS poison consumption, fall back to gpu reset flow: client id %d\n", - client_id); - amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, block, true); - } + dev_warn(dev->adev->dev, + "poison is consumed by client %d, kick off gpu reset flow\n", client_id); + + amdgpu_amdkfd_ras_pasid_poison_consumption_handler(dev->adev, + block, pasid, NULL, NULL, reset); } static bool context_id_expected(struct kfd_dev *dev) @@ -414,10 +414,25 @@ static void event_interrupt_wq_v9(struct kfd_node *dev, client_id == SOC15_IH_CLIENTID_UTCL2) { struct kfd_vm_fault_info info = {0}; uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry); + uint32_t node_id = SOC15_NODEID_FROM_IH_ENTRY(ih_ring_entry); + uint32_t vmid_type = SOC15_VMID_TYPE_FROM_IH_ENTRY(ih_ring_entry); + int hub_inst = 0; struct kfd_hsa_memory_exception_data exception_data; - if (client_id == SOC15_IH_CLIENTID_UTCL2 && - amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev)) { + /* gfxhub */ + if (!vmid_type && dev->adev->gfx.funcs->ih_node_to_logical_xcc) { + hub_inst = dev->adev->gfx.funcs->ih_node_to_logical_xcc(dev->adev, + node_id); + if (hub_inst < 0) + hub_inst = 0; + } + + /* mmhub */ + if (vmid_type && client_id == SOC15_IH_CLIENTID_VMC) + hub_inst = node_id / 4; + + if (amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev, + hub_inst, vmid_type)) { event_interrupt_poison_consumption_v9(dev, pasid, client_id); return; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c index dd3c43c1ad70..9b6b6e882593 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -104,6 +104,8 @@ void kfd_interrupt_exit(struct kfd_node *node) */ flush_workqueue(node->ih_wq); + destroy_workqueue(node->ih_wq); + kfifo_free(&node->ih_fifo); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c index bdc01ca9609a..4bcfbeac48fb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c @@ -77,7 +77,7 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages, dst_addr = amdgpu_bo_gpu_offset(adev->gart.bo); amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, - dst_addr, num_bytes, false); + dst_addr, num_bytes, 0); amdgpu_ring_pad_ib(ring, &job->ibs[0]); WARN_ON(job->ibs[0].length_dw > num_dw); @@ -153,7 +153,7 @@ svm_migrate_copy_memory_gart(struct amdgpu_device *adev, dma_addr_t *sys, } r = amdgpu_copy_buffer(ring, gart_s, gart_d, size * PAGE_SIZE, - NULL, &next, false, true, false); + NULL, &next, false, true, 0); if (r) { dev_err(adev->dev, "fail %d to copy memory\n", r); goto out_unlock; @@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, start = start_mgr << PAGE_SHIFT; end = (last_mgr + 1) << PAGE_SHIFT; + r = amdgpu_amdkfd_reserve_mem_limit(node->adev, + prange->npages * PAGE_SIZE, + KFD_IOC_ALLOC_MEM_FLAGS_VRAM, + node->xcp ? node->xcp->id : 0); + if (r) { + dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r); + return -ENOSPC; + } + r = svm_range_vram_node_new(node, prange, true); if (r) { dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r); - return r; + goto out; } ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT; @@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc, svm_range_vram_node_free(prange); } +out: + amdgpu_amdkfd_unreserve_mem_limit(node->adev, + prange->npages * PAGE_SIZE, + KFD_IOC_ALLOC_MEM_FLAGS_VRAM, + node->xcp ? node->xcp->id : 0); return r < 0 ? r : 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index 050a6936ff84..8746a61a852d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -290,3 +290,21 @@ uint64_t kfd_mqd_stride(struct mqd_manager *mm, { return mm->mqd_size; } + +bool kfd_check_hiq_mqd_doorbell_id(struct kfd_node *node, uint32_t doorbell_id, + uint32_t inst) +{ + if (doorbell_id) { + struct device *dev = node->adev->dev; + + if (node->adev->xcp_mgr && node->adev->xcp_mgr->num_xcps > 0) + dev_err(dev, "XCC %d: Queue preemption failed for queue with doorbell_id: %x\n", + inst, doorbell_id); + else + dev_err(dev, "Queue preemption failed for queue with doorbell_id: %x\n", + doorbell_id); + return true; + } + + return false; +} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h index e5cc697a3ca8..17cc1f25c8d0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h @@ -119,7 +119,7 @@ struct mqd_manager { #if defined(CONFIG_DEBUG_FS) int (*debugfs_show_mqd)(struct seq_file *m, void *data); #endif - uint32_t (*read_doorbell_id)(void *mqd); + bool (*check_preemption_failed)(struct mqd_manager *mm, void *mqd); uint64_t (*mqd_stride)(struct mqd_manager *mm, struct queue_properties *p); @@ -198,4 +198,6 @@ void kfd_get_hiq_xcc_mqd(struct kfd_node *dev, uint64_t kfd_hiq_mqd_stride(struct kfd_node *dev); uint64_t kfd_mqd_stride(struct mqd_manager *mm, struct queue_properties *q); +bool kfd_check_hiq_mqd_doorbell_id(struct kfd_node *node, uint32_t doorbell_id, + uint32_t inst); #endif /* KFD_MQD_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c index 1a4a69943c71..05f3ac2eaef9 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -206,11 +206,11 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -static uint32_t read_doorbell_id(void *mqd) +static bool check_preemption_failed(struct mqd_manager *mm, void *mqd) { struct cik_mqd *m = (struct cik_mqd *)mqd; - return m->queue_doorbell_id0; + return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0); } static void update_mqd(struct mqd_manager *mm, void *mqd, @@ -423,7 +423,7 @@ struct mqd_manager *mqd_manager_init_cik(enum KFD_MQD_TYPE type, #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif - mqd->read_doorbell_id = read_doorbell_id; + mqd->check_preemption_failed = check_preemption_failed; break; case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c index 22cbfa1bdadd..2eff37aaf827 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c @@ -224,11 +224,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -static uint32_t read_doorbell_id(void *mqd) +static bool check_preemption_failed(struct mqd_manager *mm, void *mqd) { struct v10_compute_mqd *m = (struct v10_compute_mqd *)mqd; - return m->queue_doorbell_id0; + return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0); } static int get_wave_state(struct mqd_manager *mm, void *mqd, @@ -488,7 +488,7 @@ struct mqd_manager *mqd_manager_init_v10(enum KFD_MQD_TYPE type, #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif - mqd->read_doorbell_id = read_doorbell_id; + mqd->check_preemption_failed = check_preemption_failed; pr_debug("%s@%i\n", __func__, __LINE__); break; case KFD_MQD_TYPE_DIQ: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c index 826bc4f6c8a7..68dbc0399c87 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c @@ -278,11 +278,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -static uint32_t read_doorbell_id(void *mqd) +static bool check_preemption_failed(struct mqd_manager *mm, void *mqd) { struct v11_compute_mqd *m = (struct v11_compute_mqd *)mqd; - return m->queue_doorbell_id0; + return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0); } static int get_wave_state(struct mqd_manager *mm, void *mqd, @@ -517,7 +517,7 @@ struct mqd_manager *mqd_manager_init_v11(enum KFD_MQD_TYPE type, #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif - mqd->read_doorbell_id = read_doorbell_id; + mqd->check_preemption_failed = check_preemption_failed; pr_debug("%s@%i\n", __func__, __LINE__); break; case KFD_MQD_TYPE_DIQ: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c index 697b6d530d12..6bddc16808d7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c @@ -316,11 +316,11 @@ static void update_mqd(struct mqd_manager *mm, void *mqd, } -static uint32_t read_doorbell_id(void *mqd) +static bool check_preemption_failed(struct mqd_manager *mm, void *mqd) { struct v9_mqd *m = (struct v9_mqd *)mqd; - return m->queue_doorbell_id0; + return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0); } static int get_wave_state(struct mqd_manager *mm, void *mqd, @@ -607,6 +607,24 @@ static int destroy_hiq_mqd_v9_4_3(struct mqd_manager *mm, void *mqd, return err; } +static bool check_preemption_failed_v9_4_3(struct mqd_manager *mm, void *mqd) +{ + uint64_t hiq_mqd_size = kfd_hiq_mqd_stride(mm->dev); + uint32_t xcc_mask = mm->dev->xcc_mask; + int inst = 0, xcc_id; + struct v9_mqd *m; + bool ret = false; + + for_each_inst(xcc_id, xcc_mask) { + m = get_mqd(mqd + hiq_mqd_size * inst); + ret |= kfd_check_hiq_mqd_doorbell_id(mm->dev, + m->queue_doorbell_id0, inst); + ++inst; + } + + return ret; +} + static void get_xcc_mqd(struct kfd_mem_obj *mqd_mem_obj, struct kfd_mem_obj *xcc_mqd_mem_obj, uint64_t offset) @@ -881,15 +899,16 @@ struct mqd_manager *mqd_manager_init_v9(enum KFD_MQD_TYPE type, #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif - mqd->read_doorbell_id = read_doorbell_id; if (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 3)) { mqd->init_mqd = init_mqd_hiq_v9_4_3; mqd->load_mqd = hiq_load_mqd_kiq_v9_4_3; mqd->destroy_mqd = destroy_hiq_mqd_v9_4_3; + mqd->check_preemption_failed = check_preemption_failed_v9_4_3; } else { mqd->init_mqd = init_mqd_hiq; mqd->load_mqd = kfd_hiq_load_mqd_kiq; mqd->destroy_mqd = destroy_hiq_mqd; + mqd->check_preemption_failed = check_preemption_failed; } break; case KFD_MQD_TYPE_DIQ: diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c index 3e1a574d4ea6..c1fafc502515 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -237,11 +237,11 @@ static void __update_mqd(struct mqd_manager *mm, void *mqd, q->is_active = QUEUE_IS_ACTIVE(*q); } -static uint32_t read_doorbell_id(void *mqd) +static bool check_preemption_failed(struct mqd_manager *mm, void *mqd) { struct vi_mqd *m = (struct vi_mqd *)mqd; - return m->queue_doorbell_id0; + return kfd_check_hiq_mqd_doorbell_id(mm->dev, m->queue_doorbell_id0, 0); } static void update_mqd(struct mqd_manager *mm, void *mqd, @@ -482,7 +482,7 @@ struct mqd_manager *mqd_manager_init_vi(enum KFD_MQD_TYPE type, #if defined(CONFIG_DEBUG_FS) mqd->debugfs_show_mqd = debugfs_show_mqd; #endif - mqd->read_doorbell_id = read_doorbell_id; + mqd->check_preemption_failed = check_preemption_failed; break; case KFD_MQD_TYPE_DIQ: mqd->allocate_mqd = allocate_mqd; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 717a60d7a4ea..58c1fe542193 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -819,9 +819,9 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) mutex_lock(&kfd_processes_mutex); if (kfd_is_locked()) { - mutex_unlock(&kfd_processes_mutex); pr_debug("KFD is locked! Cannot create process"); - return ERR_PTR(-EINVAL); + process = ERR_PTR(-EINVAL); + goto out; } /* A prior open of /dev/kfd could have already created the process. */ @@ -1922,6 +1922,8 @@ static int signal_eviction_fence(struct kfd_process *p) rcu_read_lock(); ef = dma_fence_get_rcu_safe(&p->ef); rcu_read_unlock(); + if (!ef) + return -EINVAL; ret = dma_fence_signal(ef); dma_fence_put(ef); @@ -1949,10 +1951,9 @@ static void evict_process_worker(struct work_struct *work) * they are responsible stopping the queues and scheduling * the restore work. */ - if (!signal_eviction_fence(p)) - queue_delayed_work(kfd_restore_wq, &p->restore_work, - msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)); - else + if (signal_eviction_fence(p) || + mod_delayed_work(kfd_restore_wq, &p->restore_work, + msecs_to_jiffies(PROCESS_RESTORE_TIME_MS))) kfd_process_restore_queues(p); pr_debug("Finished evicting pasid 0x%x\n", p->pasid); @@ -2011,9 +2012,9 @@ static void restore_process_worker(struct work_struct *work) if (ret) { pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n", p->pasid, PROCESS_BACK_OFF_TIME_MS); - ret = queue_delayed_work(kfd_restore_wq, &p->restore_work, - msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS)); - WARN(!ret, "reschedule restore work failed\n"); + if (mod_delayed_work(kfd_restore_wq, &p->restore_work, + msecs_to_jiffies(PROCESS_RESTORE_TIME_MS))) + kfd_process_restore_queues(p); } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index f0f7f48af413..386875e6eb96 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -3426,7 +3426,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange, mm, KFD_MIGRATE_TRIGGER_PREFETCH); *migrated = !r; - return r; + return 0; } int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence) diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 92a5c5efcf92..9a5bcafbf730 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -33,6 +33,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/resource subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dsc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/optc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dpp subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 71d2d44681b2..73cb88121382 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -148,6 +148,9 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU); #define FIRMWARE_DCN_35_DMUB "amdgpu/dcn_3_5_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB); +#define FIRMWARE_DCN_351_DMUB "amdgpu/dcn_3_5_1_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB); + /* Number of bytes in PSP header for firmware. */ #define PSP_HEADER_BYTES 0x100 @@ -271,7 +274,7 @@ static u32 dm_vblank_get_counter(struct amdgpu_device *adev, int crtc) static int dm_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, u32 *vbl, u32 *position) { - u32 v_blank_start, v_blank_end, h_position, v_position; + u32 v_blank_start = 0, v_blank_end = 0, h_position = 0, v_position = 0; struct amdgpu_crtc *acrtc = NULL; struct dc *dc = adev->dm.dc; @@ -845,7 +848,7 @@ static void dm_handle_hpd_work(struct work_struct *work) */ static void dm_dmub_outbox1_low_irq(void *interrupt_params) { - struct dmub_notification notify; + struct dmub_notification notify = {0}; struct common_irq_params *irq_params = interrupt_params; struct amdgpu_device *adev = irq_params->adev; struct amdgpu_display_manager *dm = &adev->dm; @@ -1227,6 +1230,15 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) break; } + switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { + case IP_VERSION(3, 5, 0): + case IP_VERSION(3, 5, 1): + hw_params.ips_sequential_ono = adev->external_rev_id > 0x10; + break; + default: + break; + } + status = dmub_srv_hw_init(dmub_srv, &hw_params); if (status != DMUB_STATUS_OK) { DRM_ERROR("Error initializing DMUB HW: %d\n", status); @@ -1723,8 +1735,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_debug_mask & DC_DISABLE_IPS) init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL; + else + init_data.flags.disable_ips = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF; - init_data.flags.disable_ips_in_vpb = 1; + init_data.flags.disable_ips_in_vpb = 0; /* Enable DWB for tested platforms only */ if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) @@ -2626,6 +2640,7 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) int i; struct dc_stream_state *del_streams[MAX_PIPES]; int del_streams_count = 0; + struct dc_commit_streams_params params = {}; memset(del_streams, 0, sizeof(del_streams)); @@ -2652,7 +2667,9 @@ static enum dc_status amdgpu_dm_commit_zero_streams(struct dc *dc) goto fail; } - res = dc_commit_streams(dc, context->streams, context->stream_count); + params.streams = context->streams; + params.stream_count = context->stream_count; + res = dc_commit_streams(dc, ¶ms); fail: dc_state_release(context); @@ -2874,6 +2891,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j, ret; bool need_hotplug = false; + struct dc_commit_streams_params commit_params = {}; if (dm->dc->caps.ips_support) { dc_dmub_srv_apply_idle_power_optimizations(dm->dc, false); @@ -2923,7 +2941,9 @@ static int dm_resume(void *handle) dc_enable_dmub_outbox(adev->dm.dc); } - WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); + commit_params.streams = dc_state->streams; + commit_params.stream_count = dc_state->stream_count; + WARN_ON(!dc_commit_streams(dm->dc, &commit_params)); dm_gpureset_commit_state(dm->cached_dc_state, dm); @@ -2940,7 +2960,7 @@ static int dm_resume(void *handle) } /* Recreate dc_state - DC invalidates it when setting power state to S3. */ dc_state_release(dm_state->context); - dm_state->context = dc_state_create(dm->dc); + dm_state->context = dc_state_create(dm->dc, NULL); /* TODO: Remove dc_state->dccg, use dc->dccg directly. */ /* Before powering on DC we need to re-initialize DMUB. */ @@ -3026,6 +3046,7 @@ static int dm_resume(void *handle) dc_stream_release(dm_new_crtc_state->stream); dm_new_crtc_state->stream = NULL; } + dm_new_crtc_state->base.color_mgmt_changed = true; } for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) { @@ -3044,6 +3065,10 @@ static int dm_resume(void *handle) /* Do mst topology probing after resuming cached state*/ drm_connector_list_iter_begin(ddev, &iter); drm_for_each_connector_iter(connector, &iter) { + + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + continue; + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type != dc_connection_mst_branch || aconnector->mst_root) @@ -3096,6 +3121,8 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = { .soft_reset = dm_soft_reset, .set_clockgating_state = dm_set_clockgating_state, .set_powergating_state = dm_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version dm_ip_block = { @@ -4820,9 +4847,11 @@ static int dm_init_microcode(struct amdgpu_device *adev) fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB; break; case IP_VERSION(3, 5, 0): - case IP_VERSION(3, 5, 1): fw_name_dmub = FIRMWARE_DCN_35_DMUB; break; + case IP_VERSION(3, 5, 1): + fw_name_dmub = FIRMWARE_DCN_351_DMUB; + break; default: /* ASIC doesn't support DMUB. */ return 0; @@ -5700,8 +5729,8 @@ static void fill_stream_properties_from_drm_display_mode( timing_out->aspect_ratio = get_aspect_ratio(mode_in); - stream->out_transfer_func->type = TF_TYPE_PREDEFINED; - stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func.type = TF_TYPE_PREDEFINED; + stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB; if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { if (!adjust_colour_depth_from_display_info(timing_out, info) && drm_mode_is_420_also(info, mode_in) && @@ -5921,6 +5950,9 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, &aconnector->base.probed_modes : &aconnector->base.modes; + if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + return NULL; + if (aconnector->freesync_vid_base.clock != 0) return &aconnector->freesync_vid_base; @@ -6306,20 +6338,17 @@ create_stream_for_sink(struct drm_connector *connector, if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); - if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) { + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + stream->signal == SIGNAL_TYPE_EDP) { // // should decide stream support vsc sdp colorimetry capability // before building vsc info packet // - stream->use_vsc_sdp_for_colorimetry = false; - if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - stream->use_vsc_sdp_for_colorimetry = - aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; - } else { - if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) - stream->use_vsc_sdp_for_colorimetry = true; - } - if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) + stream->use_vsc_sdp_for_colorimetry = stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && + stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED; + + if (stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) tf = TRANSFER_FUNC_GAMMA_22; mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf); aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY; @@ -6790,7 +6819,7 @@ static enum dc_status dm_validate_stream_and_context(struct dc *dc, if (!dc_plane_state) goto cleanup; - dc_state = dc_state_create(dc); + dc_state = dc_state_create(dc, NULL); if (!dc_state) goto cleanup; @@ -7179,7 +7208,7 @@ static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, struct amdgpu_dm_connector *aconnector; struct dm_connector_state *dm_conn_state; int i, j, ret; - int vcpi, pbn_div, pbn, slot_num = 0; + int vcpi, pbn_div, pbn = 0, slot_num = 0; for_each_new_connector_in_state(state, connector, new_con_state, i) { @@ -8392,13 +8421,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->surface_updates[planes_count].surface = dc_plane; if (new_pcrtc_state->color_mgmt_changed) { - bundle->surface_updates[planes_count].gamma = dc_plane->gamma_correction; - bundle->surface_updates[planes_count].in_transfer_func = dc_plane->in_transfer_func; + bundle->surface_updates[planes_count].gamma = &dc_plane->gamma_correction; + bundle->surface_updates[planes_count].in_transfer_func = &dc_plane->in_transfer_func; bundle->surface_updates[planes_count].gamut_remap_matrix = &dc_plane->gamut_remap_matrix; bundle->surface_updates[planes_count].hdr_mult = dc_plane->hdr_mult; - bundle->surface_updates[planes_count].func_shaper = dc_plane->in_shaper_func; - bundle->surface_updates[planes_count].lut3d_func = dc_plane->lut3d_func; - bundle->surface_updates[planes_count].blend_tf = dc_plane->blend_tf; + bundle->surface_updates[planes_count].func_shaper = &dc_plane->in_shaper_func; + bundle->surface_updates[planes_count].lut3d_func = &dc_plane->lut3d_func; + bundle->surface_updates[planes_count].blend_tf = &dc_plane->blend_tf; } amdgpu_dm_plane_fill_dc_scaling_info(dm->adev, new_plane_state, @@ -8611,7 +8640,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->stream_update.output_csc_transform = &acrtc_state->stream->csc_color_matrix; bundle->stream_update.out_transfer_func = - acrtc_state->stream->out_transfer_func; + &acrtc_state->stream->out_transfer_func; bundle->stream_update.lut3d_func = (struct dc_3dlut *) acrtc_state->stream->lut3d_func; bundle->stream_update.func_shaper = @@ -8762,10 +8791,10 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev, if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; +notify: if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) continue; -notify: aconnector = to_amdgpu_dm_connector(connector); mutex_lock(&adev->dm.audio_lock); @@ -8845,6 +8874,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state, struct drm_connector *connector; bool mode_set_reset_required = false; u32 i; + struct dc_commit_streams_params params = {dc_state->streams, dc_state->stream_count}; /* Disable writeback */ for_each_old_connector_in_state(state, connector, old_con_state, i) { @@ -8981,7 +9011,7 @@ static void amdgpu_dm_commit_streams(struct drm_atomic_state *state, dm_enable_per_frame_crtc_master_sync(dc_state); mutex_lock(&dm->dc_lock); - WARN_ON(!dc_commit_streams(dm->dc, dc_state->streams, dc_state->stream_count)); + WARN_ON(!dc_commit_streams(dm->dc, ¶ms)); /* Allow idle optimization when vblank count is 0 for display off */ if (dm->active_vblank_irq_count == 0) @@ -10585,7 +10615,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; struct drm_dp_mst_topology_mgr *mgr; struct drm_dp_mst_topology_state *mst_state; - struct dsc_mst_fairness_vars vars[MAX_PIPES]; + struct dsc_mst_fairness_vars vars[MAX_PIPES] = {0}; trace_amdgpu_dm_atomic_check_begin(state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index c87b64e464ed..ebabfe3a512f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -571,7 +571,7 @@ static int amdgpu_dm_set_atomic_regamma(struct dc_stream_state *stream, uint32_t regamma_size, bool has_rom, enum dc_transfer_func_predefined tf) { - struct dc_transfer_func *out_tf = stream->out_transfer_func; + struct dc_transfer_func *out_tf = &stream->out_transfer_func; int ret = 0; if (regamma_size || tf != TRANSFER_FUNCTION_LINEAR) { @@ -954,8 +954,8 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) * inverse color ramp in legacy userspace. */ crtc->cm_is_degamma_srgb = true; - stream->out_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; - stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB; + stream->out_transfer_func.type = TF_TYPE_DISTRIBUTED_POINTS; + stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB; /* * Note: although we pass has_rom as parameter here, we never * actually use ROM because the color module only takes the ROM @@ -963,7 +963,7 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) * * See more in mod_color_calculate_regamma_params() */ - r = __set_legacy_tf(stream->out_transfer_func, regamma_lut, + r = __set_legacy_tf(&stream->out_transfer_func, regamma_lut, regamma_size, has_rom); if (r) return r; @@ -1034,7 +1034,7 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, °amma_size); ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); - dc_plane_state->in_transfer_func->type = TF_TYPE_DISTRIBUTED_POINTS; + dc_plane_state->in_transfer_func.type = TF_TYPE_DISTRIBUTED_POINTS; /* * This case isn't fully correct, but also fairly @@ -1061,12 +1061,12 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, * map these to the atomic one instead. */ if (crtc->cm_is_degamma_srgb) - dc_plane_state->in_transfer_func->tf = tf; + dc_plane_state->in_transfer_func.tf = tf; else - dc_plane_state->in_transfer_func->tf = + dc_plane_state->in_transfer_func.tf = TRANSFER_FUNCTION_LINEAR; - r = __set_input_tf(caps, dc_plane_state->in_transfer_func, + r = __set_input_tf(caps, &dc_plane_state->in_transfer_func, degamma_lut, degamma_size); if (r) return r; @@ -1075,12 +1075,12 @@ map_crtc_degamma_to_dc_plane(struct dm_crtc_state *crtc, * For legacy gamma support we need the regamma input * in linear space. Assume that the input is sRGB. */ - dc_plane_state->in_transfer_func->type = TF_TYPE_PREDEFINED; - dc_plane_state->in_transfer_func->tf = tf; + dc_plane_state->in_transfer_func.type = TF_TYPE_PREDEFINED; + dc_plane_state->in_transfer_func.tf = tf; if (tf != TRANSFER_FUNCTION_SRGB && !mod_color_calculate_degamma_params(caps, - dc_plane_state->in_transfer_func, + &dc_plane_state->in_transfer_func, NULL, false)) return -ENOMEM; } @@ -1114,24 +1114,24 @@ __set_dm_plane_degamma(struct drm_plane_state *plane_state, if (!has_degamma_lut && tf == AMDGPU_TRANSFER_FUNCTION_DEFAULT) return -EINVAL; - dc_plane_state->in_transfer_func->tf = amdgpu_tf_to_dc_tf(tf); + dc_plane_state->in_transfer_func.tf = amdgpu_tf_to_dc_tf(tf); if (has_degamma_lut) { ASSERT(degamma_size == MAX_COLOR_LUT_ENTRIES); - dc_plane_state->in_transfer_func->type = + dc_plane_state->in_transfer_func.type = TF_TYPE_DISTRIBUTED_POINTS; - ret = __set_input_tf(color_caps, dc_plane_state->in_transfer_func, + ret = __set_input_tf(color_caps, &dc_plane_state->in_transfer_func, degamma_lut, degamma_size); if (ret) return ret; } else { - dc_plane_state->in_transfer_func->type = + dc_plane_state->in_transfer_func.type = TF_TYPE_PREDEFINED; if (!mod_color_calculate_degamma_params(color_caps, - dc_plane_state->in_transfer_func, NULL, false)) + &dc_plane_state->in_transfer_func, NULL, false)) return -ENOMEM; } return 0; @@ -1156,11 +1156,11 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state, lut3d = __extract_blob_lut(dm_plane_state->lut3d, &lut3d_size); lut3d_size = lut3d != NULL ? lut3d_size : 0; - amdgpu_dm_atomic_lut3d(lut3d, lut3d_size, dc_plane_state->lut3d_func); + amdgpu_dm_atomic_lut3d(lut3d, lut3d_size, &dc_plane_state->lut3d_func); ret = amdgpu_dm_atomic_shaper_lut(shaper_lut, false, amdgpu_tf_to_dc_tf(shaper_tf), shaper_size, - dc_plane_state->in_shaper_func); + &dc_plane_state->in_shaper_func); if (ret) { drm_dbg_kms(plane_state->plane->dev, "setting plane %d shaper LUT failed.\n", @@ -1175,7 +1175,7 @@ amdgpu_dm_plane_set_color_properties(struct drm_plane_state *plane_state, ret = amdgpu_dm_atomic_blend_lut(blend_lut, false, amdgpu_tf_to_dc_tf(blend_tf), - blend_size, dc_plane_state->blend_tf); + blend_size, &dc_plane_state->blend_tf); if (ret) { drm_dbg_kms(plane_state->plane->dev, "setting plane %d gamma lut failed.\n", @@ -1221,8 +1221,8 @@ int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, color_caps = &dc_plane_state->ctx->dc->caps.color; /* Initially, we can just bypass the DGM block. */ - dc_plane_state->in_transfer_func->type = TF_TYPE_BYPASS; - dc_plane_state->in_transfer_func->tf = TRANSFER_FUNCTION_LINEAR; + dc_plane_state->in_transfer_func.type = TF_TYPE_BYPASS; + dc_plane_state->in_transfer_func.tf = TRANSFER_FUNCTION_LINEAR; /* After, we start to update values according to color props */ has_crtc_cm_degamma = (crtc->cm_has_degamma || crtc->cm_is_degamma_srgb); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index eee4945653e2..fdbeef9720c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1249,7 +1249,7 @@ static ssize_t dp_sdp_message_debugfs_write(struct file *f, const char __user *b size_t size, loff_t *pos) { int r; - uint8_t data[36]; + uint8_t data[36] = {0}; struct amdgpu_dm_connector *connector = file_inode(f)->i_private; struct dm_crtc_state *acrtc_state; uint32_t write_size = 36; @@ -2936,7 +2936,7 @@ static int psr_read_residency(void *data, u64 *val) { struct amdgpu_dm_connector *connector = data; struct dc_link *link = connector->dc_link; - u32 residency; + u32 residency = 0; link->dc->link_srv->edp_get_psr_residency(link, &residency); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 941e96f100f4..0b03e659fdf3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -791,25 +791,12 @@ struct dsc_mst_fairness_params { struct amdgpu_dm_connector *aconnector; }; -static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link) -{ - u8 link_coding_cap; - uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B; - - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link); - if (link_coding_cap == DP_128b_132b_ENCODING) - fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B; - - return fec_overhead_multiplier_x1000; -} - -static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000) +static int kbps_to_peak_pbn(int kbps) { u64 peak_kbps = kbps; peak_kbps *= 1006; - peak_kbps *= fec_overhead_multiplier_x1000; - peak_kbps = div_u64(peak_kbps, 1000 * 1000); + peak_kbps = div_u64(peak_kbps, 1000); return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000)); } @@ -910,12 +897,11 @@ static int increase_dsc_bpp(struct drm_atomic_state *state, int link_timeslots_used; int fair_pbn_alloc; int ret = 0; - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled) { initial_slack[i] = - kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn; + kbps_to_peak_pbn(params[i].bw_range.max_kbps) - vars[i + k].pbn; bpp_increased[i] = false; remaining_to_increase += 1; } else { @@ -1011,7 +997,6 @@ static int try_disable_dsc(struct drm_atomic_state *state, int next_index; int remaining_to_try = 0; int ret; - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); for (i = 0; i < count; i++) { if (vars[i + k].dsc_enabled @@ -1041,7 +1026,7 @@ static int try_disable_dsc(struct drm_atomic_state *state, if (next_index == -1) break; - vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000); + vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps); ret = drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, @@ -1054,7 +1039,8 @@ static int try_disable_dsc(struct drm_atomic_state *state, vars[next_index].dsc_enabled = false; vars[next_index].bpp_x16 = 0; } else { - vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.max_kbps, fec_overhead_multiplier_x1000); + vars[next_index].pbn = kbps_to_peak_pbn( + params[next_index].bw_range.max_kbps); ret = drm_dp_atomic_find_time_slots(state, params[next_index].port->mgr, params[next_index].port, @@ -1083,7 +1069,6 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, int count = 0; int i, k, ret; bool debugfs_overwrite = false; - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); memset(params, 0, sizeof(params)); @@ -1148,7 +1133,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, /* Try no compression */ for (i = 0; i < count; i++) { vars[i + k].aconnector = params[i].aconnector; - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, @@ -1167,7 +1152,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, /* Try max compression */ for (i = 0; i < count; i++) { if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps); vars[i + k].dsc_enabled = true; vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, @@ -1175,7 +1160,7 @@ static int compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (ret < 0) return ret; } else { - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); + vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps); vars[i + k].dsc_enabled = false; vars[i + k].bpp_x16 = 0; ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, @@ -1601,7 +1586,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( struct amdgpu_dm_connector *aconnector, struct dc_stream_state *stream) { - int bpp, pbn, branch_max_throughput_mps = 0; + int pbn, branch_max_throughput_mps = 0; struct dc_link_settings cur_link_settings; unsigned int end_to_end_bw_in_kbps = 0; unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; @@ -1651,11 +1636,34 @@ enum dc_status dm_dp_mst_is_port_support_mode( } } } else { - /* check if mode could be supported within full_pbn */ - bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; - pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp << 4); - if (pbn > aconnector->mst_output_port->full_pbn) + /* Check if mode could be supported within max slot + * number of current mst link and full_pbn of mst links. + */ + int pbn_div, slot_num, max_slot_num; + enum dc_link_encoding_format link_encoding; + uint32_t stream_kbps = + dc_bandwidth_in_kbps_from_timing(&stream->timing, + dc_link_get_highest_encoding_format(stream->link)); + + pbn = kbps_to_peak_pbn(stream_kbps); + pbn_div = dm_mst_get_pbn_divider(stream->link); + slot_num = DIV_ROUND_UP(pbn, pbn_div); + + link_encoding = dc_link_get_highest_encoding_format(stream->link); + if (link_encoding == DC_LINK_ENCODING_DP_8b_10b) + max_slot_num = 63; + else if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) + max_slot_num = 64; + else { + DRM_DEBUG_DRIVER("Invalid link encoding format\n"); return DC_FAIL_BANDWIDTH_VALIDATE; + } + + if (slot_num > max_slot_num || + pbn > aconnector->mst_output_port->full_pbn) { + DRM_DEBUG_DRIVER("Mode can not be supported within mst links!"); + return DC_FAIL_BANDWIDTH_VALIDATE; + } } /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 37c820ab0fdb..fa84d34b7373 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -46,9 +46,6 @@ #define SYNAPTICS_CASCADED_HUB_ID 0x5A #define IS_SYNAPTICS_CASCADED_PANAMERA(devName, data) ((IS_SYNAPTICS_PANAMERA(devName) && ((int)data[2] == SYNAPTICS_CASCADED_HUB_ID)) ? 1 : 0) -#define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B 1031 -#define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B 1000 - enum mst_msg_ready_type { NONE_MSG_RDY_EVENT = 0, DOWN_REP_MSG_RDY_EVENT = 1, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 286ecd28cc6e..bfa090432ce2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -212,7 +212,7 @@ bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) } /* - * amdgpu_dm_psr_disable() - disable psr f/w + * amdgpu_dm_psr_disable_all() - disable psr f/w for all streams * if psr is enabled on any stream * * Return: true if success diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c index d9e33c6bccd9..0005f5f8f34f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c @@ -52,4 +52,12 @@ void dm_perf_trace_timestamp(const char *func_name, unsigned int line, struct dc func_name, line); } +void dm_trace_smu_msg(uint32_t msg_id, uint32_t param_in, struct dc_context *ctx) +{ +} + +void dm_trace_smu_delay(uint32_t delay, struct dc_context *ctx) +{ +} + /**** power component interfaces ****/ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c index 16e72d623630..08c494a7a21b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c @@ -76,10 +76,8 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder, static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - - return drm_add_modes_noedid(connector, dev->mode_config.max_width, - dev->mode_config.max_height); + /* Maximum resolution supported by DWB */ + return drm_add_modes_noedid(connector, 3840, 2160); } static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector, diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 7991ae468f75..4e9fb1742877 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -22,7 +22,7 @@ # # Makefile for Display Core (dc) component. -DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc +DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc dpp ifdef CONFIG_DRM_AMD_DC_FP diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 6450853fea94..bc16db69a663 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -44,8 +44,6 @@ #include "bios_parser_common.h" -#include "dc.h" - #define THREE_PERCENT_OF_10000 300 #define LAST_RECORD_TYPE 0xff @@ -1731,6 +1729,7 @@ static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1( return 0; } + /** * get_ss_entry_number_from_internal_ss_info_tbl_V3_1 * Get Number of SpreadSpectrum Entry from the ASIC_InternalSS_Info table of diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 05f392501c0a..517c976dbc19 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1594,8 +1594,6 @@ static bool bios_parser_is_device_id_supported( return (le16_to_cpu(bp->object_info_tbl.v1_5->supporteddevices) & mask) != 0; break; } - - return false; } static uint32_t bios_parser_get_ss_entry_number( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 86f9198e7501..2bcae0643e61 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -399,7 +399,7 @@ static enum bp_result transmitter_control_v1_6( static void init_transmitter_control(struct bios_parser *bp) { uint8_t frev; - uint8_t crev; + uint8_t crev = 0; if (BIOS_CMD_TABLE_REVISION(UNIPHYTransmitterControl, frev, crev) == false) diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index cbae1be7b009..cc000833d300 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -225,7 +225,7 @@ static enum bp_result transmitter_control_fallback( static void init_transmitter_control(struct bios_parser *bp) { uint8_t frev; - uint8_t crev; + uint8_t crev = 0; BIOS_CMD_TABLE_REVISION(dig1transmittercontrol, frev, crev); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 9f0f25aee426..a2b4ff2cff16 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -272,7 +272,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); return &clk_mgr->base; } - if (asic_id.chip_id == DEVICE_ID_NV_13FE) { + if (ctx->dce_version == DCN_VERSION_2_01) { dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); return &clk_mgr->base; } @@ -329,15 +329,14 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p } break; case AMDGPU_FAMILY_GC_11_0_0: { - struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); - if (clk_mgr == NULL) { - BREAK_TO_DEBUGGER(); - return NULL; - } - - dcn32_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); - return &clk_mgr->base; + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + dcn32_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); + return &clk_mgr->base; } case AMDGPU_FAMILY_GC_11_0_1: { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c index b77804cfde0f..2a5dd3a296b2 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c @@ -131,8 +131,8 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base) struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); int dprefclk_wdivider; int dprefclk_src_sel; - int dp_ref_clk_khz; - int target_div = 600000; + int dp_ref_clk_khz = 600000; + int target_div; /* ASSERT DP Reference Clock source is from DFS*/ REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c index 2a74e2d74909..369421e46c52 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c @@ -23,7 +23,6 @@ * */ -#include "reg_helper.h" #include "core_types.h" #include "clk_mgr_internal.h" #include "rv1_clk_mgr.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c index 89b79dd39628..19897fa52e7e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr_vbios_smu.c @@ -26,7 +26,6 @@ #include "core_types.h" #include "clk_mgr_internal.h" #include "reg_helper.h" -#include #include "rv1_clk_mgr_vbios_smu.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c index 5ee87965a078..bb4f3bd7532e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c @@ -503,7 +503,7 @@ static void dcn2_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (i = 0; i < MAX_PIPES * 2; i++) { + for (i = 0; i < MAX_LINKS; i++) { if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req) max_phyclk_req = clk_mgr->cur_phyclk_req_table[i]; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c index 9c90090e7351..f77840dd051e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn201/dcn201_clk_mgr.c @@ -100,7 +100,15 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base, if (clk_mgr_base->clks.dispclk_khz == 0 || dc->debug.force_clock_mode & 0x1) { + /* this is from resume or boot up, if forced_clock cfg option + * used, we bypass program dispclk and DPPCLK, but need set them + * for S3. + */ + force_reset = true; + /* force_clock_mode 0x1: force reset the clock even it is the + * same clock as long as it is in Passive level. + */ dcn2_read_clocks_from_hw_dentist(clk_mgr_base); } @@ -150,11 +158,14 @@ static void dcn201_update_clocks(struct clk_mgr *clk_mgr_base, if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) { if (dpp_clock_lowered) { + // if clock is being lowered, increase DTO before lowering refclk dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); dcn20_update_clocks_update_dentist(clk_mgr, context); } else { + // if clock is being raised, increase refclk before lowering DTO if (update_dppclk || update_dispclk) dcn20_update_clocks_update_dentist(clk_mgr, context); + // always update dtos unless clock is lowered and not safe to lower dcn20_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); } } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index e3e1940198a9..5ef0879f6ad9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -548,7 +548,7 @@ static void rn_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct dc_l clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (i = 0; i < MAX_PIPES * 2; i++) { + for (i = 0; i < MAX_LINKS; i++) { if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req) max_phyclk_req = clk_mgr->cur_phyclk_req_table[i]; } @@ -642,7 +642,8 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params j = -1; - ASSERT(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL); + static_assert(PP_SMU_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL, + "number of reported FCLK DPM levels exceed maximum"); /* Find lowest DPM, FCLK is filled in reverse order*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c index 3271c8c7905d..8083a553c60e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c @@ -474,7 +474,7 @@ static void dcn30_notify_link_rate_change(struct clk_mgr *clk_mgr_base, struct d clk_mgr->cur_phyclk_req_table[link->link_index] = link->cur_link_settings.link_rate * LINK_RATE_REF_FREQ_IN_KHZ; - for (i = 0; i < MAX_PIPES * 2; i++) { + for (i = 0; i < MAX_LINKS; i++) { if (clk_mgr->cur_phyclk_req_table[i] > max_phyclk_req) max_phyclk_req = clk_mgr->cur_phyclk_req_table[i]; } @@ -560,11 +560,19 @@ void dcn3_clk_mgr_construct( dce_clock_read_ss_info(clk_mgr); clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL); + if (!clk_mgr->base.bw_params) { + BREAK_TO_DEBUGGER(); + return; + } /* need physical address of table to give to PMFW */ clk_mgr->wm_range_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART, sizeof(WatermarksExternal_t), &clk_mgr->wm_range_table_addr); + if (!clk_mgr->wm_range_table) { + BREAK_TO_DEBUGGER(); + return; + } } void dcn3_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c index bdbf18306698..3253115a153d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c @@ -23,7 +23,6 @@ * */ -#include #include "dcn30_clk_mgr_smu_msg.h" #include "clk_mgr_internal.h" @@ -54,6 +53,7 @@ */ static uint32_t dcn30_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries) { + const uint32_t initial_max_retries = max_retries; uint32_t reg = 0; do { @@ -69,7 +69,7 @@ static uint32_t dcn30_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, un /* handle DALSMC_Result_CmdRejectedBusy? */ - /* Log? */ + TRACE_SMU_DELAY(delay_us * (initial_max_retries - max_retries), clk_mgr->base.ctx); return reg; } @@ -89,6 +89,8 @@ static bool dcn30_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, uint /* Trigger the message transaction by writing the message ID */ REG_WRITE(DAL_MSG_REG, msg_id); + TRACE_SMU_MSG(msg_id, param_in, clk_mgr->base.ctx); + result = dcn30_smu_wait_for_response(clk_mgr, 10, 200000); if (IS_SMU_TIMEOUT(result)) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c index aa9fd1dc550a..191d8b969d19 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c @@ -566,7 +566,8 @@ static void vg_clk_mgr_helper_populate_bw_params( j = -1; - ASSERT(VG_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL); + static_assert(VG_NUM_FCLK_DPM_LEVELS <= MAX_NUM_DPM_LVL, + "number of reported FCLK DPM levels exceeds maximum"); /* Find lowest DPM, FCLK is filled in reverse order*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index ce1386e22576..12a7752758b8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -562,7 +562,8 @@ static void dcn31_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk j = -1; - ASSERT(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL); + static_assert(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL, + "number of reported pstate levels exceeds maximum"); /* Find lowest DPM, FCLK is filled in reverse order*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c index 6904e95113c1..f201628e4e98 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c @@ -23,7 +23,6 @@ * */ -#include #include "core_types.h" #include "clk_mgr_internal.h" #include "reg_helper.h" diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h index 047d19ea919c..78ca1e5c5e9e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.h @@ -37,34 +37,34 @@ typedef enum { } WCK_RATIO_e; typedef struct { - uint32_t FClk; - uint32_t MemClk; - uint32_t Voltage; - uint8_t WckRatio; - uint8_t Spare[3]; + uint32_t FClk; + uint32_t MemClk; + uint32_t Voltage; + uint8_t WckRatio; + uint8_t Spare[3]; } DfPstateTable314_t; //Freq in MHz //Voltage in milli volts with 2 fractional bits typedef struct { - uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; - uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; - uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; - uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; - uint32_t VClocks[NUM_VCN_DPM_LEVELS]; - uint32_t DClocks[NUM_VCN_DPM_LEVELS]; - uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; - DfPstateTable314_t DfPstateTable[NUM_DF_PSTATE_LEVELS]; + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + uint32_t VClocks[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks[NUM_VCN_DPM_LEVELS]; + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; + DfPstateTable314_t DfPstateTable[NUM_DF_PSTATE_LEVELS]; - uint8_t NumDcfClkLevelsEnabled; - uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk - uint8_t NumSocClkLevelsEnabled; - uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk - uint8_t NumDfPstatesEnabled; - uint8_t spare[3]; + uint8_t NumDcfClkLevelsEnabled; + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk + uint8_t NumSocClkLevelsEnabled; + uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk + uint8_t NumDfPstatesEnabled; + uint8_t spare[3]; - uint32_t MinGfxClk; - uint32_t MaxGfxClk; + uint32_t MinGfxClk; + uint32_t MaxGfxClk; } DpmClocks314_t; struct dcn314_watermarks { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c index 879f1494c4cd..2d14346b680e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_smu.c @@ -29,6 +29,7 @@ #include "dm_helpers.h" #include "dcn315_smu.h" #include "mp/mp_13_0_5_offset.h" +#include "logger_types.h" #define MAX_INSTANCE 6 #define MAX_SEGMENT 6 @@ -69,7 +70,6 @@ static const struct IP_BASE NBIO_BASE = { { { { 0x00000000, 0x00000014, 0x00000D #define REG_NBIO(reg_name) \ (NBIO_BASE.instance[0].segment[regBIF_BX_PF2_ ## reg_name ## _BASE_IDX] + regBIF_BX_PF2_ ## reg_name) -#include "logger_types.h" #undef DC_LOGGER #define DC_LOGGER \ CTX->logger diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 12f3e8aa46d8..20ca7afa9cb4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -99,20 +99,25 @@ static int dcn316_get_active_display_cnt_wa( return display_count; } -static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, + bool safe_to_lower, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = safe_to_lower + ? &context->res_ctx.pipe_ctx[i] + : &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; - if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || - dc_is_virtual_signal(pipe->stream->signal))) { + if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || + !pipe->stream->link_enc)) { if (disable) { - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + reset_sync_context_for_pipe(dc, context, i); } else pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); @@ -207,11 +212,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn316_disable_otg_wa(clk_mgr_base, context, true); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn316_disable_otg_wa(clk_mgr_base, context, false); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); update_dispclk = true; } @@ -480,7 +485,8 @@ static void dcn316_clk_mgr_helper_populate_bw_params( j = -1; - ASSERT(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL); + static_assert(NUM_DF_PSTATE_LEVELS <= MAX_NUM_DPM_LVL, + "number of reported pstate levels exceeds maximum"); /* Find lowest DPM, FCLK is filled in reverse order*/ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index bec252e1dd27..b9e1f3e0b31d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -29,6 +29,7 @@ #include "dcn20/dcn20_clk_mgr.h" #include "dce100/dce_clk_mgr.h" #include "dcn31/dcn31_clk_mgr.h" +#include "dcn32/dcn32_clk_mgr.h" #include "reg_helper.h" #include "core_types.h" #include "dm_helpers.h" @@ -40,7 +41,6 @@ #include "dcn/dcn_3_2_0_offset.h" #include "dcn/dcn_3_2_0_sh_mask.h" -#include "dcn32/dcn32_clk_mgr.h" #include "dml/dcn32/dcn32_fpu.h" #define DCN_BASE__INST0_SEG1 0x000000C0 @@ -829,7 +829,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, dmcu->funcs->set_psr_wait_loop(dmcu, clk_mgr_base->clks.dispclk_khz / 1000 / 7); - if (dc->config.enable_auto_dpm_test_logs && safe_to_lower) { + if (dc->config.enable_auto_dpm_test_logs) { dcn32_auto_dpm_test_log(new_clocks, clk_mgr, context); } } @@ -1199,11 +1199,19 @@ void dcn32_clk_mgr_construct( clk_mgr->smu_present = false; clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL); + if (!clk_mgr->base.bw_params) { + BREAK_TO_DEBUGGER(); + return; + } /* need physical address of table to give to PMFW */ clk_mgr->wm_range_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART, sizeof(WatermarksExternal_t), &clk_mgr->wm_range_table_addr); + if (!clk_mgr->wm_range_table) { + BREAK_TO_DEBUGGER(); + return; + } } void dcn32_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c index df244b175fdb..f2f60478b1a6 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.c @@ -49,6 +49,7 @@ */ static uint32_t dcn32_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, unsigned int delay_us, unsigned int max_retries) { + const uint32_t initial_max_retries = max_retries; uint32_t reg = 0; do { @@ -62,6 +63,8 @@ static uint32_t dcn32_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, un udelay(delay_us); } while (max_retries--); + TRACE_SMU_DELAY(delay_us * (initial_max_retries - max_retries), clk_mgr->base.ctx); + return reg; } @@ -79,6 +82,8 @@ static bool dcn32_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr, uint /* Trigger the message transaction by writing the message ID */ REG_WRITE(DAL_MSG_REG, msg_id); + TRACE_SMU_MSG(msg_id, param_in, clk_mgr->base.ctx); + /* Wait for response */ if (dcn32_smu_wait_for_response(clk_mgr, 10, 200000) == DALSMC_Result_OK) { if (param_out) @@ -115,6 +120,8 @@ static uint32_t dcn32_smu_wait_for_response_delay(struct clk_mgr_internal *clk_m *total_delay_us += delay_us; } while (max_retries--); + TRACE_SMU_DELAY(*total_delay_us, clk_mgr->base.ctx); + return reg; } @@ -135,6 +142,8 @@ static bool dcn32_smu_send_msg_with_param_delay(struct clk_mgr_internal *clk_mgr /* Trigger the message transaction by writing the message ID */ REG_WRITE(DAL_MSG_REG, msg_id); + TRACE_SMU_MSG(msg_id, param_in, clk_mgr->base.ctx); + /* Wait for response */ if (dcn32_smu_wait_for_response_delay(clk_mgr, 10, 200000, &delay2_us) == DALSMC_Result_OK) { if (param_out) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.h index c76352a817de..5c44ab0e8667 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr_smu_msg.h @@ -37,10 +37,9 @@ #define DALSMC_Result_OK 0x1 void dcn32_smu_send_fclk_pstate_message(struct clk_mgr_internal *clk_mgr, bool enable); -void dcn32_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); -void dcn32_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr); void dcn32_smu_send_cab_for_uclk_message(struct clk_mgr_internal *clk_mgr, unsigned int num_ways); void dcn32_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); +void dcn32_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr); unsigned int dcn32_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz); void dcn32_smu_wait_for_dmub_ack_mclk(struct clk_mgr_internal *clk_mgr, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 101fe96287cb..6c9b4e6491a5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -73,6 +73,12 @@ #define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK 0x00000007L #define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK 0x000F0000L +#define regCLK5_0_CLK5_spll_field_8 0x464b +#define regCLK5_0_CLK5_spll_field_8_BASE_IDX 0 + +#define CLK5_0_CLK5_spll_field_8__spll_ssc_en__SHIFT 0xd +#define CLK5_0_CLK5_spll_field_8__spll_ssc_en_MASK 0x00002000L + #define SMU_VER_THRESHOLD 0x5D4A00 //93.74.0 #define REG(reg_name) \ @@ -246,7 +252,8 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, } if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) { - dcn35_smu_set_dtbclk(clk_mgr, false); + if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk) + dcn35_smu_set_dtbclk(clk_mgr, false); clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; } /* check that we're not already in lower */ @@ -411,6 +418,17 @@ static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs { } +static bool dcn35_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_context *ctx = clk_mgr->base.ctx; + uint32_t ssc_enable; + + REG_GET(CLK5_0_CLK5_spll_field_8, spll_ssc_en, &ssc_enable); + + return ssc_enable == 1; +} + static void init_clk_states(struct clk_mgr *clk_mgr) { struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); @@ -428,7 +446,16 @@ static void init_clk_states(struct clk_mgr *clk_mgr) void dcn35_init_clocks(struct clk_mgr *clk_mgr) { + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); init_clk_states(clk_mgr); + + // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk + if (dcn35_is_spll_ssc_enabled(clk_mgr)) + clk_mgr->dp_dto_source_clock_in_khz = + dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr->dprefclk_khz); + else + clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz; + } static struct clk_bw_params dcn35_bw_params = { .vram_type = Ddr4MemType, @@ -517,6 +544,28 @@ static DpmClocks_t_dcn35 dummy_clocks; static struct dcn35_watermarks dummy_wms = { 0 }; +static struct dcn35_ss_info_table ss_info_table = { + .ss_divider = 1000, + .ss_percentage = {0, 0, 375, 375, 375} +}; + +static void dcn35_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr) +{ + struct dc_context *ctx = clk_mgr->base.ctx; + uint32_t clock_source; + + REG_GET(CLK1_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL, &clock_source); + // If it's DFS mode, clock_source is 0. + if (dcn35_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(ss_info_table.ss_percentage))) { + clk_mgr->dprefclk_ss_percentage = ss_info_table.ss_percentage[clock_source]; + + if (clk_mgr->dprefclk_ss_percentage != 0) { + clk_mgr->ss_on_dprefclk = true; + clk_mgr->dprefclk_ss_divider = ss_info_table.ss_divider; + } + } +} + static void dcn35_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn35_watermarks *table) { int i, num_valid_sets; @@ -841,35 +890,6 @@ static void dcn35_set_low_power_state(struct clk_mgr *clk_mgr_base) } } -static void dcn35_set_ips_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle) -{ - struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - struct dc *dc = clk_mgr_base->ctx->dc; - uint32_t val = dcn35_smu_read_ips_scratch(clk_mgr); - - if (dc->config.disable_ips == DMUB_IPS_ENABLE || - dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) { - val = val & ~DMUB_IPS1_ALLOW_MASK; - val = val & ~DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) { - val |= DMUB_IPS1_ALLOW_MASK; - val |= DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) { - val = val & ~DMUB_IPS1_ALLOW_MASK; - val |= DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) { - val = val & ~DMUB_IPS1_ALLOW_MASK; - val = val & ~DMUB_IPS2_ALLOW_MASK; - } - - if (!allow_idle) { - val |= DMUB_IPS1_ALLOW_MASK; - val |= DMUB_IPS2_ALLOW_MASK; - } - - dcn35_smu_write_ips_scratch(clk_mgr, val); -} - static void dcn35_exit_low_power_state(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); @@ -889,13 +909,6 @@ static bool dcn35_is_ips_supported(struct clk_mgr *clk_mgr_base) return ips_supported; } -static uint32_t dcn35_get_ips_idle_state(struct clk_mgr *clk_mgr_base) -{ - struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - - return dcn35_smu_read_ips_scratch(clk_mgr); -} - static void dcn35_init_clocks_fpga(struct clk_mgr *clk_mgr) { init_clk_states(clk_mgr); @@ -983,8 +996,6 @@ static struct clk_mgr_funcs dcn35_funcs = { .set_low_power_state = dcn35_set_low_power_state, .exit_low_power_state = dcn35_exit_low_power_state, .is_ips_supported = dcn35_is_ips_supported, - .set_idle_state = dcn35_set_ips_idle_state, - .get_idle_state = dcn35_get_ips_idle_state }; struct clk_mgr_funcs dcn35_fpga_funcs = { @@ -1061,6 +1072,8 @@ void dcn35_clk_mgr_construct( dce_clock_read_ss_info(&clk_mgr->base); /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ + dcn35_read_ss_info_from_lut(&clk_mgr->base); + clk_mgr->base.base.bw_params = &dcn35_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c index 9e588c56c570..1399b41dfd1c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c @@ -487,24 +487,3 @@ int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr) //smu_print("%s: VBIOSSMC_MSG_QueryIPS2Support return = %x\n", __func__, retv); return retv; } - -void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param) -{ - if (!clk_mgr->smu_present) - return; - - REG_WRITE(MP1_SMN_C2PMSG_71, param); - //smu_print("%s: write_ips_scratch = %x\n", __func__, param); -} - -uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr) -{ - uint32_t retv; - - if (!clk_mgr->smu_present) - return 0; - - retv = REG_READ(MP1_SMN_C2PMSG_71); - //smu_print("%s: dcn35_smu_read_ips_scratch = %x\n", __func__, retv); - return retv; -} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h index 2b8e6959a03d..06cd3cc6d36e 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.h @@ -198,6 +198,4 @@ int dcn35_smu_exit_low_power_state(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_ips_supported(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr); int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr); -void dcn35_smu_write_ips_scratch(struct clk_mgr_internal *clk_mgr, uint32_t param); -uint32_t dcn35_smu_read_ips_scratch(struct clk_mgr_internal *clk_mgr); #endif /* DAL_DC_35_SMU_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 03b554e912a2..eb2aa90b370b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -36,6 +36,7 @@ #include "resource.h" #include "dc_state.h" #include "dc_state_priv.h" +#include "dc_plane_priv.h" #include "gpio_service_interface.h" #include "clk_mgr.h" @@ -212,7 +213,8 @@ static bool create_links( connectors_num, num_virtual_links); - for (i = 0; i < connectors_num; i++) { + // condition loop on link_count to allow skipping invalid indices + for (i = 0; dc->link_count < connectors_num && i < MAX_LINKS; i++) { struct link_init_data link_init_params = {0}; struct dc_link *link; @@ -386,6 +388,30 @@ static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) *perf_trace = NULL; } +static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struct dc_crtc_timing_adjust *adjust) +{ + if (!dc || !stream || !adjust) + return false; + + if (!dc->current_state) + return false; + + int i; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + + if (pipe->stream == stream && pipe->stream_res.tg) { + if (dc->hwss.set_long_vtotal) + dc->hwss.set_long_vtotal(&pipe, 1, adjust->v_total_min, adjust->v_total_max); + + return true; + } + } + + return false; +} + /** * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR * @dc: dc reference @@ -420,6 +446,15 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; stream->adjust.v_total_min = adjust->v_total_min; + stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; + + if (dc->caps.max_v_total != 0 && + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { + if (adjust->allow_otg_v_count_halt) + return set_long_vtotal(dc, stream, adjust); + else + return false; + } for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; @@ -1055,8 +1090,7 @@ static bool dc_construct(struct dc *dc, * is initialized in dc_create_resource_pool because * on creation it copies the contents of dc->dml */ - - dc->current_state = dc_state_create(dc); + dc->current_state = dc_state_create(dc, NULL); if (!dc->current_state) { dm_error("%s: failed to create validate ctx\n", __func__); @@ -1272,7 +1306,7 @@ static void disable_vbios_mode_if_required( if (link != NULL && link->link_enc->funcs->is_dig_enabled(link->link_enc)) { unsigned int enc_inst, tg_inst = 0; - unsigned int pix_clk_100hz; + unsigned int pix_clk_100hz = 0; enc_inst = link->link_enc->funcs->get_dig_frontend(link->link_enc); if (enc_inst != ENGINE_ID_UNKNOWN) { @@ -1759,7 +1793,7 @@ bool dc_validate_boot_timing(const struct dc *dc, return false; if (dc_is_dp_signal(link->connector_signal)) { - unsigned int pix_clk_100hz; + unsigned int pix_clk_100hz = 0; uint32_t numOdmPipes = 1; uint32_t id_src[4] = {0}; @@ -2085,15 +2119,14 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c return result; } -static bool commit_minimal_transition_state_legacy(struct dc *dc, +static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context); /** * dc_commit_streams - Commit current stream state * * @dc: DC object with the commit state to be configured in the hardware - * @streams: Array with a list of stream state - * @stream_count: Total of streams + * @params: Parameters for the commit, including the streams to be committed * * Function responsible for commit streams change to the hardware. * @@ -2101,9 +2134,7 @@ static bool commit_minimal_transition_state_legacy(struct dc *dc, * Return DC_OK if everything work as expected, otherwise, return a dc_status * code. */ -enum dc_status dc_commit_streams(struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count) +enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params *params) { int i, j; struct dc_state *context; @@ -2112,18 +2143,22 @@ enum dc_status dc_commit_streams(struct dc *dc, struct pipe_ctx *pipe; bool handle_exit_odm2to1 = false; + if (!params) + return DC_ERROR_UNEXPECTED; + if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW) return res; - if (!streams_changed(dc, streams, stream_count)) + if (!streams_changed(dc, params->streams, params->stream_count) && + dc->current_state->power_source == params->power_source) return res; dc_exit_ips_for_hw_access(dc); - DC_LOG_DC("%s: %d streams\n", __func__, stream_count); + DC_LOG_DC("%s: %d streams\n", __func__, params->stream_count); - for (i = 0; i < stream_count; i++) { - struct dc_stream_state *stream = streams[i]; + for (i = 0; i < params->stream_count; i++) { + struct dc_stream_state *stream = params->streams[i]; struct dc_stream_status *status = dc_stream_get_status(stream); dc_stream_log(dc, stream); @@ -2141,7 +2176,7 @@ enum dc_status dc_commit_streams(struct dc *dc, * scenario, it uses extra pipes than needed to reduce power consumption * We need to switch off this feature to make room for new streams. */ - if (stream_count > dc->current_state->stream_count && + if (params->stream_count > dc->current_state->stream_count && dc->current_state->stream_count == 1) { for (i = 0; i < dc->res_pool->pipe_count; i++) { pipe = &dc->current_state->res_ctx.pipe_ctx[i]; @@ -2151,13 +2186,15 @@ enum dc_status dc_commit_streams(struct dc *dc, } if (handle_exit_odm2to1) - res = commit_minimal_transition_state_legacy(dc, dc->current_state); + res = commit_minimal_transition_state(dc, dc->current_state); context = dc_state_create_current_copy(dc); if (!context) goto context_alloc_fail; - res = dc_validate_with_context(dc, set, stream_count, context, false); + context->power_source = params->power_source; + + res = dc_validate_with_context(dc, set, params->stream_count, context, false); if (res != DC_OK) { BREAK_TO_DEBUGGER(); goto fail; @@ -2165,16 +2202,16 @@ enum dc_status dc_commit_streams(struct dc *dc, res = dc_commit_state_no_check(dc, context); - for (i = 0; i < stream_count; i++) { + for (i = 0; i < params->stream_count; i++) { for (j = 0; j < context->stream_count; j++) { - if (streams[i]->stream_id == context->streams[j]->stream_id) - streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; + if (params->streams[i]->stream_id == context->streams[j]->stream_id) + params->streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst; - if (dc_is_embedded_signal(streams[i]->signal)) { - struct dc_stream_status *status = dc_state_get_stream_status(context, streams[i]); + if (dc_is_embedded_signal(params->streams[i]->signal)) { + struct dc_stream_status *status = dc_state_get_stream_status(context, params->streams[i]); if (dc->hwss.is_abm_supported) - status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]); + status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, params->streams[i]); else status->is_abm_supported = true; } @@ -2818,55 +2855,45 @@ static void copy_surface_update_to_plane( srf_update->plane_info->layer_index; } - if (srf_update->gamma && - (surface->gamma_correction != - srf_update->gamma)) { - memcpy(&surface->gamma_correction->entries, + if (srf_update->gamma) { + memcpy(&surface->gamma_correction.entries, &srf_update->gamma->entries, sizeof(struct dc_gamma_entries)); - surface->gamma_correction->is_identity = + surface->gamma_correction.is_identity = srf_update->gamma->is_identity; - surface->gamma_correction->num_entries = + surface->gamma_correction.num_entries = srf_update->gamma->num_entries; - surface->gamma_correction->type = + surface->gamma_correction.type = srf_update->gamma->type; } - if (srf_update->in_transfer_func && - (surface->in_transfer_func != - srf_update->in_transfer_func)) { - surface->in_transfer_func->sdr_ref_white_level = + if (srf_update->in_transfer_func) { + surface->in_transfer_func.sdr_ref_white_level = srf_update->in_transfer_func->sdr_ref_white_level; - surface->in_transfer_func->tf = + surface->in_transfer_func.tf = srf_update->in_transfer_func->tf; - surface->in_transfer_func->type = + surface->in_transfer_func.type = srf_update->in_transfer_func->type; - memcpy(&surface->in_transfer_func->tf_pts, + memcpy(&surface->in_transfer_func.tf_pts, &srf_update->in_transfer_func->tf_pts, sizeof(struct dc_transfer_func_distributed_points)); } - if (srf_update->func_shaper && - (surface->in_shaper_func != - srf_update->func_shaper)) - memcpy(surface->in_shaper_func, srf_update->func_shaper, - sizeof(*surface->in_shaper_func)); + if (srf_update->func_shaper) + memcpy(&surface->in_shaper_func, srf_update->func_shaper, + sizeof(surface->in_shaper_func)); - if (srf_update->lut3d_func && - (surface->lut3d_func != - srf_update->lut3d_func)) - memcpy(surface->lut3d_func, srf_update->lut3d_func, - sizeof(*surface->lut3d_func)); + if (srf_update->lut3d_func) + memcpy(&surface->lut3d_func, srf_update->lut3d_func, + sizeof(surface->lut3d_func)); if (srf_update->hdr_mult.value) surface->hdr_mult = srf_update->hdr_mult; - if (srf_update->blend_tf && - (surface->blend_tf != - srf_update->blend_tf)) - memcpy(surface->blend_tf, srf_update->blend_tf, - sizeof(*surface->blend_tf)); + if (srf_update->blend_tf) + memcpy(&surface->blend_tf, srf_update->blend_tf, + sizeof(surface->blend_tf)); if (srf_update->input_csc_color_matrix) surface->input_csc_color_matrix = @@ -2897,14 +2924,13 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->dst.height && update->dst.width) stream->dst = update->dst; - if (update->out_transfer_func && - stream->out_transfer_func != update->out_transfer_func) { - stream->out_transfer_func->sdr_ref_white_level = + if (update->out_transfer_func) { + stream->out_transfer_func.sdr_ref_white_level = update->out_transfer_func->sdr_ref_white_level; - stream->out_transfer_func->tf = update->out_transfer_func->tf; - stream->out_transfer_func->type = + stream->out_transfer_func.tf = update->out_transfer_func->tf; + stream->out_transfer_func.type = update->out_transfer_func->type; - memcpy(&stream->out_transfer_func->tf_pts, + memcpy(&stream->out_transfer_func.tf_pts, &update->out_transfer_func->tf_pts, sizeof(struct dc_transfer_func_distributed_points)); } @@ -3017,15 +3043,8 @@ static void backup_planes_and_stream_state( for (i = 0; i < status->plane_count; i++) { scratch->plane_states[i] = *status->plane_states[i]; - scratch->gamma_correction[i] = *status->plane_states[i]->gamma_correction; - scratch->in_transfer_func[i] = *status->plane_states[i]->in_transfer_func; - scratch->lut3d_func[i] = *status->plane_states[i]->lut3d_func; - scratch->in_shaper_func[i] = *status->plane_states[i]->in_shaper_func; - scratch->blend_tf[i] = *status->plane_states[i]->blend_tf; } scratch->stream_state = *stream; - if (stream->out_transfer_func) - scratch->out_transfer_func = *stream->out_transfer_func; } static void restore_planes_and_stream_state( @@ -3040,17 +3059,67 @@ static void restore_planes_and_stream_state( for (i = 0; i < status->plane_count; i++) { *status->plane_states[i] = scratch->plane_states[i]; - *status->plane_states[i]->gamma_correction = scratch->gamma_correction[i]; - *status->plane_states[i]->in_transfer_func = scratch->in_transfer_func[i]; - *status->plane_states[i]->lut3d_func = scratch->lut3d_func[i]; - *status->plane_states[i]->in_shaper_func = scratch->in_shaper_func[i]; - *status->plane_states[i]->blend_tf = scratch->blend_tf[i]; } *stream = scratch->stream_state; - if (stream->out_transfer_func) - *stream->out_transfer_func = scratch->out_transfer_func; } +/** + * update_seamless_boot_flags() - Helper function for updating seamless boot flags + * + * @dc: Current DC state + * @context: New DC state to be programmed + * @surface_count: Number of surfaces that have an updated + * @stream: Corresponding stream to be updated in the current flip + * + * Updating seamless boot flags do not need to be part of the commit sequence. This + * helper function will update the seamless boot flags on each flip (if required) + * outside of the HW commit sequence (fast or slow). + * + * Return: void + */ +static void update_seamless_boot_flags(struct dc *dc, + struct dc_state *context, + int surface_count, + struct dc_stream_state *stream) +{ + if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) { + /* Optimize seamless boot flag keeps clocks and watermarks high until + * first flip. After first flip, optimization is required to lower + * bandwidth. Important to note that it is expected UEFI will + * only light up a single display on POST, therefore we only expect + * one stream with seamless boot flag set. + */ + if (stream->apply_seamless_boot_optimization) { + stream->apply_seamless_boot_optimization = false; + + if (get_seamless_boot_stream_count(context) == 0) + dc->optimized_required = true; + } + } +} + +/** + * update_planes_and_stream_state() - The function takes planes and stream + * updates as inputs and determines the appropriate update type. If update type + * is FULL, the function allocates a new context, populates and validates it. + * Otherwise, it updates current dc context. The function will return both + * new_context and new_update_type back to the caller. The function also backs + * up both current and new contexts into corresponding dc state scratch memory. + * TODO: The function does too many things, and even conditionally allocates dc + * context memory implicitly. We should consider to break it down. + * + * @dc: Current DC state + * @srf_updates: an array of surface updates + * @surface_count: surface update count + * @stream: Corresponding stream to be updated + * @stream_update: stream update + * @new_update_type: [out] determined update type by the function + * @new_context: [out] new context allocated and validated if update type is + * FULL, reference to current context if update type is less than FULL. + * + * Return: true if a valid update is populated into new_context, false + * otherwise. + */ static bool update_planes_and_stream_state(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, @@ -3074,9 +3143,10 @@ static bool update_planes_and_stream_state(struct dc *dc, } context = dc->current_state; - backup_planes_and_stream_state(&dc->current_state->scratch, stream); update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); + if (update_type == UPDATE_TYPE_FULL) + backup_planes_and_stream_state(&dc->scratch.current_state, stream); /* update current stream with the new updates */ copy_stream_update_to_stream(dc, context, stream, stream_update); @@ -3145,7 +3215,10 @@ static bool update_planes_and_stream_state(struct dc *dc, for (i = 0; i < surface_count; i++) { struct dc_plane_state *surface = srf_updates[i].surface; - if (update_type >= UPDATE_TYPE_MED) { + if (update_type != UPDATE_TYPE_MED) + continue; + if (surface->update_flags.bits.clip_size_change || + surface->update_flags.bits.position_change) { for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -3162,19 +3235,13 @@ static bool update_planes_and_stream_state(struct dc *dc, BREAK_TO_DEBUGGER(); goto fail; } - - for (i = 0; i < context->stream_count; i++) { - struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(&context->res_ctx, - context->streams[i]); - - if (otg_master && otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) - resource_build_test_pattern_params(&context->res_ctx, otg_master); - } } + update_seamless_boot_flags(dc, context, surface_count, stream); *new_context = context; *new_update_type = update_type; - backup_planes_and_stream_state(&context->scratch, stream); + if (update_type == UPDATE_TYPE_FULL) + backup_planes_and_stream_state(&dc->scratch.new_state, stream); return true; @@ -3263,12 +3330,26 @@ static void commit_planes_do_stream_update(struct dc *dc, } if (stream_update->pending_test_pattern) { - dc_link_dp_set_test_pattern(stream->link, + /* + * test pattern params depends on ODM topology + * changes that we could be applying to front + * end. Since at the current stage front end + * changes are not yet applied. We can only + * apply test pattern in hw based on current + * state and populate the final test pattern + * params in new state. If current and new test + * pattern params are different as result of + * different ODM topology being used, it will be + * detected and handle during front end + * programming update. + */ + dc->link_srv->dp_set_test_pattern(stream->link, stream->test_pattern.type, stream->test_pattern.color_space, stream->test_pattern.p_link_settings, stream->test_pattern.p_custom_pattern, stream->test_pattern.cust_pattern_size); + resource_build_test_pattern_params(&context->res_ctx, pipe_ctx); } if (stream_update->dpms_off) { @@ -3365,6 +3446,7 @@ void dc_dmub_update_dirty_rect(struct dc *dc, if (srf_updates[i].surface->flip_immediate) continue; + update_dirty_rect->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1; update_dirty_rect->dirty_rect_count = flip_addr->dirty_rect_count; memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects, sizeof(flip_addr->dirty_rects)); @@ -3481,6 +3563,7 @@ static void commit_planes_for_stream_fast(struct dc *dc, int i, j; struct pipe_ctx *top_pipe_to_program = NULL; struct dc_stream_status *stream_status = NULL; + dc_exit_ips_for_hw_access(dc); dc_z10_restore(dc); @@ -3538,7 +3621,8 @@ static void commit_planes_for_stream_fast(struct dc *dc, context->block_sequence, &(context->block_sequence_steps), top_pipe_to_program, - stream_status); + stream_status, + context); hwss_execute_sequence(dc, context->block_sequence, context->block_sequence_steps); @@ -4067,24 +4151,14 @@ struct pipe_split_policy_backup { bool dynamic_odm_policy; bool subvp_policy; enum pipe_split_policy mpc_policy; + char force_odm[MAX_PIPES]; }; -static void release_minimal_transition_state(struct dc *dc, - struct dc_state *context, struct pipe_split_policy_backup *policy) +static void backup_and_set_minimal_pipe_split_policy(struct dc *dc, + struct dc_state *context, + struct pipe_split_policy_backup *policy) { - dc_state_release(context); - /* restore previous pipe split and odm policy */ - if (!dc->config.is_vmin_only_asic) - dc->debug.pipe_split_policy = policy->mpc_policy; - dc->debug.enable_single_display_2to1_odm_policy = policy->dynamic_odm_policy; - dc->debug.force_disable_subvp = policy->subvp_policy; -} - -static struct dc_state *create_minimal_transition_state(struct dc *dc, - struct dc_state *base_context, struct pipe_split_policy_backup *policy) -{ - struct dc_state *minimal_transition_context = NULL; - unsigned int i, j; + int i; if (!dc->config.is_vmin_only_asic) { policy->mpc_policy = dc->debug.pipe_split_policy; @@ -4094,97 +4168,257 @@ static struct dc_state *create_minimal_transition_state(struct dc *dc, dc->debug.enable_single_display_2to1_odm_policy = false; policy->subvp_policy = dc->debug.force_disable_subvp; dc->debug.force_disable_subvp = true; + for (i = 0; i < context->stream_count; i++) { + policy->force_odm[i] = context->streams[i]->debug.force_odm_combine_segments; + context->streams[i]->debug.force_odm_combine_segments = 0; + } +} + +static void restore_minimal_pipe_split_policy(struct dc *dc, + struct dc_state *context, + struct pipe_split_policy_backup *policy) +{ + uint8_t i; + + if (!dc->config.is_vmin_only_asic) + dc->debug.pipe_split_policy = policy->mpc_policy; + dc->debug.enable_single_display_2to1_odm_policy = + policy->dynamic_odm_policy; + dc->debug.force_disable_subvp = policy->subvp_policy; + for (i = 0; i < context->stream_count; i++) + context->streams[i]->debug.force_odm_combine_segments = policy->force_odm[i]; +} + +static void release_minimal_transition_state(struct dc *dc, + struct dc_state *minimal_transition_context, + struct dc_state *base_context, + struct pipe_split_policy_backup *policy) +{ + restore_minimal_pipe_split_policy(dc, base_context, policy); + dc_state_release(minimal_transition_context); +} + +static void force_vsync_flip_in_minimal_transition_context(struct dc_state *context) +{ + uint8_t i; + int j; + struct dc_stream_status *stream_status; + + for (i = 0; i < context->stream_count; i++) { + stream_status = &context->stream_status[i]; + + for (j = 0; j < stream_status->plane_count; j++) + stream_status->plane_states[j]->flip_immediate = false; + } +} + +static struct dc_state *create_minimal_transition_state(struct dc *dc, + struct dc_state *base_context, struct pipe_split_policy_backup *policy) +{ + struct dc_state *minimal_transition_context = NULL; minimal_transition_context = dc_state_create_copy(base_context); if (!minimal_transition_context) return NULL; + backup_and_set_minimal_pipe_split_policy(dc, base_context, policy); /* commit minimal state */ if (dc->res_pool->funcs->validate_bandwidth(dc, minimal_transition_context, false)) { - for (i = 0; i < minimal_transition_context->stream_count; i++) { - struct dc_stream_status *stream_status = &minimal_transition_context->stream_status[i]; - - for (j = 0; j < stream_status->plane_count; j++) { - struct dc_plane_state *plane_state = stream_status->plane_states[j]; - - /* force vsync flip when reconfiguring pipes to prevent underflow - * and corruption - */ - plane_state->flip_immediate = false; - } - } + /* prevent underflow and corruption when reconfiguring pipes */ + force_vsync_flip_in_minimal_transition_context(minimal_transition_context); } else { - /* this should never happen */ - release_minimal_transition_state(dc, minimal_transition_context, policy); + /* + * This should never happen, minimal transition state should + * always be validated first before adding pipe split features. + */ + release_minimal_transition_state(dc, minimal_transition_context, base_context, policy); BREAK_TO_DEBUGGER(); minimal_transition_context = NULL; } return minimal_transition_context; } +static bool is_pipe_topology_transition_seamless_with_intermediate_step( + struct dc *dc, + struct dc_state *initial_state, + struct dc_state *intermediate_state, + struct dc_state *final_state) +{ + return dc->hwss.is_pipe_topology_transition_seamless(dc, initial_state, + intermediate_state) && + dc->hwss.is_pipe_topology_transition_seamless(dc, + intermediate_state, final_state); +} -/** - * commit_minimal_transition_state - Commit a minimal state based on current or new context - * - * @dc: DC structure, used to get the current state - * @context: New context - * @stream: Stream getting the update for the flip - * - * The function takes in current state and new state and determine a minimal transition state - * as the intermediate step which could make the transition between current and new states - * seamless. If found, it will commit the minimal transition state and update current state to - * this minimal transition state and return true, if not, it will return false. - * - * Return: - * Return True if the minimal transition succeeded, false otherwise - */ -static bool commit_minimal_transition_state(struct dc *dc, - struct dc_state *context, - struct dc_stream_state *stream) +static void swap_and_release_current_context(struct dc *dc, + struct dc_state *new_context, struct dc_stream_state *stream) +{ + + int i; + struct dc_state *old = dc->current_state; + struct pipe_ctx *pipe_ctx; + + /* Since memory free requires elevated IRQ, an interrupt + * request is generated by mem free. If this happens + * between freeing and reassigning the context, our vsync + * interrupt will call into dc and cause a memory + * corruption. Hence, we first reassign the context, + * then free the old context. + */ + dc->current_state = new_context; + dc_state_release(old); + + // clear any forced full updates + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &new_context->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->plane_state && pipe_ctx->stream == stream) + pipe_ctx->plane_state->force_full_update = false; + } +} + +static int initialize_empty_surface_updates( + struct dc_stream_state *stream, + struct dc_surface_update *srf_updates) +{ + struct dc_stream_status *status = dc_stream_get_status(stream); + int i; + + if (!status) + return 0; + + for (i = 0; i < status->plane_count; i++) + srf_updates[i].surface = status->plane_states[i]; + + return status->plane_count; +} + +static bool commit_minimal_transition_based_on_new_context(struct dc *dc, + struct dc_state *new_context, + struct dc_stream_state *stream, + struct dc_surface_update *srf_updates, + int surface_count) { bool success = false; - struct dc_state *minimal_transition_context; struct pipe_split_policy_backup policy; + struct dc_state *intermediate_context = + create_minimal_transition_state(dc, new_context, + &policy); - /* commit based on new context */ - minimal_transition_context = create_minimal_transition_state(dc, - context, &policy); - if (minimal_transition_context) { - if (dc->hwss.is_pipe_topology_transition_seamless( - dc, dc->current_state, minimal_transition_context) && - dc->hwss.is_pipe_topology_transition_seamless( - dc, minimal_transition_context, context)) { - DC_LOG_DC("%s base = new state\n", __func__); - - success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK; + if (intermediate_context) { + if (is_pipe_topology_transition_seamless_with_intermediate_step( + dc, + dc->current_state, + intermediate_context, + new_context)) { + DC_LOG_DC("commit minimal transition state: base = new state\n"); + commit_planes_for_stream(dc, srf_updates, + surface_count, stream, NULL, + UPDATE_TYPE_FULL, intermediate_context); + swap_and_release_current_context( + dc, intermediate_context, stream); + dc_state_retain(dc->current_state); + success = true; } - release_minimal_transition_state(dc, minimal_transition_context, &policy); + release_minimal_transition_state( + dc, intermediate_context, new_context, &policy); } + return success; +} - if (!success) { - /* commit based on current context */ - restore_planes_and_stream_state(&dc->current_state->scratch, stream); - minimal_transition_context = create_minimal_transition_state(dc, - dc->current_state, &policy); - if (minimal_transition_context) { - if (dc->hwss.is_pipe_topology_transition_seamless( - dc, dc->current_state, minimal_transition_context) && - dc->hwss.is_pipe_topology_transition_seamless( - dc, minimal_transition_context, context)) { - DC_LOG_DC("%s base = current state\n", __func__); - success = dc_commit_state_no_check(dc, minimal_transition_context) == DC_OK; - } - release_minimal_transition_state(dc, minimal_transition_context, &policy); +static bool commit_minimal_transition_based_on_current_context(struct dc *dc, + struct dc_state *new_context, struct dc_stream_state *stream) +{ + bool success = false; + struct pipe_split_policy_backup policy; + struct dc_state *intermediate_context; + struct dc_state *old_current_state = dc->current_state; + struct dc_surface_update srf_updates[MAX_SURFACE_NUM] = {0}; + int surface_count; + + /* + * Both current and new contexts share the same stream and plane state + * pointers. When new context is validated, stream and planes get + * populated with new updates such as new plane addresses. This makes + * the current context no longer valid because stream and planes are + * modified from the original. We backup current stream and plane states + * into scratch space whenever we are populating new context. So we can + * restore the original values back by calling the restore function now. + * This restores back the original stream and plane states associated + * with the current state. + */ + restore_planes_and_stream_state(&dc->scratch.current_state, stream); + dc_state_retain(old_current_state); + intermediate_context = create_minimal_transition_state(dc, + old_current_state, &policy); + + if (intermediate_context) { + if (is_pipe_topology_transition_seamless_with_intermediate_step( + dc, + dc->current_state, + intermediate_context, + new_context)) { + DC_LOG_DC("commit minimal transition state: base = current state\n"); + surface_count = initialize_empty_surface_updates( + stream, srf_updates); + commit_planes_for_stream(dc, srf_updates, + surface_count, stream, NULL, + UPDATE_TYPE_FULL, intermediate_context); + swap_and_release_current_context( + dc, intermediate_context, stream); + dc_state_retain(dc->current_state); + success = true; } - restore_planes_and_stream_state(&context->scratch, stream); + release_minimal_transition_state(dc, intermediate_context, + old_current_state, &policy); } - - ASSERT(success); + dc_state_release(old_current_state); + /* + * Restore stream and plane states back to the values associated with + * new context. + */ + restore_planes_and_stream_state(&dc->scratch.new_state, stream); return success; } /** - * commit_minimal_transition_state_legacy - Create a transition pipe split state + * commit_minimal_transition_state_in_dc_update - Commit a minimal state based + * on current or new context + * + * @dc: DC structure, used to get the current state + * @new_context: New context + * @stream: Stream getting the update for the flip + * @srf_updates: Surface updates + * @surface_count: Number of surfaces + * + * The function takes in current state and new state and determine a minimal + * transition state as the intermediate step which could make the transition + * between current and new states seamless. If found, it will commit the minimal + * transition state and update current state to this minimal transition state + * and return true, if not, it will return false. + * + * Return: + * Return True if the minimal transition succeeded, false otherwise + */ +static bool commit_minimal_transition_state_in_dc_update(struct dc *dc, + struct dc_state *new_context, + struct dc_stream_state *stream, + struct dc_surface_update *srf_updates, + int surface_count) +{ + bool success = commit_minimal_transition_based_on_new_context( + dc, new_context, stream, srf_updates, + surface_count); + if (!success) + success = commit_minimal_transition_based_on_current_context(dc, + new_context, stream); + if (!success) + DC_LOG_ERROR("Fail to commit a seamless minimal transition state between current and new states.\nThis pipe topology update is non-seamless!\n"); + return success; +} + +/** + * commit_minimal_transition_state - Create a transition pipe split state * * @dc: Used to get the current state status * @transition_base_context: New transition state @@ -4201,7 +4435,7 @@ static bool commit_minimal_transition_state(struct dc *dc, * Return: * Return false if something is wrong in the transition state. */ -static bool commit_minimal_transition_state_legacy(struct dc *dc, +static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context) { struct dc_state *transition_context; @@ -4262,12 +4496,14 @@ static bool commit_minimal_transition_state_legacy(struct dc *dc, dc->debug.pipe_split_policy != MPC_SPLIT_AVOID ? "MPC in Use" : "Unknown"); + dc_state_retain(transition_base_context); transition_context = create_minimal_transition_state(dc, transition_base_context, &policy); if (transition_context) { ret = dc_commit_state_no_check(dc, transition_context); - release_minimal_transition_state(dc, transition_context, &policy); + release_minimal_transition_state(dc, transition_context, transition_base_context, &policy); } + dc_state_release(transition_base_context); if (ret != DC_OK) { /* this should never happen */ @@ -4285,41 +4521,6 @@ static bool commit_minimal_transition_state_legacy(struct dc *dc, return true; } -/** - * update_seamless_boot_flags() - Helper function for updating seamless boot flags - * - * @dc: Current DC state - * @context: New DC state to be programmed - * @surface_count: Number of surfaces that have an updated - * @stream: Corresponding stream to be updated in the current flip - * - * Updating seamless boot flags do not need to be part of the commit sequence. This - * helper function will update the seamless boot flags on each flip (if required) - * outside of the HW commit sequence (fast or slow). - * - * Return: void - */ -static void update_seamless_boot_flags(struct dc *dc, - struct dc_state *context, - int surface_count, - struct dc_stream_state *stream) -{ - if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) { - /* Optimize seamless boot flag keeps clocks and watermarks high until - * first flip. After first flip, optimization is required to lower - * bandwidth. Important to note that it is expected UEFI will - * only light up a single display on POST, therefore we only expect - * one stream with seamless boot flag set. - */ - if (stream->apply_seamless_boot_optimization) { - stream->apply_seamless_boot_optimization = false; - - if (get_seamless_boot_stream_count(context) == 0) - dc->optimized_required = true; - } - } -} - static void populate_fast_updates(struct dc_fast_update *fast_update, struct dc_surface_update *srf_updates, int surface_count, @@ -4439,123 +4640,9 @@ static bool fast_update_only(struct dc *dc, && !full_update_required(dc, srf_updates, surface_count, stream_update, stream); } -bool dc_update_planes_and_stream(struct dc *dc, +static bool update_planes_and_stream_v1(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, - struct dc_stream_update *stream_update) -{ - struct dc_state *context; - enum surface_update_type update_type; - int i; - struct dc_fast_update fast_update[MAX_SURFACES] = {0}; - - /* In cases where MPO and split or ODM are used transitions can - * cause underflow. Apply stream configuration with minimal pipe - * split first to avoid unsupported transitions for active pipes. - */ - bool force_minimal_pipe_splitting = 0; - bool is_plane_addition = 0; - bool is_fast_update_only; - - dc_exit_ips_for_hw_access(dc); - - populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); - is_fast_update_only = fast_update_only(dc, fast_update, srf_updates, - surface_count, stream_update, stream); - force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( - dc, - stream, - srf_updates, - surface_count, - &is_plane_addition); - - /* on plane addition, minimal state is the current one */ - if (force_minimal_pipe_splitting && is_plane_addition && - !commit_minimal_transition_state_legacy(dc, dc->current_state)) - return false; - - if (!update_planes_and_stream_state( - dc, - srf_updates, - surface_count, - stream, - stream_update, - &update_type, - &context)) - return false; - - /* on plane removal, minimal state is the new one */ - if (force_minimal_pipe_splitting && !is_plane_addition) { - if (!commit_minimal_transition_state_legacy(dc, context)) { - dc_state_release(context); - return false; - } - update_type = UPDATE_TYPE_FULL; - } - - if (dc->hwss.is_pipe_topology_transition_seamless && - !dc->hwss.is_pipe_topology_transition_seamless( - dc, dc->current_state, context)) { - commit_minimal_transition_state(dc, - context, stream); - } - update_seamless_boot_flags(dc, context, surface_count, stream); - if (is_fast_update_only && !dc->debug.enable_legacy_fast_update) { - commit_planes_for_stream_fast(dc, - srf_updates, - surface_count, - stream, - stream_update, - update_type, - context); - } else { - if (!stream_update && - dc->hwss.is_pipe_topology_transition_seamless && - !dc->hwss.is_pipe_topology_transition_seamless( - dc, dc->current_state, context)) { - DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n"); - BREAK_TO_DEBUGGER(); - } - commit_planes_for_stream( - dc, - srf_updates, - surface_count, - stream, - stream_update, - update_type, - context); - } - - if (dc->current_state != context) { - - /* Since memory free requires elevated IRQL, an interrupt - * request is generated by mem free. If this happens - * between freeing and reassigning the context, our vsync - * interrupt will call into dc and cause a memory - * corruption BSOD. Hence, we first reassign the context, - * then free the old context. - */ - - struct dc_state *old = dc->current_state; - - dc->current_state = context; - dc_state_release(old); - - // clear any forced full updates - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (pipe_ctx->plane_state && pipe_ctx->stream == stream) - pipe_ctx->plane_state->force_full_update = false; - } - } - return true; -} - -void dc_commit_updates_for_stream(struct dc *dc, - struct dc_surface_update *srf_updates, - int surface_count, - struct dc_stream_state *stream, struct dc_stream_update *stream_update, struct dc_state *state) { @@ -4575,35 +4662,13 @@ void dc_commit_updates_for_stream(struct dc *dc, update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); - /* TODO: Since change commit sequence can have a huge impact, - * we decided to only enable it for DCN3x. However, as soon as - * we get more confident about this change we'll need to enable - * the new sequence for all ASICs. - */ - if (dc->ctx->dce_version >= DCN_VERSION_3_2) { - /* - * Previous frame finished and HW is ready for optimization. - */ - if (update_type == UPDATE_TYPE_FAST) - dc_post_update_surfaces_to_stream(dc); - - dc_update_planes_and_stream(dc, srf_updates, - surface_count, stream, - stream_update); - return; - } - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { /* initialize scratch memory for building context */ context = dc_state_create_copy(state); if (context == NULL) { DC_ERROR("Failed to allocate new validate context!\n"); - return; + return false; } for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -4620,7 +4685,6 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_post_update_surfaces_to_stream(dc); } - for (i = 0; i < surface_count; i++) { struct dc_plane_state *surface = srf_updates[i].surface; @@ -4645,13 +4709,12 @@ void dc_commit_updates_for_stream(struct dc *dc, if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { DC_ERROR("Mode validation failed for stream update!\n"); dc_state_release(context); - return; + return false; } } TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES); - update_seamless_boot_flags(dc, context, surface_count, stream); if (fast_update_only(dc, fast_update, srf_updates, surface_count, stream_update, stream) && !dc->debug.enable_legacy_fast_update) { commit_planes_for_stream_fast(dc, @@ -4692,9 +4755,252 @@ void dc_commit_updates_for_stream(struct dc *dc, dc_post_update_surfaces_to_stream(dc); TRACE_DCE_CLOCK_STATE(&context->bw_ctx.bw.dce); } + return true; +} - return; +static bool update_planes_and_stream_v2(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update) +{ + struct dc_state *context; + enum surface_update_type update_type; + struct dc_fast_update fast_update[MAX_SURFACES] = {0}; + /* In cases where MPO and split or ODM are used transitions can + * cause underflow. Apply stream configuration with minimal pipe + * split first to avoid unsupported transitions for active pipes. + */ + bool force_minimal_pipe_splitting = 0; + bool is_plane_addition = 0; + bool is_fast_update_only; + + populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); + is_fast_update_only = fast_update_only(dc, fast_update, srf_updates, + surface_count, stream_update, stream); + force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( + dc, + stream, + srf_updates, + surface_count, + &is_plane_addition); + + /* on plane addition, minimal state is the current one */ + if (force_minimal_pipe_splitting && is_plane_addition && + !commit_minimal_transition_state(dc, dc->current_state)) + return false; + + if (!update_planes_and_stream_state( + dc, + srf_updates, + surface_count, + stream, + stream_update, + &update_type, + &context)) + return false; + + /* on plane removal, minimal state is the new one */ + if (force_minimal_pipe_splitting && !is_plane_addition) { + if (!commit_minimal_transition_state(dc, context)) { + dc_state_release(context); + return false; + } + update_type = UPDATE_TYPE_FULL; + } + + if (dc->hwss.is_pipe_topology_transition_seamless && + !dc->hwss.is_pipe_topology_transition_seamless( + dc, dc->current_state, context)) + commit_minimal_transition_state_in_dc_update(dc, context, stream, + srf_updates, surface_count); + + if (is_fast_update_only && !dc->debug.enable_legacy_fast_update) { + commit_planes_for_stream_fast(dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + } else { + if (!stream_update && + dc->hwss.is_pipe_topology_transition_seamless && + !dc->hwss.is_pipe_topology_transition_seamless( + dc, dc->current_state, context)) { + DC_LOG_ERROR("performing non-seamless pipe topology transition with surface only update!\n"); + BREAK_TO_DEBUGGER(); + } + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + } + if (dc->current_state != context) + swap_and_release_current_context(dc, context, stream); + return true; +} + +static void commit_planes_and_stream_update_on_current_context(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + enum surface_update_type update_type) +{ + struct dc_fast_update fast_update[MAX_SURFACES] = {0}; + + ASSERT(update_type < UPDATE_TYPE_FULL); + populate_fast_updates(fast_update, srf_updates, surface_count, + stream_update); + if (fast_update_only(dc, fast_update, srf_updates, surface_count, + stream_update, stream) && + !dc->debug.enable_legacy_fast_update) + commit_planes_for_stream_fast(dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + dc->current_state); + else + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + dc->current_state); +} + +static void commit_planes_and_stream_update_with_new_context(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *new_context) +{ + ASSERT(update_type >= UPDATE_TYPE_FULL); + if (!dc->hwss.is_pipe_topology_transition_seamless(dc, + dc->current_state, new_context)) + /* + * It is required by the feature design that all pipe topologies + * using extra free pipes for power saving purposes such as + * dynamic ODM or SubVp shall only be enabled when it can be + * transitioned seamlessly to AND from its minimal transition + * state. A minimal transition state is defined as the same dc + * state but with all power saving features disabled. So it uses + * the minimum pipe topology. When we can't seamlessly + * transition from state A to state B, we will insert the + * minimal transition state A' or B' in between so seamless + * transition between A and B can be made possible. + */ + commit_minimal_transition_state_in_dc_update(dc, new_context, + stream, srf_updates, surface_count); + + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + new_context); +} + +static bool update_planes_and_stream_v3(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update) +{ + struct dc_state *new_context; + enum surface_update_type update_type; + + /* + * When this function returns true and new_context is not equal to + * current state, the function allocates and validates a new dc state + * and assigns it to new_context. The function expects that the caller + * is responsible to free this memory when new_context is no longer + * used. We swap current with new context and free current instead. So + * new_context's memory will live until the next full update after it is + * replaced by a newer context. Refer to the use of + * swap_and_free_current_context below. + */ + if (!update_planes_and_stream_state(dc, srf_updates, surface_count, + stream, stream_update, &update_type, + &new_context)) + return false; + + if (new_context == dc->current_state) { + commit_planes_and_stream_update_on_current_context(dc, + srf_updates, surface_count, stream, + stream_update, update_type); + } else { + commit_planes_and_stream_update_with_new_context(dc, + srf_updates, surface_count, stream, + stream_update, update_type, new_context); + swap_and_release_current_context(dc, new_context, stream); + } + + return true; +} + +bool dc_update_planes_and_stream(struct dc *dc, + struct dc_surface_update *srf_updates, int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update) +{ + dc_exit_ips_for_hw_access(dc); + /* + * update planes and stream version 3 separates FULL and FAST updates + * to their own sequences. It aims to clean up frequent checks for + * update type resulting unnecessary branching in logic flow. It also + * adds a new commit minimal transition sequence, which detects the need + * for minimal transition based on the actual comparison of current and + * new states instead of "predicting" it based on per feature software + * policy.i.e could_mpcc_tree_change_for_active_pipes. The new commit + * minimal transition sequence is made universal to any power saving + * features that would use extra free pipes such as Dynamic ODM/MPC + * Combine, MPO or SubVp. Therefore there is no longer a need to + * specially handle compatibility problems with transitions among those + * features as they are now transparent to the new sequence. + */ + if (dc->ctx->dce_version > DCN_VERSION_3_51) + return update_planes_and_stream_v3(dc, srf_updates, + surface_count, stream, stream_update); + return update_planes_and_stream_v2(dc, srf_updates, + surface_count, stream, stream_update); +} + +void dc_commit_updates_for_stream(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_stream_update *stream_update, + struct dc_state *state) +{ + dc_exit_ips_for_hw_access(dc); + /* TODO: Since change commit sequence can have a huge impact, + * we decided to only enable it for DCN3x. However, as soon as + * we get more confident about this change we'll need to enable + * the new sequence for all ASICs. + */ + if (dc->ctx->dce_version > DCN_VERSION_3_51) { + update_planes_and_stream_v3(dc, srf_updates, surface_count, + stream, stream_update); + return; + } + if (dc->ctx->dce_version >= DCN_VERSION_3_2) { + update_planes_and_stream_v2(dc, srf_updates, surface_count, + stream, stream_update); + return; + } + update_planes_and_stream_v1(dc, srf_updates, surface_count, stream, + stream_update, state); } uint8_t dc_get_current_stream_count(struct dc *dc) @@ -4737,8 +5043,13 @@ void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src) void dc_power_down_on_boot(struct dc *dc) { if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW && - dc->hwss.power_down_on_boot) + dc->hwss.power_down_on_boot) { + + if (dc->caps.ips_support) + dc_exit_ips_for_hw_access(dc); + dc->hwss.power_down_on_boot(dc); + } } void dc_set_power_state( @@ -4876,11 +5187,15 @@ bool dc_set_replay_allow_active(struct dc *dc, bool active) return true; } -void dc_allow_idle_optimizations(struct dc *dc, bool allow) +void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name) { if (dc->debug.disable_idle_power_optimizations) return; + if (allow != dc->idle_optimizations_allowed) + DC_LOG_IPS("%s: allow_idle old=%d new=%d (caller=%s)\n", __func__, + dc->idle_optimizations_allowed, allow, caller_name); + if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL)) return; @@ -4895,10 +5210,10 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) dc->idle_optimizations_allowed = allow; } -void dc_exit_ips_for_hw_access(struct dc *dc) +void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name) { if (dc->caps.ips_support) - dc_allow_idle_optimizations(dc, false); + dc_allow_idle_optimizations_internal(dc, false, caller_name); } bool dc_dmub_is_ips_idle_state(struct dc *dc) @@ -5032,10 +5347,13 @@ void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable) } dc->clk_mgr->dc_mode_softmax_enabled = enable; } -bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_state *plane, +bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, + unsigned int pitch, + unsigned int height, + enum surface_pixel_format format, struct dc_cursor_attributes *cursor_attr) { - if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, plane, cursor_attr)) + if (dc->hwss.does_plane_fit_in_mall && dc->hwss.does_plane_fit_in_mall(dc, pitch, height, format, cursor_attr)) return true; return false; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 9c05b1a07142..5c1d3017aefd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -392,10 +392,10 @@ void get_hdr_visual_confirm_color( switch (top_pipe_ctx->plane_res.scl_data.format) { case PIXEL_FORMAT_ARGB2101010: - if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + if (top_pipe_ctx->stream->out_transfer_func.tf == TRANSFER_FUNCTION_PQ) { /* HDR10, ARGB2101010 - set border color to red */ color->color_r_cr = color_value; - } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { + } else if (top_pipe_ctx->stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { /* FreeSync 2 ARGB2101010 - set border color to pink */ color->color_r_cr = color_value; color->color_b_cb = color_value; @@ -403,10 +403,10 @@ void get_hdr_visual_confirm_color( is_sdr = true; break; case PIXEL_FORMAT_FP16: - if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) { + if (top_pipe_ctx->stream->out_transfer_func.tf == TRANSFER_FUNCTION_PQ) { /* HDR10, FP16 - set border color to blue */ color->color_b_cb = color_value; - } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { + } else if (top_pipe_ctx->stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { /* FreeSync 2 HDR - set border color to green */ color->color_g_y = color_value; } else @@ -558,9 +558,10 @@ void hwss_build_fast_sequence(struct dc *dc, struct dc_dmub_cmd *dc_dmub_cmd, unsigned int dmub_cmd_count, struct block_sequence block_sequence[], - int *num_steps, + unsigned int *num_steps, struct pipe_ctx *pipe_ctx, - struct dc_stream_status *stream_status) + struct dc_stream_status *stream_status, + struct dc_state *context) { struct dc_plane_state *plane = pipe_ctx->plane_state; struct dc_stream_state *stream = pipe_ctx->stream; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index ec4bf9432bdb..15819416a2f3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -340,7 +340,7 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, return res_pool; } -void dc_destroy_resource_pool(struct dc *dc) +void dc_destroy_resource_pool(struct dc *dc) { if (dc) { if (dc->res_pool) @@ -1457,6 +1457,9 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, controller_color_space = convert_dp_to_controller_color_space( otg_master->stream->test_pattern.color_space); + if (controller_test_pattern == CONTROLLER_DP_TEST_PATTERN_VIDEOMODE) + return; + odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads); odm_slice_width = h_active / odm_cnt; @@ -1485,6 +1488,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; const struct rect odm_slice_rec = calculate_odm_slice_in_timing_active(pipe_ctx); bool res = false; + DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); /* Invalid input */ @@ -1496,9 +1500,6 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) return false; } - pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( - pipe_ctx->plane_state->format); - /* Timing borders are part of vactive that we are also supposed to skip in addition * to any stream dst offset. Since dm logic assumes dst is in addressable * space we need to add the left and top borders to dst offsets temporarily. @@ -1510,6 +1511,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) /* Calculate H and V active size */ pipe_ctx->plane_res.scl_data.h_active = odm_slice_rec.width; pipe_ctx->plane_res.scl_data.v_active = odm_slice_rec.height; + pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( + pipe_ctx->plane_state->format); /* depends on h_active */ calculate_recout(pipe_ctx); @@ -1794,6 +1797,30 @@ int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( return free_pipe_idx; } +int resource_find_free_pipe_used_as_cur_sec_dpp( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool) +{ + int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND; + const struct pipe_ctx *new_pipe, *cur_pipe; + int i; + + for (i = 0; i < pool->pipe_count; i++) { + cur_pipe = &cur_res_ctx->pipe_ctx[i]; + new_pipe = &new_res_ctx->pipe_ctx[i]; + + if (resource_is_pipe_type(cur_pipe, DPP_PIPE) && + !resource_is_pipe_type(cur_pipe, OPP_HEAD) && + resource_is_pipe_type(new_pipe, FREE_PIPE)) { + free_pipe_idx = i; + break; + } + } + + return free_pipe_idx; +} + int resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine( const struct resource_context *cur_res_ctx, struct resource_context *new_res_ctx, @@ -2168,50 +2195,91 @@ static void resource_log_pipe(struct dc *dc, struct pipe_ctx *pipe, } } -void resource_log_pipe_topology_update(struct dc *dc, struct dc_state *state) +static void resource_log_pipe_for_stream(struct dc *dc, struct dc_state *state, + struct pipe_ctx *otg_master, int stream_idx) { - struct pipe_ctx *otg_master; struct pipe_ctx *opp_heads[MAX_PIPES]; struct pipe_ctx *dpp_pipes[MAX_PIPES]; - int stream_idx, slice_idx, dpp_idx, plane_idx, slice_count, dpp_count; + int slice_idx, dpp_idx, plane_idx, slice_count, dpp_count; bool is_primary; DC_LOGGER_INIT(dc->ctx->logger); + slice_count = resource_get_opp_heads_for_otg_master(otg_master, + &state->res_ctx, opp_heads); + for (slice_idx = 0; slice_idx < slice_count; slice_idx++) { + plane_idx = -1; + if (opp_heads[slice_idx]->plane_state) { + dpp_count = resource_get_dpp_pipes_for_opp_head( + opp_heads[slice_idx], + &state->res_ctx, + dpp_pipes); + for (dpp_idx = 0; dpp_idx < dpp_count; dpp_idx++) { + is_primary = !dpp_pipes[dpp_idx]->top_pipe || + dpp_pipes[dpp_idx]->top_pipe->plane_state != dpp_pipes[dpp_idx]->plane_state; + if (is_primary) + plane_idx++; + resource_log_pipe(dc, dpp_pipes[dpp_idx], + stream_idx, slice_idx, + plane_idx, slice_count, + is_primary); + } + } else { + resource_log_pipe(dc, opp_heads[slice_idx], + stream_idx, slice_idx, plane_idx, + slice_count, true); + } + + } +} + +static int resource_stream_to_stream_idx(struct dc_state *state, + struct dc_stream_state *stream) +{ + int i, stream_idx = -1; + + for (i = 0; i < state->stream_count; i++) + if (state->streams[i] == stream) { + stream_idx = i; + break; + } + + /* never return negative array index */ + if (stream_idx == -1) { + ASSERT(0); + return 0; + } + + return stream_idx; +} + +void resource_log_pipe_topology_update(struct dc *dc, struct dc_state *state) +{ + struct pipe_ctx *otg_master; + int stream_idx, phantom_stream_idx; + DC_LOGGER_INIT(dc->ctx->logger); + DC_LOG_DC(" pipe topology update"); DC_LOG_DC(" ________________________"); for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) { + if (state->streams[stream_idx]->is_phantom) + continue; + otg_master = resource_get_otg_master_for_stream( &state->res_ctx, state->streams[stream_idx]); - if (!otg_master || otg_master->stream_res.tg == NULL) { - DC_LOG_DC("topology update: otg_master NULL stream_idx %d!\n", stream_idx); - return; - } - slice_count = resource_get_opp_heads_for_otg_master(otg_master, - &state->res_ctx, opp_heads); - for (slice_idx = 0; slice_idx < slice_count; slice_idx++) { - plane_idx = -1; - if (opp_heads[slice_idx]->plane_state) { - dpp_count = resource_get_dpp_pipes_for_opp_head( - opp_heads[slice_idx], - &state->res_ctx, - dpp_pipes); - for (dpp_idx = 0; dpp_idx < dpp_count; dpp_idx++) { - is_primary = !dpp_pipes[dpp_idx]->top_pipe || - dpp_pipes[dpp_idx]->top_pipe->plane_state != dpp_pipes[dpp_idx]->plane_state; - if (is_primary) - plane_idx++; - resource_log_pipe(dc, dpp_pipes[dpp_idx], - stream_idx, slice_idx, - plane_idx, slice_count, - is_primary); - } - } else { - resource_log_pipe(dc, opp_heads[slice_idx], - stream_idx, slice_idx, plane_idx, - slice_count, true); - } + resource_log_pipe_for_stream(dc, state, otg_master, stream_idx); + } + if (state->phantom_stream_count > 0) { + DC_LOG_DC(" | (phantom pipes) |"); + for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) { + if (state->stream_status[stream_idx].mall_stream_config.type != SUBVP_MAIN) + continue; + phantom_stream_idx = resource_stream_to_stream_idx(state, + state->stream_status[stream_idx].mall_stream_config.paired_stream); + otg_master = resource_get_otg_master_for_stream( + &state->res_ctx, state->streams[phantom_stream_idx]); + resource_log_pipe_for_stream(dc, state, otg_master, stream_idx); } } DC_LOG_DC(" |________________________|\n"); @@ -2266,6 +2334,9 @@ static bool update_pipe_params_after_odm_slice_count_change( if (pool->funcs->build_pipe_pix_clk_params) pool->funcs->build_pipe_pix_clk_params(otg_master); + + resource_build_test_pattern_params(&context->res_ctx, otg_master); + return result; } @@ -2624,13 +2695,19 @@ bool resource_append_dpp_pipes_for_plane_composition( struct pipe_ctx *otg_master_pipe, struct dc_plane_state *plane_state) { + bool success; if (otg_master_pipe->plane_state == NULL) - return add_plane_to_opp_head_pipes(otg_master_pipe, + success = add_plane_to_opp_head_pipes(otg_master_pipe, plane_state, new_ctx); else - return acquire_secondary_dpp_pipes_and_add_plane( + success = acquire_secondary_dpp_pipes_and_add_plane( otg_master_pipe, plane_state, new_ctx, cur_ctx, pool); + if (success) + /* when appending a plane mpc slice count changes from 0 to 1 */ + success = update_pipe_params_after_mpc_slice_count_change( + plane_state, new_ctx, pool); + return success; } void resource_remove_dpp_pipes_for_plane_composition( @@ -2965,7 +3042,7 @@ bool resource_update_pipes_for_plane_with_slice_count( int i; int dpp_pipe_count; int cur_slice_count; - struct pipe_ctx *dpp_pipes[MAX_PIPES]; + struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0}; bool result = true; dpp_pipe_count = resource_get_dpp_pipes_for_plane(plane, @@ -3117,6 +3194,9 @@ static struct audio *find_first_free_audio( { int i, available_audio_count; + if (id == ENGINE_ID_UNKNOWN) + return NULL; + available_audio_count = pool->audio_count; for (i = 0; i < available_audio_count; i++) { @@ -3371,11 +3451,31 @@ static bool acquire_otg_master_pipe_for_stream( * any free pipes already used in current context as this could tear * down exiting ODM/MPC/MPO configuration unnecessarily. */ + + /* + * Try to acquire the same OTG master already in use. This is not + * optimal because resetting an enabled OTG master pipe for a new stream + * requires an extra frame of wait. However there are test automation + * and eDP assumptions that rely on reusing the same OTG master pipe + * during mode change. We have to keep this logic as is for now. + */ pipe_idx = recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); + /* + * Try to acquire a pipe not used in current resource context to avoid + * pipe swapping. + */ if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); + /* + * If pipe swapping is unavoidable, try to acquire pipe used as + * secondary DPP pipe in current state as we prioritize to support more + * streams over supporting MPO planes. + */ + if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + pipe_idx = resource_find_free_pipe_used_as_cur_sec_dpp( + &cur_ctx->res_ctx, &new_ctx->res_ctx, pool); if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) pipe_idx = resource_find_any_free_pipe(&new_ctx->res_ctx, pool); if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) { @@ -3990,7 +4090,7 @@ static void set_avi_info_frame( } if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR && - stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) { + stream->out_transfer_func.tf == TRANSFER_FUNCTION_GAMMA22) { hdmi_info.bits.EC0_EC2 = 0; hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709; } @@ -4992,3 +5092,39 @@ bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_st return false; } + +void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuration_options *dml2_options) +{ + dml2_options->callbacks.dc = dc; + dml2_options->callbacks.build_scaling_params = &resource_build_scaling_params; + dml2_options->callbacks.build_test_pattern_params = &resource_build_test_pattern_params; + dml2_options->callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; + dml2_options->callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; + dml2_options->callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; + dml2_options->callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; + dml2_options->callbacks.get_mpc_slice_count = &resource_get_mpc_slice_count; + dml2_options->callbacks.get_odm_slice_index = &resource_get_odm_slice_index; + dml2_options->callbacks.get_odm_slice_count = &resource_get_odm_slice_count; + dml2_options->callbacks.get_opp_head = &resource_get_opp_head; + dml2_options->callbacks.get_otg_master_for_stream = &resource_get_otg_master_for_stream; + dml2_options->callbacks.get_opp_heads_for_otg_master = &resource_get_opp_heads_for_otg_master; + dml2_options->callbacks.get_dpp_pipes_for_plane = &resource_get_dpp_pipes_for_plane; + dml2_options->callbacks.get_stream_status = &dc_state_get_stream_status; + dml2_options->callbacks.get_stream_from_id = &dc_state_get_stream_from_id; + + dml2_options->svp_pstate.callbacks.dc = dc; + dml2_options->svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane; + dml2_options->svp_pstate.callbacks.add_phantom_stream = &dc_state_add_phantom_stream; + dml2_options->svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; + dml2_options->svp_pstate.callbacks.create_phantom_plane = &dc_state_create_phantom_plane; + dml2_options->svp_pstate.callbacks.remove_phantom_plane = &dc_state_remove_phantom_plane; + dml2_options->svp_pstate.callbacks.remove_phantom_stream = &dc_state_remove_phantom_stream; + dml2_options->svp_pstate.callbacks.create_phantom_stream = &dc_state_create_phantom_stream; + dml2_options->svp_pstate.callbacks.release_phantom_plane = &dc_state_release_phantom_plane; + dml2_options->svp_pstate.callbacks.release_phantom_stream = &dc_state_release_phantom_stream; + dml2_options->svp_pstate.callbacks.get_pipe_subvp_type = &dc_state_get_pipe_subvp_type; + dml2_options->svp_pstate.callbacks.get_stream_subvp_type = &dc_state_get_stream_subvp_type; + dml2_options->svp_pstate.callbacks.get_paired_subvp_stream = &dc_state_get_paired_subvp_stream; + dml2_options->svp_pstate.callbacks.remove_phantom_streams_and_planes = &dc_state_remove_phantom_streams_and_planes; + dml2_options->svp_pstate.callbacks.release_phantom_streams_and_planes = &dc_state_release_phantom_streams_and_planes; +} diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stat.c b/drivers/gpu/drm/amd/display/dc/core/dc_stat.c index 5f6392ae31a6..cd6570a1e20e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stat.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stat.c @@ -61,7 +61,7 @@ void dc_stat_get_dmub_notification(const struct dc *dc, struct dmub_notification /* For HPD/HPD RX, convert dpia port index into link index */ if (notify->type == DMUB_NOTIFICATION_HPD || notify->type == DMUB_NOTIFICATION_HPD_IRQ || - notify->type == DMUB_NOTIFICATION_DPIA_NOTIFICATION || + notify->type == DMUB_NOTIFICATION_DPIA_NOTIFICATION || notify->type == DMUB_NOTIFICATION_SET_CONFIG_REPLY) { notify->link_index = get_link_index_from_dpia_port_index(dc, notify->link_index); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 5cc7f8da209c..76bb05f4d6bf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -188,8 +188,11 @@ static void init_state(struct dc *dc, struct dc_state *state) } /* Public dc_state functions */ -struct dc_state *dc_state_create(struct dc *dc) +struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *params) { +#ifdef CONFIG_DRM_AMD_DC_FP + struct dml2_configuration_options *dml2_opt = &dc->dml2_options; +#endif struct dc_state *state = kvzalloc(sizeof(struct dc_state), GFP_KERNEL); @@ -198,10 +201,16 @@ struct dc_state *dc_state_create(struct dc *dc) init_state(dc, state); dc_state_construct(dc, state); + state->power_source = params ? params->power_source : DC_POWER_SOURCE_AC; #ifdef CONFIG_DRM_AMD_DC_FP - if (dc->debug.using_dml2) - dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2); + if (dc->debug.using_dml2) { + dml2_opt->use_clock_dc_limits = false; + dml2_create(dc, dml2_opt, &state->bw_ctx.dml2); + + dml2_opt->use_clock_dc_limits = true; + dml2_create(dc, dml2_opt, &state->bw_ctx.dml2_dc_power_source); + } #endif kref_init(&state->refcount); @@ -214,6 +223,7 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state) struct kref refcount = dst_state->refcount; #ifdef CONFIG_DRM_AMD_DC_FP struct dml2_context *dst_dml2 = dst_state->bw_ctx.dml2; + struct dml2_context *dst_dml2_dc_power_source = dst_state->bw_ctx.dml2_dc_power_source; #endif dc_state_copy_internal(dst_state, src_state); @@ -222,6 +232,10 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state) dst_state->bw_ctx.dml2 = dst_dml2; if (src_state->bw_ctx.dml2) dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2); + + dst_state->bw_ctx.dml2_dc_power_source = dst_dml2_dc_power_source; + if (src_state->bw_ctx.dml2_dc_power_source) + dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source); #endif /* context refcount should not be overridden */ @@ -245,6 +259,12 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state) dc_state_release(new_state); return NULL; } + + if (src_state->bw_ctx.dml2_dc_power_source && + !dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source)) { + dc_state_release(new_state); + return NULL; + } #endif kref_init(&new_state->refcount); @@ -310,7 +330,6 @@ void dc_state_destruct(struct dc_state *state) memset(state->dc_dmub_cmd, 0, sizeof(state->dc_dmub_cmd)); state->dmub_cmd_count = 0; memset(&state->perf_params, 0, sizeof(state->perf_params)); - memset(&state->scratch, 0, sizeof(state->scratch)); } void dc_state_retain(struct dc_state *state) @@ -327,6 +346,9 @@ static void dc_state_free(struct kref *kref) #ifdef CONFIG_DRM_AMD_DC_FP dml2_destroy(state->bw_ctx.dml2); state->bw_ctx.dml2 = 0; + + dml2_destroy(state->bw_ctx.dml2_dc_power_source); + state->bw_ctx.dml2_dc_power_source = 0; #endif kvfree(state); @@ -341,7 +363,7 @@ void dc_state_release(struct dc_state *state) * dc_state_add_stream() - Add a new dc_stream_state to a dc_state. */ enum dc_status dc_state_add_stream( - struct dc *dc, + const struct dc *dc, struct dc_state *state, struct dc_stream_state *stream) { @@ -370,7 +392,7 @@ enum dc_status dc_state_add_stream( * dc_state_remove_stream() - Remove a stream from a dc_state. */ enum dc_status dc_state_remove_stream( - struct dc *dc, + const struct dc *dc, struct dc_state *state, struct dc_stream_state *stream) { @@ -436,6 +458,15 @@ bool dc_state_add_plane( goto out; } + if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm) + /* ODM combine could prevent us from supporting more planes + * we will reset ODM slice count back to 1 when all planes have + * been removed to maximize the amount of planes supported when + * new planes are added. + */ + resource_update_pipes_for_stream_with_slice_count( + state, dc->current_state, dc->res_pool, stream, 1); + otg_master_pipe = resource_get_otg_master_for_stream( &state->res_ctx, stream); if (otg_master_pipe) @@ -586,7 +617,7 @@ bool dc_state_add_all_planes_for_stream( */ struct dc_stream_status *dc_state_get_stream_status( struct dc_state *state, - struct dc_stream_state *stream) + const struct dc_stream_state *stream) { uint8_t i; @@ -680,7 +711,7 @@ void dc_state_release_phantom_stream(const struct dc *dc, dc_stream_release(phantom_stream); } -struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc, +struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc, struct dc_state *state, struct dc_plane_state *main_plane) { @@ -716,7 +747,7 @@ void dc_state_release_phantom_plane(const struct dc *dc, } /* add phantom streams to context and generate correct meta inside dc_state */ -enum dc_status dc_state_add_phantom_stream(struct dc *dc, +enum dc_status dc_state_add_phantom_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *phantom_stream, struct dc_stream_state *main_stream) @@ -742,7 +773,7 @@ enum dc_status dc_state_add_phantom_stream(struct dc *dc, return res; } -enum dc_status dc_state_remove_phantom_stream(struct dc *dc, +enum dc_status dc_state_remove_phantom_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *phantom_stream) { @@ -836,7 +867,7 @@ bool dc_state_add_all_phantom_planes_for_stream( } bool dc_state_remove_phantom_streams_and_planes( - struct dc *dc, + const struct dc *dc, struct dc_state *state) { int i; @@ -858,7 +889,7 @@ bool dc_state_remove_phantom_streams_and_planes( } void dc_state_release_phantom_streams_and_planes( - struct dc *dc, + const struct dc *dc, struct dc_state *state) { int i; @@ -869,3 +900,19 @@ void dc_state_release_phantom_streams_and_planes( for (i = 0; i < state->phantom_plane_count; i++) dc_state_release_phantom_plane(dc, state, state->phantom_planes[i]); } + +struct dc_stream_state *dc_state_get_stream_from_id(const struct dc_state *state, unsigned int id) +{ + struct dc_stream_state *stream = NULL; + int i; + + for (i = 0; i < state->stream_count; i++) { + if (state->streams[i] && state->streams[i]->stream_id == id) { + stream = state->streams[i]; + break; + } + } + + return stream; +} + diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 51a970fcb5d0..5c7e4884cac2 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -116,12 +116,7 @@ bool dc_stream_construct(struct dc_stream_state *stream, update_stream_signal(stream, dc_sink_data); - stream->out_transfer_func = dc_create_transfer_func(); - if (stream->out_transfer_func == NULL) { - dc_sink_release(dc_sink_data); - return false; - } - stream->out_transfer_func->type = TF_TYPE_BYPASS; + stream->out_transfer_func.type = TF_TYPE_BYPASS; dc_stream_assign_stream_id(stream); @@ -131,10 +126,6 @@ bool dc_stream_construct(struct dc_stream_state *stream, void dc_stream_destruct(struct dc_stream_state *stream) { dc_sink_release(stream->sink); - if (stream->out_transfer_func != NULL) { - dc_transfer_func_release(stream->out_transfer_func); - stream->out_transfer_func = NULL; - } } void dc_stream_assign_stream_id(struct dc_stream_state *stream) @@ -201,9 +192,6 @@ struct dc_stream_state *dc_copy_stream(const struct dc_stream_state *stream) if (new_stream->sink) dc_sink_retain(new_stream->sink); - if (new_stream->out_transfer_func) - dc_transfer_func_retain(new_stream->out_transfer_func); - dc_stream_assign_stream_id(new_stream); /* If using dynamic encoder assignment, wait till stream committed to assign encoder. */ @@ -319,7 +307,7 @@ bool dc_stream_set_cursor_attributes( program_cursor_attributes(dc, stream, attributes); /* re-enable idle optimizations if necessary */ - if (reset_idle_optimizations) + if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); return true; @@ -394,7 +382,7 @@ bool dc_stream_set_cursor_position( program_cursor_position(dc, stream, position); /* re-enable idle optimizations if necessary */ - if (reset_idle_optimizations) + if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); return true; @@ -425,7 +413,7 @@ bool dc_stream_add_writeback(struct dc *dc, dc_exit_ips_for_hw_access(dc); - wb_info->dwb_params.out_transfer_func = stream->out_transfer_func; + wb_info->dwb_params.out_transfer_func = &stream->out_transfer_func; dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; dwb->dwb_is_drc = false; @@ -507,7 +495,7 @@ bool dc_stream_remove_writeback(struct dc *dc, struct dc_stream_state *stream, uint32_t dwb_pipe_inst) { - int i = 0, j = 0; + unsigned int i, j; if (stream == NULL) { dm_error("DC: dc_stream is NULL!\n"); return false; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 19140fb65787..067f6555cfdf 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c @@ -41,25 +41,15 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta { plane_state->ctx = ctx; - plane_state->gamma_correction = dc_create_gamma(); - if (plane_state->gamma_correction != NULL) - plane_state->gamma_correction->is_identity = true; + plane_state->gamma_correction.is_identity = true; - plane_state->in_transfer_func = dc_create_transfer_func(); - if (plane_state->in_transfer_func != NULL) { - plane_state->in_transfer_func->type = TF_TYPE_BYPASS; - } - plane_state->in_shaper_func = dc_create_transfer_func(); - if (plane_state->in_shaper_func != NULL) { - plane_state->in_shaper_func->type = TF_TYPE_BYPASS; - } + plane_state->in_transfer_func.type = TF_TYPE_BYPASS; - plane_state->lut3d_func = dc_create_3dlut_func(); + plane_state->in_shaper_func.type = TF_TYPE_BYPASS; - plane_state->blend_tf = dc_create_transfer_func(); - if (plane_state->blend_tf != NULL) { - plane_state->blend_tf->type = TF_TYPE_BYPASS; - } + plane_state->lut3d_func.state.raw = 0; + + plane_state->blend_tf.type = TF_TYPE_BYPASS; plane_state->pre_multiplied_alpha = true; @@ -67,30 +57,27 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta void dc_plane_destruct(struct dc_plane_state *plane_state) { - if (plane_state->gamma_correction != NULL) { - dc_gamma_release(&plane_state->gamma_correction); - } - if (plane_state->in_transfer_func != NULL) { - dc_transfer_func_release( - plane_state->in_transfer_func); - plane_state->in_transfer_func = NULL; - } - if (plane_state->in_shaper_func != NULL) { - dc_transfer_func_release( - plane_state->in_shaper_func); - plane_state->in_shaper_func = NULL; - } - if (plane_state->lut3d_func != NULL) { - dc_3dlut_func_release( - plane_state->lut3d_func); - plane_state->lut3d_func = NULL; - } - if (plane_state->blend_tf != NULL) { - dc_transfer_func_release( - plane_state->blend_tf); - plane_state->blend_tf = NULL; + // no more pointers to free within dc_plane_state +} + + +/* dc_state is passed in separately since it may differ from the current dc state accessible from plane_state e.g. + * if the driver is doing an update from an old context to a new one and the caller wants the pipe mask for the new + * context rather than the existing one + */ +uint8_t dc_plane_get_pipe_mask(struct dc_state *dc_state, const struct dc_plane_state *plane_state) +{ + uint8_t pipe_mask = 0; + int i; + + for (i = 0; i < plane_state->ctx->dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &dc_state->res_ctx.pipe_ctx[i]; + + if (pipe_ctx->plane_state == plane_state && pipe_ctx->plane_res.hubp) + pipe_mask |= 1 << pipe_ctx->plane_res.hubp->inst; } + return pipe_mask; } /******************************************************************************* @@ -103,7 +90,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, /*register_flip_interrupt(surface);*/ } -struct dc_plane_state *dc_create_plane_state(struct dc *dc) +struct dc_plane_state *dc_create_plane_state(const struct dc *dc) { struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state), GFP_KERNEL); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ee8453bf958f..3c33c3bcbe2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -44,6 +44,8 @@ #include "dml2/dml2_wrapper.h" +#include "dmub/inc/dmub_cmd.h" + struct abm_save_restore; /* forward declaration */ @@ -51,7 +53,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.273" +#define DC_VER "3.2.281" #define MAX_SURFACES 3 #define MAX_PLANES 6 @@ -219,6 +221,7 @@ struct dc_dmub_caps { bool mclk_sw; bool subvp_psr; bool gecc_enable; + uint8_t fams_ver; }; struct dc_caps { @@ -306,12 +309,12 @@ struct dc_dcc_setting { unsigned int max_compressed_blk_size; unsigned int max_uncompressed_blk_size; bool independent_64b_blks; - //These bitfields to be used starting with DCN + //These bitfields to be used starting with DCN 3.0 struct { - uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN (the worst compression case) - uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN - uint32_t dcc_256_128_128 : 1; //available starting with DCN - uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN (the best compression case) + uint32_t dcc_256_64_64 : 1;//available in ASICs before DCN 3.0 (the worst compression case) + uint32_t dcc_128_128_uncontrained : 1; //available in ASICs before DCN 3.0 + uint32_t dcc_256_128_128 : 1; //available starting with DCN 3.0 + uint32_t dcc_256_256_unconstrained : 1; //available in ASICs before DCN 3.0 (the best compression case) } dcc_controls; }; @@ -435,6 +438,9 @@ struct dc_config { unsigned int disable_ips; unsigned int disable_ips_in_vpb; bool usb4_bw_alloc_support; + bool allow_0_dtb_clk; + bool use_assr_psp_message; + bool support_edp0_on_dp1; }; enum visual_confirm { @@ -693,6 +699,8 @@ enum pg_hw_pipe_resources { PG_MPCC, PG_OPP, PG_OPTC, + PG_DPSTREAM, + PG_HDMISTREAM, PG_HW_PIPE_RESOURCES_NUM_ELEMENT }; @@ -987,14 +995,17 @@ struct dc_debug_options { bool psp_disabled_wa; unsigned int ips2_eval_delay_us; unsigned int ips2_entry_delay_us; + bool optimize_ips_handshake; bool disable_dmub_reallow_idle; bool disable_timeout; bool disable_extblankadj; + bool enable_idle_reg_checks; unsigned int static_screen_wait_frames; bool force_chroma_subsampling_1tap; + bool disable_422_left_edge_pixel; + unsigned int force_cositing; }; -struct gpu_info_soc_bounding_box_v1_0; /* Generic structure that can be used to query properties of DC. More fields * can be added as required. @@ -1003,76 +1014,6 @@ struct dc_current_properties { unsigned int cursor_size_limit; }; -struct dc { - struct dc_debug_options debug; - struct dc_versions versions; - struct dc_caps caps; - struct dc_cap_funcs cap_funcs; - struct dc_config config; - struct dc_bounding_box_overrides bb_overrides; - struct dc_bug_wa work_arounds; - struct dc_context *ctx; - struct dc_phy_addr_space_config vm_pa_config; - - uint8_t link_count; - struct dc_link *links[MAX_PIPES * 2]; - struct link_service *link_srv; - - struct dc_state *current_state; - struct resource_pool *res_pool; - - struct clk_mgr *clk_mgr; - - /* Display Engine Clock levels */ - struct dm_pp_clock_levels sclk_lvls; - - /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip *bw_dceip; - struct bw_calcs_vbios *bw_vbios; - struct dcn_soc_bounding_box *dcn_soc; - struct dcn_ip_params *dcn_ip; - struct display_mode_lib dml; - - /* HW functions */ - struct hw_sequencer_funcs hwss; - struct dce_hwseq *hwseq; - - /* Require to optimize clocks and bandwidth for added/removed planes */ - bool optimized_required; - bool wm_optimized_required; - bool idle_optimizations_allowed; - bool enable_c20_dtm_b0; - - /* Require to maintain clocks and bandwidth for UEFI enabled HW */ - - /* FBC compressor */ - struct compressor *fbc_compressor; - - struct dc_debug_data debug_data; - struct dpcd_vendor_signature vendor_signature; - - const char *build_id; - struct vm_helper *vm_helper; - - uint32_t *dcn_reg_offsets; - uint32_t *nbio_reg_offsets; - uint32_t *clk_reg_offsets; - - /* Scratch memory */ - struct { - struct { - /* - * For matching clock_limits table in driver with table - * from PMFW. - */ - struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - } update_bw_bounding_box; - } scratch; - - struct dml2_configuration_options dml2_options; - enum dc_acpi_cm_power_state power_state; -}; - enum frame_buffer_mode { FRAME_BUFFER_MODE_LOCAL_ONLY = 0, FRAME_BUFFER_MODE_ZFB_ONLY, @@ -1277,6 +1218,8 @@ union surface_update_flags { uint32_t raw; }; +#define DC_REMOVE_PLANE_POINTERS 1 + struct dc_plane_state { struct dc_plane_address address; struct dc_plane_flip_time time; @@ -1291,8 +1234,8 @@ struct dc_plane_state { struct dc_plane_dcc_param dcc; - struct dc_gamma *gamma_correction; - struct dc_transfer_func *in_transfer_func; + struct dc_gamma gamma_correction; + struct dc_transfer_func in_transfer_func; struct dc_bias_and_scale *bias_and_scale; struct dc_csc_transform input_csc_color_matrix; struct fixed31_32 coeff_reduction_factor; @@ -1304,9 +1247,9 @@ struct dc_plane_state { enum dc_color_space color_space; - struct dc_3dlut *lut3d_func; - struct dc_transfer_func *in_shaper_func; - struct dc_transfer_func *blend_tf; + struct dc_3dlut lut3d_func; + struct dc_transfer_func in_shaper_func; + struct dc_transfer_func blend_tf; struct dc_transfer_func *gamcor_tf; enum surface_pixel_format format; @@ -1342,6 +1285,7 @@ struct dc_plane_state { struct tg_color visual_confirm_color; bool is_statically_allocated; + enum chroma_cositing cositing; }; struct dc_plane_info { @@ -1360,6 +1304,96 @@ struct dc_plane_info { int global_alpha_value; bool input_csc_enabled; int layer_index; + enum chroma_cositing cositing; +}; + +#include "dc_stream.h" + +struct dc_scratch_space { + /* used to temporarily backup plane states of a stream during + * dc update. The reason is that plane states are overwritten + * with surface updates in dc update. Once they are overwritten + * current state is no longer valid. We want to temporarily + * store current value in plane states so we can still recover + * a valid current state during dc update. + */ + struct dc_plane_state plane_states[MAX_SURFACE_NUM]; + + struct dc_stream_state stream_state; +}; + +struct dc { + struct dc_debug_options debug; + struct dc_versions versions; + struct dc_caps caps; + struct dc_cap_funcs cap_funcs; + struct dc_config config; + struct dc_bounding_box_overrides bb_overrides; + struct dc_bug_wa work_arounds; + struct dc_context *ctx; + struct dc_phy_addr_space_config vm_pa_config; + + uint8_t link_count; + struct dc_link *links[MAX_LINKS]; + struct link_service *link_srv; + + struct dc_state *current_state; + struct resource_pool *res_pool; + + struct clk_mgr *clk_mgr; + + /* Display Engine Clock levels */ + struct dm_pp_clock_levels sclk_lvls; + + /* Inputs into BW and WM calculations. */ + struct bw_calcs_dceip *bw_dceip; + struct bw_calcs_vbios *bw_vbios; + struct dcn_soc_bounding_box *dcn_soc; + struct dcn_ip_params *dcn_ip; + struct display_mode_lib dml; + + /* HW functions */ + struct hw_sequencer_funcs hwss; + struct dce_hwseq *hwseq; + + /* Require to optimize clocks and bandwidth for added/removed planes */ + bool optimized_required; + bool wm_optimized_required; + bool idle_optimizations_allowed; + bool enable_c20_dtm_b0; + + /* Require to maintain clocks and bandwidth for UEFI enabled HW */ + + /* FBC compressor */ + struct compressor *fbc_compressor; + + struct dc_debug_data debug_data; + struct dpcd_vendor_signature vendor_signature; + + const char *build_id; + struct vm_helper *vm_helper; + + uint32_t *dcn_reg_offsets; + uint32_t *nbio_reg_offsets; + uint32_t *clk_reg_offsets; + + /* Scratch memory */ + struct { + struct { + /* + * For matching clock_limits table in driver with table + * from PMFW. + */ + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + } update_bw_bounding_box; + struct dc_scratch_space current_state; + struct dc_scratch_space new_state; + struct dc_stream_state temp_stream; // Used so we don't need to allocate stream on the stack + } scratch; + + struct dml2_configuration_options dml2_options; + enum dc_acpi_cm_power_state power_state; + }; struct dc_scaling_info { @@ -1476,10 +1510,15 @@ bool dc_acquire_release_mpc_3dlut( bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); void get_audio_check(struct audio_info *aud_modes, struct audio_check *aud_chk); - -enum dc_status dc_commit_streams(struct dc *dc, - struct dc_stream_state *streams[], - uint8_t stream_count); +/* + * Set up streams and links associated to drive sinks + * The streams parameter is an absolute set of all active streams. + * + * After this call: + * Phy, Encoder, Timing Generator are programmed and enabled. + * New streams are enabled with blank stream; no memory read. + */ +enum dc_status dc_commit_streams(struct dc *dc, struct dc_commit_streams_params *params); struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, @@ -2335,11 +2374,17 @@ bool dc_is_dmcu_initialized(struct dc *dc); enum dc_status dc_set_clock(struct dc *dc, enum dc_clock_type clock_type, uint32_t clk_khz, uint32_t stepping); void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_config *clock_cfg); -bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_state *plane, - struct dc_cursor_attributes *cursor_attr); +bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, + unsigned int pitch, + unsigned int height, + enum surface_pixel_format format, + struct dc_cursor_attributes *cursor_attr); -void dc_allow_idle_optimizations(struct dc *dc, bool allow); -void dc_exit_ips_for_hw_access(struct dc *dc); +#define dc_allow_idle_optimizations(dc, allow) dc_allow_idle_optimizations_internal(dc, allow, __func__) +#define dc_exit_ips_for_hw_access(dc) dc_exit_ips_for_hw_access_internal(dc, __func__) + +void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, const char *caller_name); +void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name); bool dc_dmub_is_ips_idle_state(struct dc *dc); /* set min and max memory clock to lowest and highest DPM level, respectively */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 6083b1dcf050..2293a92df3be 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -23,6 +23,7 @@ * */ +#include "dm_services.h" #include "dc.h" #include "dc_dmub_srv.h" #include "../dmub/dmub_srv.h" @@ -34,6 +35,7 @@ #include "resource.h" #include "clk_mgr.h" #include "dc_state_priv.h" +#include "dc_plane_priv.h" #define CTX dc_dmub_srv->ctx #define DC_LOGGER CTX->logger @@ -198,6 +200,11 @@ bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv, if (status != DMUB_STATUS_OK) { DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status); + if (!dmub->debug.timeout_occured) { + dmub->debug.timeout_occured = true; + dmub->debug.timeout_cmd = *cmd_list; + dmub->debug.timestamp = dm_get_timestamp(dc_dmub_srv->ctx); + } dc_dmub_srv_log_diagnostic_data(dc_dmub_srv); return false; } @@ -904,12 +911,15 @@ bool dc_dmub_srv_get_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv, struct dmu void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) { struct dmub_diagnostic_data diag_data = {0}; + uint32_t i; if (!dc_dmub_srv || !dc_dmub_srv->dmub) { DC_LOG_ERROR("%s: invalid parameters.", __func__); return; } + DC_LOG_ERROR("%s: DMCUB error - collecting diagnostic data\n", __func__); + if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, &diag_data)) { DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__); return; @@ -933,7 +943,8 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) DC_LOG_DEBUG(" scratch [13] : %08x", diag_data.scratch[13]); DC_LOG_DEBUG(" scratch [14] : %08x", diag_data.scratch[14]); DC_LOG_DEBUG(" scratch [15] : %08x", diag_data.scratch[15]); - DC_LOG_DEBUG(" pc : %08x", diag_data.pc); + for (i = 0; i < DMUB_PC_SNAPSHOT_COUNT; i++) + DC_LOG_DEBUG(" pc[%d] : %08x", i, diag_data.pc[i]); DC_LOG_DEBUG(" unk_fault_addr : %08x", diag_data.undefined_address_fault_addr); DC_LOG_DEBUG(" inst_fault_addr : %08x", diag_data.inst_fetch_fault_addr); DC_LOG_DEBUG(" data_fault_addr : %08x", diag_data.data_write_fault_addr); @@ -1199,8 +1210,23 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) return true; } +static int count_active_streams(const struct dc *dc) +{ + int i, count = 0; + + for (i = 0; i < dc->current_state->stream_count; ++i) { + struct dc_stream_state *stream = dc->current_state->streams[i]; + + if (stream && !stream->dpms_off) + count += 1; + } + + return count; +} + static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) { + volatile const struct dmub_shared_state_ips_fw *ips_fw; struct dc_dmub_srv *dc_dmub_srv; union dmub_rb_cmd cmd = {0}; @@ -1211,6 +1237,7 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) return; dc_dmub_srv = dc->ctx->dmub_srv; + ips_fw = &dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_FW].data.ips_fw; memset(&cmd, 0, sizeof(cmd)); cmd.idle_opt_notify_idle.header.type = DMUB_CMD__IDLE_OPT; @@ -1226,6 +1253,12 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) &dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER].data.ips_driver; union dmub_shared_state_ips_driver_signals new_signals; + DC_LOG_IPS( + "%s wait idle (ips1_commit=%d ips2_commit=%d)", + __func__, + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); memset(&new_signals, 0, sizeof(new_signals)); @@ -1245,19 +1278,46 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) new_signals.bits.allow_pg = 1; new_signals.bits.allow_ips1 = 1; new_signals.bits.allow_ips2 = 1; + } else if (dc->config.disable_ips == DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF) { + /* TODO: Move this logic out to hwseq */ + if (count_active_streams(dc) == 0) { + /* IPS2 - Display off */ + new_signals.bits.allow_pg = 1; + new_signals.bits.allow_ips1 = 1; + new_signals.bits.allow_ips2 = 1; + new_signals.bits.allow_z10 = 1; + } else { + /* RCG only */ + new_signals.bits.allow_pg = 0; + new_signals.bits.allow_ips1 = 1; + new_signals.bits.allow_ips2 = 0; + new_signals.bits.allow_z10 = 0; + } } ips_driver->signals = new_signals; } + DC_LOG_IPS( + "%s send allow_idle=%d (ips1_commit=%d ips2_commit=%d)", + __func__, + allow_idle, + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + /* NOTE: This does not use the "wake" interface since this is part of the wake path. */ /* We also do not perform a wait since DMCUB could enter idle after the notification. */ dm_execute_dmub_cmd(dc->ctx, &cmd, allow_idle ? DM_DMUB_WAIT_TYPE_NO_WAIT : DM_DMUB_WAIT_TYPE_WAIT); + + /* Register access should stop at this point. */ + if (allow_idle) + dc_dmub_srv->needs_idle_wake = true; } static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) { struct dc_dmub_srv *dc_dmub_srv; + uint32_t rcg_exit_count = 0, ips1_exit_count = 0, ips2_exit_count = 0; if (dc->debug.dmcub_emulation) return; @@ -1274,40 +1334,113 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) &dc_dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER].data.ips_driver; union dmub_shared_state_ips_driver_signals prev_driver_signals = ips_driver->signals; + rcg_exit_count = ips_fw->rcg_exit_count; + ips1_exit_count = ips_fw->ips1_exit_count; + ips2_exit_count = ips_fw->ips2_exit_count; + ips_driver->signals.all = 0; - if (prev_driver_signals.bits.allow_ips2) { - udelay(dc->debug.ips2_eval_delay_us); + DC_LOG_IPS( + "%s (allow ips1=%d ips2=%d) (commit ips1=%d ips2=%d) (count rcg=%d ips1=%d ips2=%d)", + __func__, + ips_driver->signals.bits.allow_ips1, + ips_driver->signals.bits.allow_ips2, + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit, + ips_fw->rcg_entry_count, + ips_fw->ips1_entry_count, + ips_fw->ips2_entry_count); + + /* Note: register access has technically not resumed for DCN here, but we + * need to be message PMFW through our standard register interface. + */ + dc_dmub_srv->needs_idle_wake = false; + + if (prev_driver_signals.bits.allow_ips2 && + (!dc->debug.optimize_ips_handshake || + ips_fw->signals.bits.ips2_commit || !ips_fw->signals.bits.in_idle)) { + DC_LOG_IPS( + "wait IPS2 eval (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + + if (!dc->debug.optimize_ips_handshake || !ips_fw->signals.bits.ips2_commit) + udelay(dc->debug.ips2_eval_delay_us); if (ips_fw->signals.bits.ips2_commit) { + DC_LOG_IPS( + "exit IPS2 #1 (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + // Tell PMFW to exit low power state dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); + DC_LOG_IPS( + "wait IPS2 entry delay (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + // Wait for IPS2 entry upper bound udelay(dc->debug.ips2_entry_delay_us); + DC_LOG_IPS( + "exit IPS2 #2 (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); + DC_LOG_IPS( + "wait IPS2 commit clear (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + while (ips_fw->signals.bits.ips2_commit) udelay(1); + DC_LOG_IPS( + "wait hw_pwr_up (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true)) ASSERT(0); + DC_LOG_IPS( + "resync inbox1 (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + dmub_srv_sync_inbox1(dc->ctx->dmub_srv->dmub); } } dc_dmub_srv_notify_idle(dc, false); if (prev_driver_signals.bits.allow_ips1) { + DC_LOG_IPS( + "wait for IPS1 commit clear (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); + while (ips_fw->signals.bits.ips1_commit) udelay(1); + DC_LOG_IPS( + "wait for IPS1 commit clear done (ips1_commit=%d ips2_commit=%d)", + ips_fw->signals.bits.ips1_commit, + ips_fw->signals.bits.ips2_commit); } } if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true)) ASSERT(0); + + DC_LOG_IPS("%s exit (count rcg=%d ips1=%d ips2=%d)", + __func__, + rcg_exit_count, + ips1_exit_count, + ips2_exit_count); } void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState) @@ -1335,21 +1468,42 @@ void dc_dmub_srv_apply_idle_power_optimizations(const struct dc *dc, bool allow_ if (dc_dmub_srv->idle_allowed == allow_idle) return; + DC_LOG_IPS("%s state change: old=%d new=%d", __func__, dc_dmub_srv->idle_allowed, allow_idle); + /* * Entering a low power state requires a driver notification. * Powering up the hardware requires notifying PMFW and DMCUB. * Clearing the driver idle allow requires a DMCUB command. * DMCUB commands requires the DMCUB to be powered up and restored. - * - * Exit out early to prevent an infinite loop of DMCUB commands - * triggering exit low power - use software state to track this. */ - dc_dmub_srv->idle_allowed = allow_idle; - if (!allow_idle) + if (!allow_idle) { + dc_dmub_srv->idle_exit_counter += 1; + dc_dmub_srv_exit_low_power_state(dc); - else + /* + * Idle is considered fully exited only after the sequence above + * fully completes. If we have a race of two threads exiting + * at the same time then it's safe to perform the sequence + * twice as long as we're not re-entering. + * + * Infinite command submission is avoided by using the + * dm_execute_dmub_cmd submission instead of the "wake" helpers. + */ + dc_dmub_srv->idle_allowed = false; + + dc_dmub_srv->idle_exit_counter -= 1; + if (dc_dmub_srv->idle_exit_counter < 0) { + ASSERT(0); + dc_dmub_srv->idle_exit_counter = 0; + } + } else { + /* Consider idle as notified prior to the actual submission to + * prevent multiple entries. */ + dc_dmub_srv->idle_allowed = true; + dc_dmub_srv_notify_idle(dc, allow_idle); + } } bool dc_wake_and_execute_dmub_cmd(const struct dc_context *ctx, union dmub_rb_cmd *cmd, @@ -1384,7 +1538,8 @@ bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned in else result = dm_execute_dmub_cmd(ctx, cmd, wait_type); - if (result && reallow_idle && !ctx->dc->debug.disable_dmub_reallow_idle) + if (result && reallow_idle && dc_dmub_srv->idle_exit_counter == 0 && + !ctx->dc->debug.disable_dmub_reallow_idle) dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); return result; @@ -1433,8 +1588,10 @@ bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_com result = dc_dmub_execute_gpint(ctx, command_code, param, response, wait_type); - if (result && reallow_idle && !ctx->dc->debug.disable_dmub_reallow_idle) + if (result && reallow_idle && dc_dmub_srv->idle_exit_counter == 0 && + !ctx->dc->debug.disable_dmub_reallow_idle) dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true); return result; } + diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 952bfb368886..2c5866211f60 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -35,6 +35,7 @@ struct pipe_ctx; struct dc_crtc_timing_adjust; struct dc_crtc_timing; struct dc_state; +struct dc_surface_update; struct dc_reg_helper_state { bool gather_in_progress; @@ -51,7 +52,9 @@ struct dc_dmub_srv { struct dc_context *ctx; void *dm; + int32_t idle_exit_counter; bool idle_allowed; + bool needs_idle_wake; }; void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv); diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 1cb7765f593a..519c3df78ee5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -137,8 +137,13 @@ enum dp_link_encoding { enum dp_test_link_rate { DP_TEST_LINK_RATE_RBR = 0x06, + DP_TEST_LINK_RATE_RATE_2 = 0x08, // Rate_2 - 2.16 Gbps/Lane + DP_TEST_LINK_RATE_RATE_3 = 0x09, // Rate_3 - 2.43 Gbps/Lane DP_TEST_LINK_RATE_HBR = 0x0A, + DP_TEST_LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2) - 3.24 Gbps/Lane + DP_TEST_LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane DP_TEST_LINK_RATE_HBR2 = 0x14, + DP_TEST_LINK_RATE_RATE_8 = 0x19, // Rate_8 - 6.75 Gbps/Lane DP_TEST_LINK_RATE_HBR3 = 0x1E, DP_TEST_LINK_RATE_UHBR10 = 0x01, DP_TEST_LINK_RATE_UHBR20 = 0x02, @@ -917,16 +922,6 @@ struct dpcd_usb4_dp_tunneling_info { uint8_t usb4_topology_id[DPCD_USB4_TOPOLOGY_ID_LEN]; }; -#ifndef DP_DFP_CAPABILITY_EXTENSION_SUPPORT -#define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0A3 -#endif -#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_7_0 -#define DP_TEST_264BIT_CUSTOM_PATTERN_7_0 0X2230 -#endif -#ifndef DP_TEST_264BIT_CUSTOM_PATTERN_263_256 -#define DP_TEST_264BIT_CUSTOM_PATTERN_263_256 0X2250 -#endif - union dp_main_line_channel_coding_cap { struct { uint8_t DP_8b_10b_SUPPORTED :1; @@ -1232,8 +1227,7 @@ union replay_enable_and_configuration { unsigned char FREESYNC_PANEL_REPLAY_MODE :1; unsigned char TIMING_DESYNC_ERROR_VERIFICATION :1; unsigned char STATE_TRANSITION_ERROR_DETECTION :1; - unsigned char RESERVED0 :1; - unsigned char RESERVED1 :4; + unsigned char RESERVED :5; } bits; unsigned char raw; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index aae2f3a2660d..2ad7f60805f5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -738,6 +738,13 @@ enum scanning_type { SCANNING_TYPE_UNDEFINED }; +enum chroma_cositing { + CHROMA_COSITING_NONE, + CHROMA_COSITING_LEFT, + CHROMA_COSITING_TOPLEFT, + CHROMA_COSITING_COUNT +}; + struct dc_crtc_timing_flags { uint32_t INTERLACE :1; uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1, @@ -974,6 +981,7 @@ struct dc_crtc_timing_adjust { uint32_t v_total_max; uint32_t v_total_mid; uint32_t v_total_mid_frame_num; + uint32_t allow_otg_v_count_halt; }; diff --git a/drivers/gpu/drm/amd/display/dc/dc_plane.h b/drivers/gpu/drm/amd/display/dc/dc_plane.h index ef380cae816a..44afcd989224 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_plane.h +++ b/drivers/gpu/drm/amd/display/dc/dc_plane.h @@ -29,7 +29,7 @@ #include "dc.h" #include "dc_hw_types.h" -struct dc_plane_state *dc_create_plane_state(struct dc *dc); +struct dc_plane_state *dc_create_plane_state(const struct dc *dc); const struct dc_plane_status *dc_plane_get_status( const struct dc_plane_state *plane_state); void dc_plane_state_retain(struct dc_plane_state *plane_state); diff --git a/drivers/gpu/drm/amd/display/dc/dc_plane_priv.h b/drivers/gpu/drm/amd/display/dc/dc_plane_priv.h index 9ee184c1df00..ab13335f1d01 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_plane_priv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_plane_priv.h @@ -30,5 +30,6 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_state); void dc_plane_destruct(struct dc_plane_state *plane_state); +uint8_t dc_plane_get_pipe_mask(struct dc_state *dc_state, const struct dc_plane_state *plane_state); #endif /* _DC_PLANE_PRIV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_state.h b/drivers/gpu/drm/amd/display/dc/dc_state.h index d167fdbfa8a9..caa45db50232 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_state.h +++ b/drivers/gpu/drm/amd/display/dc/dc_state.h @@ -29,7 +29,7 @@ #include "dc.h" #include "inc/core_status.h" -struct dc_state *dc_state_create(struct dc *dc); +struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *params); void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state); struct dc_state *dc_state_create_copy(struct dc_state *src_state); void dc_state_copy_current(struct dc *dc, struct dc_state *dst_state); @@ -39,12 +39,12 @@ void dc_state_destruct(struct dc_state *state); void dc_state_retain(struct dc_state *state); void dc_state_release(struct dc_state *state); -enum dc_status dc_state_add_stream(struct dc *dc, +enum dc_status dc_state_add_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *stream); enum dc_status dc_state_remove_stream( - struct dc *dc, + const struct dc *dc, struct dc_state *state, struct dc_stream_state *stream); @@ -74,5 +74,5 @@ bool dc_state_add_all_planes_for_stream( struct dc_stream_status *dc_state_get_stream_status( struct dc_state *state, - struct dc_stream_state *stream); + const struct dc_stream_state *stream); #endif /* _DC_STATE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h index c1f44e09a6c1..615086d74d32 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h @@ -29,6 +29,8 @@ #include "dc_state.h" #include "dc_stream.h" +struct dc_stream_state *dc_state_get_stream_from_id(const struct dc_state *state, unsigned int id); + /* Get the type of the provided resource (none, phantom, main) based on the provided * context. If the context is unavailable, determine only if phantom or not. */ @@ -45,7 +47,7 @@ struct dc_stream_state *dc_state_get_paired_subvp_stream(const struct dc_state * struct dc_stream_state *dc_state_create_phantom_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *main_stream); -struct dc_plane_state *dc_state_create_phantom_plane(struct dc *dc, +struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc, struct dc_state *state, struct dc_plane_state *main_plane); @@ -58,11 +60,11 @@ void dc_state_release_phantom_plane(const struct dc *dc, struct dc_plane_state *phantom_plane); /* add/remove phantom stream to context and generate subvp meta data */ -enum dc_status dc_state_add_phantom_stream(struct dc *dc, +enum dc_status dc_state_add_phantom_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *phantom_stream, struct dc_stream_state *main_stream); -enum dc_status dc_state_remove_phantom_stream(struct dc *dc, +enum dc_status dc_state_remove_phantom_stream(const struct dc *dc, struct dc_state *state, struct dc_stream_state *phantom_stream); @@ -92,11 +94,11 @@ bool dc_state_add_all_phantom_planes_for_stream( struct dc_state *state); bool dc_state_remove_phantom_streams_and_planes( - struct dc *dc, + const struct dc *dc, struct dc_state *state); void dc_state_release_phantom_streams_and_planes( - struct dc *dc, + const struct dc *dc, struct dc_state *state); #endif /* _DC_STATE_PRIV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index ee10941caa59..e5dbbc6089a5 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -190,7 +190,7 @@ struct dc_stream_state { PHYSICAL_ADDRESS_LOC dmdata_address; bool use_dynamic_meta; - struct dc_transfer_func *out_transfer_func; + struct dc_transfer_func out_transfer_func; struct colorspace_transform gamut_remap_matrix; struct dc_csc_transform csc_color_matrix; @@ -427,14 +427,6 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc, enum dc_status dc_validate_stream(struct dc *dc, struct dc_stream_state *stream); -/* - * Set up streams and links associated to drive sinks - * The streams parameter is an absolute set of all active streams. - * - * After this call: - * Phy, Encoder, Timing Generator are programmed and enabled. - * New streams are enabled with blank stream; no memory read. - */ /* * Enable stereo when commit_streams is not required, * for example, frame alternate. diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index be2ac5c442a4..0f66d00ef80f 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -422,7 +422,7 @@ struct dc_dwb_params { enum dwb_capture_rate capture_rate; /* controls the frame capture rate */ struct scaling_taps scaler_taps; /* Scaling taps */ enum dwb_subsample_position subsample_position; - struct dc_transfer_func *out_transfer_func; + const struct dc_transfer_func *out_transfer_func; }; /* audio*/ @@ -1050,6 +1050,8 @@ union replay_error_status { struct replay_config { /* Replay feature is supported */ bool replay_supported; + /* Replay caps support DPCD & EDID caps*/ + bool replay_cap_support; /* Power opt flags that are supported */ unsigned int replay_power_opt_supported; /* SMU optimization is supported */ @@ -1175,4 +1177,20 @@ enum mall_stream_type { SUBVP_MAIN, // subvp in use, this stream is main stream SUBVP_PHANTOM, // subvp in use, this stream is a phantom stream }; + +enum dc_power_source_type { + DC_POWER_SOURCE_AC, // wall power + DC_POWER_SOURCE_DC, // battery power +}; + +struct dc_state_create_params { + enum dc_power_source_type power_source; +}; + +struct dc_commit_streams_params { + struct dc_stream_state **streams; + uint8_t stream_count; + enum dc_power_source_type power_source; +}; + #endif /* DC_TYPES_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 970644b695cd..b5e0289d2fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -976,7 +976,10 @@ static bool dcn31_program_pix_clk( struct bp_pixel_clock_parameters bp_pc_params = {0}; enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; - if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0) + // Apply ssed(spread spectrum) dpref clock for edp only. + if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0 + && pix_clk_params->signal_type == SIGNAL_TYPE_EDP + && encoding == DP_8b_10b_ENCODING) dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz; // For these signal types Driver to program DP_DTO without calling VBIOS Command table if (dc_is_dp_signal(pix_clk_params->signal_type) || dc_is_virtual_signal(pix_clk_params->signal_type)) { @@ -1093,9 +1096,6 @@ static bool get_pixel_clk_frequency_100hz( unsigned int modulo_hz = 0; unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz; - if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0) - dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz; - if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) { clock_hz = REG_READ(PHASE[inst]); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c index a2f48d46d199..ee601a6897a1 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c @@ -22,9 +22,6 @@ * Authors: AMD * */ - -#include - #include "resource.h" #include "dce_i2c.h" #include "dce_i2c_hw.h" @@ -315,9 +312,6 @@ static bool setup_engine( /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/ REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1); - /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/ - REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1); - /*set SW requested I2c speed to default, if API calls in it will be override later*/ set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h index f98400efdd9b..e34e445a4013 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.h @@ -181,6 +181,7 @@ struct dce_mem_input_registers { SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\ SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\ + SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\ SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\ SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\ SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h index bf1ffc3629c7..3d9be87aae45 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.h @@ -111,6 +111,7 @@ enum dce110_opp_reg_type { OPP_SF(FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh),\ OPP_SF(FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh),\ OPP_SF(FMT_DITHER_RAND_B_SEED, FMT_RAND_B_SEED, mask_sh),\ + OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_EN, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_RESET, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_OFFSET, mask_sh),\ OPP_SF(FMT_BIT_DEPTH_CONTROL, FMT_TEMPORAL_DITHER_DEPTH, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index 670d5ab9d998..2b1673d69ea8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -1408,7 +1408,7 @@ void dce110_opp_set_csc_default( static void program_pwl(struct dce_transform *xfm_dce, const struct pwl_params *params) { - int retval; + uint32_t retval; uint8_t max_tries = 10; uint8_t counter = 0; uint32_t i = 0; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c index f9d6a181164a..b851fc65f5b7 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c @@ -34,11 +34,7 @@ #include "reg_helper.h" #include "fixed31_32.h" -#ifdef _WIN32 -#include "atombios.h" -#else #include "atom.h" -#endif #define TO_DMUB_ABM(abm)\ container_of(abm, struct dce_abm, base) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index b010814706fe..4f559a025cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -244,7 +244,7 @@ static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst, uint16_t param = (uint16_t)(panel_inst << 8); if (is_alpm) - param |= REPLAY_RESIDENCY_MODE_ALPM; + param |= REPLAY_RESIDENCY_FIELD_MODE_ALPM; if (is_start) param |= REPLAY_RESIDENCY_ENABLE; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index ae6a131be71b..8dc7938c36d8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -24,9 +24,9 @@ DCN10 = dcn10_ipp.o \ dcn10_hw_sequencer_debug.o \ - dcn10_dpp.o dcn10_opp.o \ + dcn10_opp.o \ dcn10_hubp.o dcn10_mpc.o \ - dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ + dcn10_cm_common.o \ dcn10_hubbub.o dcn10_stream_encoder.o dcn10_link_encoder.o AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c index b7e57aa27361..0b49362f71b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c @@ -24,7 +24,7 @@ */ #include "dc.h" #include "reg_helper.h" -#include "dcn10_dpp.h" +#include "dcn10/dcn10_dpp.h" #include "dcn10_cm_common.h" #include "custom_float.h" @@ -402,6 +402,11 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx, i += increment) { if (j == hw_points - 1) break; + if (i >= TRANSFER_FUNC_POINTS) { + DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n", + i, TRANSFER_FUNC_POINTS); + return false; + } rgb_resulted[j].red = output_tf->tf_pts.red[i]; rgb_resulted[j].green = output_tf->tf_pts.green[i]; rgb_resulted[j].blue = output_tf->tf_pts.blue[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index d51f1ce02874..6dd355a03033 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c @@ -130,7 +130,7 @@ bool hubbub1_verify_allow_pstate_change_high( static unsigned int max_sampled_pstate_wait_us; /* data collection */ static bool forced_pstate_allow; /* help with revert wa */ - unsigned int debug_data; + unsigned int debug_data = 0; unsigned int i; if (forced_pstate_allow) { @@ -242,7 +242,7 @@ void hubbub1_wm_change_req_wa(struct hubbub *hubbub) bool hubbub1_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -356,7 +356,7 @@ bool hubbub1_program_urgent_watermarks( bool hubbub1_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -501,7 +501,7 @@ bool hubbub1_program_stutter_watermarks( bool hubbub1_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -582,7 +582,7 @@ bool hubbub1_program_pstate_watermarks( bool hubbub1_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h index 4201b7627030..d1f9e63944c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h @@ -409,7 +409,7 @@ struct dcn10_hubbub { const struct dcn_hubbub_shift *shifts; const struct dcn_hubbub_mask *masks; unsigned int debug_test_index_pstate; - struct dcn_watermark_set watermarks; + union dcn_watermark_set watermarks; }; void hubbub1_update_dchub( @@ -423,7 +423,7 @@ void hubbub1_wm_change_req_wa(struct hubbub *hubbub); bool hubbub1_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); @@ -446,17 +446,17 @@ void hubbub1_construct(struct hubbub *hubbub, bool hubbub1_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub1_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub1_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h index 09784222cc03..69119b2fdce2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h @@ -692,6 +692,7 @@ struct dcn_hubp_state { uint32_t primary_meta_addr_hi; uint32_t uclk_pstate_force; uint32_t hubp_cntl; + uint32_t flip_control; }; struct dcn10_hubp { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c index 9033b39e0e0c..c51b717e5622 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer_debug.c @@ -392,7 +392,7 @@ static unsigned int dcn10_get_mpcc_states(struct dc *dc, char *pBuf, unsigned in remaining_buffer -= chars_printed; pBuf += chars_printed; - for (i = 0; i < pool->pipe_count; i++) { + for (i = 0; i < pool->mpcc_count; i++) { struct mpcc_state s = {0}; pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 377f1ba1a81b..4d0eed7598b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c @@ -1439,7 +1439,6 @@ enum signal_type dcn10_get_dig_mode( default: return SIGNAL_TYPE_NONE; } - return SIGNAL_TYPE_NONE; } void dcn10_link_encoder_get_max_link_cap(struct link_encoder *enc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index d980e6bd6c66..b7a89c39f445 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -167,7 +167,6 @@ struct dcn10_link_enc_registers { uint32_t DIO_LINKD_CNTL; uint32_t DIO_LINKE_CNTL; uint32_t DIO_LINKF_CNTL; - uint32_t DIG_FIFO_CTRL0; uint32_t DIO_CLK_CNTL; uint32_t DIG_BE_CLK_CNTL; }; @@ -475,9 +474,6 @@ struct dcn10_link_enc_registers { type HPO_DP_ENC_SEL;\ type HPO_HDMI_ENC_SEL -#define DCN32_LINK_ENCODER_REG_FIELD_LIST(type) \ - type DIG_FIFO_OUTPUT_PIXEL_MODE - #define DCN35_LINK_ENCODER_REG_FIELD_LIST(type) \ type DIG_BE_ENABLE;\ type DIG_RB_SWITCH_EN;\ @@ -512,7 +508,6 @@ struct dcn10_link_enc_shift { DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t); - DCN32_LINK_ENCODER_REG_FIELD_LIST(uint8_t); DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t); }; @@ -521,7 +516,6 @@ struct dcn10_link_enc_mask { DCN20_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t); - DCN32_LINK_ENCODER_REG_FIELD_LIST(uint32_t); DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t); }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 5838a11efd00..71e9288d60ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c @@ -168,6 +168,10 @@ static void opp1_set_pixel_encoding( case PIXEL_ENCODING_RGB: case PIXEL_ENCODING_YCBCR444: + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 0, + FMT_SUBSAMPLING_MODE, 0, + FMT_CBCR_BIT_REDUCTION_BYPASS, 0); REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 0); break; case PIXEL_ENCODING_YCBCR422: @@ -177,7 +181,10 @@ static void opp1_set_pixel_encoding( FMT_CBCR_BIT_REDUCTION_BYPASS, 0); break; case PIXEL_ENCODING_YCBCR420: - REG_UPDATE(FMT_CONTROL, FMT_PIXEL_ENCODING, 2); + REG_UPDATE_3(FMT_CONTROL, + FMT_PIXEL_ENCODING, 2, + FMT_SUBSAMPLING_MODE, 2, + FMT_CBCR_BIT_REDUCTION_BYPASS, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h index 2c0ecfa5a643..c87de68a509e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.h @@ -79,6 +79,8 @@ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_PIXEL_ENCODING, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_SUBSAMPLING_MODE, mask_sh), \ + OPP_SF(FMT0_FMT_CONTROL, FMT_CBCR_BIT_REDUCTION_BYPASS, mask_sh), \ OPP_SF(FMT0_FMT_CONTROL, FMT_STEREOSYNC_OVERRIDE, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_R_SEED, FMT_RAND_R_SEED, mask_sh), \ OPP_SF(FMT0_FMT_DITHER_RAND_G_SEED, FMT_RAND_G_SEED, mask_sh), \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index c429590f1298..1b96972b9d0f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -127,7 +127,6 @@ struct dcn10_stream_enc_registers { uint32_t AFMT_60958_1; uint32_t AFMT_60958_2; uint32_t DIG_FE_CNTL; - uint32_t DIG_FE_CNTL2; uint32_t DIG_FIFO_STATUS; uint32_t DP_MSE_RATE_CNTL; uint32_t DP_MSE_RATE_UPDATE; @@ -570,7 +569,7 @@ struct dcn10_stream_enc_registers { type DP_SEC_GSP11_ENABLE;\ type DP_SEC_GSP11_LINE_NUM -#define SE_REG_FIELD_LIST_DCN3_2(type) \ +#define SE_REG_FIELD_LIST_DCN3_1_COMMON(type) \ type DIG_FIFO_OUTPUT_PIXEL_MODE;\ type DP_PIXEL_PER_CYCLE_PROCESSING_MODE;\ type DIG_SYMCLK_FE_ON;\ @@ -599,7 +598,7 @@ struct dcn10_stream_encoder_shift { uint8_t HDMI_ACP_SEND; SE_REG_FIELD_LIST_DCN2_0(uint8_t); SE_REG_FIELD_LIST_DCN3_0(uint8_t); - SE_REG_FIELD_LIST_DCN3_2(uint8_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t); SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t); }; @@ -608,7 +607,7 @@ struct dcn10_stream_encoder_mask { uint32_t HDMI_ACP_SEND; SE_REG_FIELD_LIST_DCN2_0(uint32_t); SE_REG_FIELD_LIST_DCN3_0(uint32_t); - SE_REG_FIELD_LIST_DCN3_2(uint32_t); + SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t); SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t); }; @@ -667,9 +666,6 @@ void enc1_stream_encoder_send_immediate_sdp_message( void enc1_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc); -void enc1_stream_encoder_reset_fifo( - struct stream_encoder *enc); - void enc1_stream_encoder_dp_blank( struct dc_link *link, struct stream_encoder *enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 3dae3943b056..9b6070c99794 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -2,7 +2,7 @@ # # Makefile for DCN. -DCN20 = dcn20_dpp.o dcn20_dpp_cm.o dcn20_hubp.o \ +DCN20 = dcn20_hubp.o \ dcn20_mpc.o dcn20_opp.o dcn20_hubbub.o dcn20_mmhubbub.o \ dcn20_stream_encoder.o dcn20_link_encoder.o dcn20_dccg.o \ dcn20_vmid.o dcn20_dwb.o dcn20_dwb_scl.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.c index f8667be57046..80779e85e2c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.c @@ -299,6 +299,17 @@ void dwb2_set_scaler(struct dwbc *dwbc, struct dc_dwb_params *params) } } + + if (dwbc20->dwbc_mask->WBSCL_COEF_RAM_SEL) { + /* Swap double buffered coefficient set */ + uint32_t wbscl_mode = REG_READ(WBSCL_MODE); + bool coef_ram_current = get_reg_field_value_ex( + wbscl_mode, dwbc20->dwbc_mask->WBSCL_COEF_RAM_SEL_CURRENT, + dwbc20->dwbc_shift->WBSCL_COEF_RAM_SEL_CURRENT); + + REG_UPDATE(WBSCL_MODE, WBSCL_COEF_RAM_SEL, !coef_ram_current); + } + } static const struct dwbc_funcs dcn20_dwbc_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c index 6eebcb22e317..c6f859871d11 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c @@ -570,7 +570,7 @@ void hubbub2_get_dchub_ref_freq(struct hubbub *hubbub, static bool hubbub2_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h index 2f6146bf1d32..24a9c45988ed 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.h @@ -85,7 +85,7 @@ struct dcn20_hubbub { const struct dcn_hubbub_shift *shifts; const struct dcn_hubbub_mask *masks; unsigned int debug_test_index_pstate; - struct dcn_watermark_set watermarks; + union dcn_watermark_set watermarks; int num_vmid; struct dcn20_vmid vmid[16]; unsigned int detile_buf_size; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c index 89c3bf0fe0c9..6bba020ad6fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c @@ -1331,6 +1331,12 @@ void hubp2_read_state(struct hubp *hubp) SWATH_HEIGHT_C, &rq_regs->rq_regs_c.swath_height, PTE_ROW_HEIGHT_LINEAR_C, &rq_regs->rq_regs_c.pte_row_height_linear); + if (REG(DCHUBP_CNTL)) + s->hubp_cntl = REG_READ(DCHUBP_CNTL); + + if (REG(DCSURF_FLIP_CONTROL)) + s->flip_control = REG_READ(DCSURF_FLIP_CONTROL); + } static void hubp2_validate_dml_output(struct hubp *hubp, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h index efa2adf4f83d..8da3084d933f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.h @@ -147,7 +147,7 @@ uint32_t DCN_CUR1_TTU_CNTL1;\ uint32_t VMID_SETTINGS_0 - +/*shared with dcn3.x*/ #define DCN21_HUBP_REG_COMMON_VARIABLE_LIST \ DCN2_HUBP_REG_COMMON_VARIABLE_LIST; \ uint32_t FLIP_PARAMETERS_3;\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index b2b266953d18..c34e04cac9a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -147,7 +147,8 @@ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_SWAP, mask_sh),\ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT, mask_sh),\ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_EN, mask_sh),\ - LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh) + LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_FIFO_RD_START_DELAY, mask_sh),\ + LE_SF(DPCSTX0_DPCSTX_DEBUG_CONFIG, DPCS_DBG_CBUS_DIS, mask_sh) #define DPCS_DCN2_MASK_SH_LIST(mask_sh)\ DPCS_MASK_SH_LIST(mask_sh),\ @@ -231,6 +232,8 @@ SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ + SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ SR(RDPCSTX0_RDPCSTX_SCRATCH) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c index 16b5ff208d14..ea73473b970a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c @@ -395,9 +395,12 @@ static void mpc20_program_ogam_pwl( MPCC_OGAM_LUT_DATA, rgb[i].delta_green_reg); REG_SET(MPCC_OGAM_LUT_DATA[mpcc_id], 0, MPCC_OGAM_LUT_DATA, rgb[i].delta_blue_reg); - } + REG_SEQ_SUBMIT(); + PERF_TRACE(); + REG_SEQ_WAIT_DONE(); + PERF_TRACE(); } static void apply_DEDCN20_305_wa(struct mpc *mpc, int mpcc_id, @@ -501,11 +504,6 @@ void mpc2_assert_mpcc_idle_before_connect(struct mpc *mpc, int mpcc_id) ASSERT(!mpc_disabled); ASSERT(!mpc_idle); } - - REG_SEQ_SUBMIT(); - PERF_TRACE(); - REG_SEQ_WAIT_DONE(); - PERF_TRACE(); } static void mpc2_init_mpcc(struct mpcc *mpcc, int mpcc_inst) diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile index 2b0b4f32e13b..3880db59e457 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn201/Makefile @@ -2,7 +2,7 @@ # # Makefile for DCN. DCN201 = dcn201_hubbub.o\ - dcn201_mpc.o dcn201_hubp.o dcn201_opp.o dcn201_dpp.o \ + dcn201_mpc.o dcn201_hubp.o dcn201_opp.o \ dcn201_dccg.o dcn201_link_encoder.o AMD_DAL_DCN201 = $(addprefix $(AMDDALPATH)/dc/dcn201/,$(DCN201)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubbub.c index 037d265431c6..63798132ed95 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubbub.c @@ -52,7 +52,7 @@ static bool hubbub201_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -103,5 +103,5 @@ void hubbub201_construct(struct dcn20_hubbub *hubbub, hubbub->masks = hubbub_mask; hubbub->debug_test_index_pstate = 0xB; - hubbub->detile_buf_size = 164 * 1024; + hubbub->detile_buf_size = 164 * 1024; /* 164KB for DCN2.0 */ } diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubp.c index 35dd4bac242a..cd2bfcc51276 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_hubp.c @@ -77,6 +77,7 @@ static void hubp201_program_requestor(struct hubp *hubp, MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode, CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode); + /* no need to program PTE */ REG_SET_5(DCHUBP_REQ_SIZE_CONFIG, 0, CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size, MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size, @@ -99,6 +100,10 @@ static void hubp201_setup( struct _vcs_dpi_display_rq_regs_st *rq_regs, struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest) { + /* + * otg is locked when this func is called. Register are double buffered. + * disable the requestors is not needed + */ hubp2_vready_at_or_After_vsync(hubp, pipe_dest); hubp201_program_requestor(hubp, rq_regs); hubp201_program_deadline(hubp, dlg_attr, ttu_attr); diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.h index 8b95ef251332..be25e8dc0636 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.h @@ -30,6 +30,10 @@ #define DPCS_DCN201_MASK_SH_LIST(mask_sh)\ DPCS_MASK_SH_LIST(mask_sh),\ + LE_SF(DPCSSYS_CR0_RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2, VCO_LD_VAL_OVRD, mask_sh),\ + LE_SF(DPCSSYS_CR0_RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2, VCO_LD_VAL_OVRD_EN, mask_sh),\ + LE_SF(DPCSSYS_CR0_RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3, REF_LD_VAL_OVRD, mask_sh),\ + LE_SF(DPCSSYS_CR0_RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3, REF_LD_VAL_OVRD_EN, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DPALT_DISABLE_ACK, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DPALT_DISABLE, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL2, RDPCS_PHY_DPALT_DP4, mask_sh),\ @@ -44,7 +48,15 @@ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL11, RDPCS_PHY_DP_REF_CLK_EN, mask_sh) #define DPCS_DCN201_REG_LIST(id) \ - DPCS_DCN2_CMN_REG_LIST(id) + DPCS_DCN2_CMN_REG_LIST(id), \ + SRI_IX(RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_2, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE0_DIG_PCS_XF_RX_OVRD_IN_3, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_2, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE1_DIG_PCS_XF_RX_OVRD_IN_3, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_2, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE2_DIG_PCS_XF_RX_OVRD_IN_3, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_2, DPCSSYS_CR, id), \ + SRI_IX(RAWLANE3_DIG_PCS_XF_RX_OVRD_IN_3, DPCSSYS_CR, id) void dcn201_link_encoder_construct( struct dcn20_link_encoder *enc20, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c index aeb0e0d9b70a..2546224b326a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c @@ -140,7 +140,7 @@ int hubbub21_init_dchub(struct hubbub *hubbub, bool hubbub21_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -334,7 +334,7 @@ bool hubbub21_program_urgent_watermarks( bool hubbub21_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -487,7 +487,7 @@ bool hubbub21_program_stutter_watermarks( bool hubbub21_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -573,7 +573,7 @@ bool hubbub21_program_pstate_watermarks( bool hubbub21_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h index d8eb2bb7282c..ab2ce0313529 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.h @@ -127,22 +127,22 @@ int hubbub21_init_dchub(struct hubbub *hubbub, struct dcn_hubbub_phys_addr_config *pa_config); bool hubbub21_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub21_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub21_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub21_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index b5b2aa3b3783..c6ca70f3c061 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -25,13 +25,11 @@ DCN30 := dcn30_hubbub.o \ dcn30_hubp.o \ - dcn30_dpp.o \ dcn30_dccg.o \ dcn30_mpc.o dcn30_vpg.o \ dcn30_afmt.o \ dcn30_dio_stream_encoder.o \ dcn30_dwb.o \ - dcn30_dpp_cm.o \ dcn30_dwb_cm.o \ dcn30_cm_common.o \ dcn30_mmhubbub.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c index ddb344056d40..b8327237ed44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c @@ -26,7 +26,7 @@ #include "dm_services.h" #include "core_types.h" #include "reg_helper.h" -#include "dcn30_dpp.h" +#include "dcn30/dcn30_dpp.h" #include "basics/conversion.h" #include "dcn30_cm_common.h" #include "custom_float.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h index 35a613bb08bf..3f1da7f3a91c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dccg.h @@ -29,15 +29,9 @@ #include "dcn20/dcn20_dccg.h" -#define DCCG_REG_LIST_DCN3AG() \ - DCCG_COMMON_REG_LIST_DCN_BASE(),\ - SR(PHYASYMCLK_CLOCK_CNTL),\ - SR(PHYBSYMCLK_CLOCK_CNTL),\ - SR(PHYCSYMCLK_CLOCK_CNTL) - - #define DCCG_REG_LIST_DCN30() \ DCCG_REG_LIST_DCN2(),\ + DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0),\ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2),\ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3),\ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 4),\ @@ -46,19 +40,10 @@ SR(PHYBSYMCLK_CLOCK_CNTL),\ SR(PHYCSYMCLK_CLOCK_CNTL) -#define DCCG_MASK_SH_LIST_DCN3AG(mask_sh) \ - DCCG_MASK_SH_LIST_DCN2_1(mask_sh),\ - DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ - DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ - DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_SRC_SEL, mask_sh),\ - DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_EN, mask_sh),\ - DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_FORCE_SRC_SEL, mask_sh) - #define DCCG_MASK_SH_LIST_DCN3(mask_sh) \ DCCG_MASK_SH_LIST_DCN2(mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c index 1fb8fd7afc95..b8e31b5ea114 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c @@ -30,8 +30,6 @@ #include "dcn30_dio_link_encoder.h" #include "stream_encoder.h" #include "dc_bios_types.h" -/* #include "dcn3ag/dcn3ag_phy_fw.h" */ - #include "gpio_service_interface.h" #define CTX \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index f2d90f2b8bf1..5b6177c2ae98 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -55,7 +55,8 @@ SRI(DP_DPHY_HBR2_PATTERN_CONTROL, DP, id) #define LINK_ENCODER_MASK_SH_LIST_DCN30(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh) + LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh),\ + LE_SF(DIG0_TMDS_DCBALANCER_CONTROL, TMDS_SYNC_DCBAL_EN, mask_sh) #define DPCS_DCN3_MASK_SH_LIST(mask_sh)\ DPCS_DCN2_MASK_SH_LIST(mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c index 005dbe099a7a..425b830b88d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c @@ -29,9 +29,6 @@ #include "reg_helper.h" #include "hw_shared.h" #include "dc.h" -#include "core_types.h" -#include - #define DC_LOGGER \ enc1->base.ctx->logger diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c index 1b9d9495f76d..fae98cf52020 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.c @@ -251,9 +251,7 @@ static const struct dwbc_funcs dcn30_dwbc_funcs = { .set_fc_enable = dwb3_set_fc_enable, .set_stereo = dwb3_set_stereo, .set_new_content = dwb3_set_new_content, - .dwb_program_output_csc = NULL, .dwb_ogam_set_input_transfer_func = dwb3_ogam_set_input_transfer_func, //TODO: rename - .dwb_set_scaler = NULL, }; void dcn30_dwbc_construct(struct dcn30_dwbc *dwbc30, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h index 332634b76aac..0f3f7c5fbaec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h @@ -217,6 +217,7 @@ SF_DWB2(DWB_OGAM_LUT_DATA, DWBCP, 0, DWB_OGAM_LUT_DATA, mask_sh),\ SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\ SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_COLOR_SEL, mask_sh),\ + SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_READ_DBG, mask_sh),\ SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_HOST_SEL, mask_sh),\ SF_DWB2(DWB_OGAM_LUT_CONTROL, DWBCP, 0, DWB_OGAM_LUT_CONFIG_MODE, mask_sh),\ SF_DWB2(DWB_OGAM_RAMA_START_CNTL_B, DWBCP, 0, DWB_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\ @@ -524,6 +525,7 @@ type DWB_OGAM_LUT_DATA;\ type DWB_OGAM_LUT_WRITE_COLOR_MASK;\ type DWB_OGAM_LUT_READ_COLOR_SEL;\ + type DWB_OGAM_LUT_READ_DBG;\ type DWB_OGAM_LUT_HOST_SEL;\ type DWB_OGAM_LUT_CONFIG_MODE;\ type DWB_OGAM_LUT_STATUS;\ @@ -710,7 +712,7 @@ type DWB_OGAM_RAMB_EXP_REGION32_LUT_OFFSET;\ type DWB_OGAM_RAMB_EXP_REGION32_NUM_SEGMENTS;\ type DWB_OGAM_RAMB_EXP_REGION33_LUT_OFFSET;\ - type DWB_OGAM_RAMB_EXP_REGION33_NUM_SEGMENTS; + type DWB_OGAM_RAMB_EXP_REGION33_NUM_SEGMENTS struct dcn30_dwbc_registers { /* DCN3AG */ @@ -733,6 +735,10 @@ struct dcn30_dwbc_registers { uint32_t DWB_MMHUBBUB_BACKPRESSURE_CNT; uint32_t DWB_HOST_READ_CONTROL; uint32_t DWB_SOFT_RESET; + uint32_t DWB_DEBUG_CTRL; + uint32_t DWB_DEBUG; + uint32_t DWB_TEST_DEBUG_INDEX; + uint32_t DWB_TEST_DEBUG_DATA; /* DWBSCL */ uint32_t DWBSCL_COEF_RAM_TAP_SELECT; @@ -747,6 +753,9 @@ struct dcn30_dwbc_registers { uint32_t DWBSCL_DEST_SIZE; uint32_t DWBSCL_OVERFLOW_STATUS; uint32_t DWBSCL_OVERFLOW_COUNTER; + uint32_t DWBSCL_DEBUG; + uint32_t DWBSCL_TEST_DEBUG_INDEX; + uint32_t DWBSCL_TEST_DEBUG_DATA; /* DWBCP */ uint32_t DWB_HDR_MULT_COEF; @@ -838,6 +847,9 @@ struct dcn30_dwbc_registers { uint32_t DWB_OGAM_RAMB_REGION_28_29; uint32_t DWB_OGAM_RAMB_REGION_30_31; uint32_t DWB_OGAM_RAMB_REGION_32_33; + uint32_t DWBCP_DEBUG; + uint32_t DWBCP_TEST_DEBUG_INDEX; + uint32_t DWBCP_TEST_DEBUG_DATA; }; /* Internal enums / structs */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c index 152c9c5733f1..6a5af3da4b45 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.c @@ -95,7 +95,7 @@ int hubbub3_init_dchub_sys_ctx(struct hubbub *hubbub, bool hubbub3_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h index 7b597908b937..ca6233e8f1f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubbub.h @@ -124,7 +124,7 @@ bool hubbub3_get_dcc_compression_cap(struct hubbub *hubbub, bool hubbub3_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c index 75547ce86c09..60a64d290352 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.c @@ -455,6 +455,9 @@ void hubp3_read_state(struct hubp *hubp) if (REG(DCHUBP_CNTL)) s->hubp_cntl = REG_READ(DCHUBP_CNTL); + if (REG(DCSURF_FLIP_CONTROL)) + s->flip_control = REG_READ(DCSURF_FLIP_CONTROL); + } void hubp3_setup( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index 5ebb57303130..fca94e50ae93 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -1183,7 +1183,7 @@ void mpc3_get_gamut_remap(struct mpc *mpc, struct mpc_grph_gamut_adjustment *adjust) { struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); - uint16_t arr_reg_val[12]; + uint16_t arr_reg_val[12] = {0}; int select; read_gamut_remap(mpc30, mpcc_id, arr_reg_val, &select); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h index ed9a5549c389..466ba20b9c61 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_vpg.h @@ -26,6 +26,7 @@ #ifndef __DAL_DCN30_VPG_H__ #define __DAL_DCN30_VPG_H__ +#include "vpg.h" #define DCN30_VPG_FROM_VPG(vpg)\ container_of(vpg, struct dcn30_vpg, base) @@ -132,28 +133,6 @@ struct dcn30_vpg_mask { VPG_DCN3_REG_FIELD_LIST(uint32_t); }; -struct vpg; - -struct vpg_funcs { - void (*update_generic_info_packet)( - struct vpg *vpg, - uint32_t packet_index, - const struct dc_info_packet *info_packet, - bool immediate_update); - - void (*vpg_poweron)( - struct vpg *vpg); - - void (*vpg_powerdown)( - struct vpg *vpg); -}; - -struct vpg { - const struct vpg_funcs *funcs; - struct dc_context *ctx; - int inst; -}; - struct dcn30_vpg { struct vpg base; const struct dcn30_vpg_registers *regs; diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_dccg.h index 73db962dbc03..067e49cb238e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_dccg.h @@ -56,10 +56,4 @@ struct dccg *dccg301_create( const struct dccg_shift *dccg_shift, const struct dccg_mask *dccg_mask); -struct dccg *dccg301_create( - struct dc_context *ctx, - const struct dccg_registers *regs, - const struct dccg_shift *dccg_shift, - const struct dccg_mask *dccg_mask); - #endif //__DCN301_DCCG_H__ diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c index a046664e2031..c1959672df50 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_hubbub.c @@ -63,6 +63,7 @@ static const struct hubbub_funcs hubbub301_funcs = { .verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high, .force_wm_propagate_to_pipes = hubbub3_force_wm_propagate_to_pipes, .force_pstate_change_control = hubbub3_force_pstate_change_control, + .init_watermarks = hubbub3_init_watermarks, .hubbub_read_state = hubbub2_read_state, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h index e3caaacf7493..e3be0bab4007 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dccg.h @@ -34,12 +34,14 @@ DCCG_SRII(DTO_PARAM, DPPCLK, 1),\ DCCG_SRII(DTO_PARAM, DPPCLK, 2),\ DCCG_SRII(DTO_PARAM, DPPCLK, 3),\ + DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0),\ SR(PHYASYMCLK_CLOCK_CNTL),\ SR(PHYBSYMCLK_CLOCK_CNTL),\ SR(PHYCSYMCLK_CLOCK_CNTL),\ SR(PHYDSYMCLK_CLOCK_CNTL),\ SR(PHYESYMCLK_CLOCK_CNTL),\ SR(DPSTREAMCLK_CNTL),\ + SR(HDMISTREAMCLK_CNTL),\ SR(SYMCLK32_SE_CNTL),\ SR(SYMCLK32_LE_CNTL),\ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0),\ @@ -78,6 +80,8 @@ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\ + DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_EN, mask_sh),\ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_FORCE_SRC_SEL, mask_sh),\ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_FORCE_EN, mask_sh),\ @@ -92,6 +96,8 @@ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK_PIPE1_EN, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK_PIPE2_EN, mask_sh),\ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK_PIPE3_EN, mask_sh),\ + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\ + DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_DTO_FORCE_DIS, mask_sh),\ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c index 26be5fee7411..b2cea59ba5d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.c @@ -205,7 +205,7 @@ void dcn31_link_encoder_set_dio_phy_mux( } } -static void enc31_hw_init(struct link_encoder *enc) +void enc31_hw_init(struct link_encoder *enc) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h index 221671563a0b..ee78ba80797c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_dio_link_encoder.h @@ -89,6 +89,7 @@ SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ SR(RDPCSTX0_RDPCSTX_SCRATCH), \ SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) @@ -222,6 +223,7 @@ SRI(RDPCSTX_PHY_FUSE1, RDPCSTX, id), \ SRI(RDPCSTX_PHY_FUSE2, RDPCSTX, id), \ SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ + SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ SR(RDPCSTX0_RDPCSTX_SCRATCH), \ SRI(RDPCSTX_PHY_RX_LD_VAL, RDPCSTX, id),\ SRI(RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG, RDPCSTX, id) @@ -283,4 +285,6 @@ bool dcn31_link_encoder_is_in_alt_mode( void dcn31_link_encoder_get_max_link_cap(struct link_encoder *enc, struct dc_link_settings *link_settings); +void enc31_hw_init(struct link_encoder *enc); + #endif /* __DC_LINK_ENCODER__DCN31_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c index 5b7ad38f85e0..03b4ac2f1991 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c @@ -377,7 +377,7 @@ void dcn31_hpo_dp_link_enc_update_stream_allocation_table( */ REG_WAIT(DP_DPHY_SYM32_STATUS, SAT_UPDATE_PENDING, 0, - 10, DP_SAT_UPDATE_MAX_RETRY); + 100, DP_SAT_UPDATE_MAX_RETRY); } void dcn31_hpo_dp_link_enc_set_throttled_vcp_size( @@ -395,6 +395,12 @@ void dcn31_hpo_dp_link_enc_set_throttled_vcp_size( x), 25)); + // If y rounds up to integer, carry it over to x. + if (y >> 25) { + x += 1; + y = 0; + } + switch (stream_encoder_inst) { case 0: REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c index 45143459eedd..678db949cfe3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c @@ -474,6 +474,10 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( &info_frame->hdrsmd, true); + /* packetIndex 4 is used for send immediate sdp message, and please + * use other packetIndex (such as 5,6) for other info packet + */ + if (info_frame->adaptive_sync.valid) enc->vpg->funcs->update_generic_info_packet( enc->vpg, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c index 5b5b5e0775fa..b906db6e7355 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hubbub.c @@ -172,7 +172,7 @@ static uint32_t convert_and_clamp( static bool hubbub31_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -362,7 +362,7 @@ static bool hubbub31_program_urgent_watermarks( static bool hubbub31_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -635,7 +635,7 @@ static bool hubbub31_program_stutter_watermarks( static bool hubbub31_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -717,7 +717,7 @@ static bool hubbub31_program_pstate_watermarks( static bool hubbub31_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c index 281be20b1a10..20c6fe48567f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c @@ -173,5 +173,12 @@ void dcn31_panel_cntl_construct( break; } - dcn31_panel_cntl->base.pwrseq_inst = pwrseq_inst; + if (dcn31_panel_cntl->base.ctx->dc->config.support_edp0_on_dp1) + //If supported, power sequencer mapping shall follow the DIG instance + dcn31_panel_cntl->base.pwrseq_inst = pwrseq_inst; + else + /* If not supported, pwrseq will be assigned in order, + * so first pwrseq will be assigned to first panel instance (legacy behavior) + */ + dcn31_panel_cntl->base.pwrseq_inst = dcn31_panel_cntl->base.inst; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c index f1deb1c3c363..cfb923d85630 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.c @@ -63,7 +63,12 @@ void vpg31_poweron(struct vpg *vpg) { struct dcn31_vpg *vpg31 = DCN31_VPG_FROM_VPG(vpg); - if (vpg->ctx->dc->debug.enable_mem_low_power.bits.vpg == false) + uint32_t vpg_gsp_mem_pwr_state; + + REG_GET(VPG_MEM_PWR, VPG_GSP_MEM_PWR_STATE, &vpg_gsp_mem_pwr_state); + + if (vpg->ctx->dc->debug.enable_mem_low_power.bits.vpg == false && + vpg_gsp_mem_pwr_state == 0) return; REG_UPDATE_2(VPG_MEM_PWR, VPG_GSP_MEM_LIGHT_SLEEP_DIS, 1, VPG_GSP_LIGHT_SLEEP_FORCE, 0); diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h index 0e76eabce441..609e58dbd056 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_vpg.h @@ -26,6 +26,7 @@ #ifndef __DAL_DCN31_VPG_H__ #define __DAL_DCN31_VPG_H__ +#include "vpg.h" #define DCN31_VPG_FROM_VPG(vpg)\ container_of(vpg, struct dcn31_vpg, base) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile index 5314770fff1c..a58c37165f5a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn32/Makefile @@ -11,7 +11,7 @@ # Makefile for dcn32. DCN32 = dcn32_hubbub.o dcn32_dccg.o \ - dcn32_mmhubbub.o dcn32_dpp.o dcn32_hubp.o dcn32_mpc.o \ + dcn32_mmhubbub.o dcn32_hubp.o dcn32_mpc.o \ dcn32_dio_stream_encoder.o dcn32_dio_link_encoder.o dcn32_resource_helpers.o \ dcn32_hpo_dp_link_encoder.o diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c index e224a028d68a..d9ff95cd2dbd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c @@ -251,8 +251,6 @@ void dcn32_link_encoder_construct( enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; enc10->base.features = *enc_features; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; if (enc10->base.connector.id == CONNECTOR_ID_USBC) enc10->base.features.flags.bits.DP_IS_USB_C = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h index 2d5f25290ed1..35d23d9db45e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h @@ -26,15 +26,7 @@ #ifndef __DC_LINK_ENCODER__DCN32_H__ #define __DC_LINK_ENCODER__DCN32_H__ -#include "dcn31/dcn31_dio_link_encoder.h" - -#define LE_DCN32_REG_LIST(id)\ - LE_DCN31_REG_LIST(id),\ - SRI(DIG_FIFO_CTRL0, DIG, id) - -#define LINK_ENCODER_MASK_SH_LIST_DCN32(mask_sh) \ - LINK_ENCODER_MASK_SH_LIST_DCN31(mask_sh),\ - LE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh) +#include "dcn30/dcn30_dio_link_encoder.h" void dcn32_link_encoder_construct( struct dcn20_link_encoder *enc20, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h index 1be5410cce97..ca53d39561d2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.h @@ -177,11 +177,12 @@ SE_SF(DIG0_DIG_FE_CNTL, DIG_SYMCLK_FE_ON, mask_sh),\ SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\ SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\ - SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh) + SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh) + void dcn32_dio_stream_encoder_construct( struct dcn10_stream_encoder *enc1, diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c index 88dfc907553d..515c4c2b4c21 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c @@ -167,7 +167,7 @@ static uint32_t convert_and_clamp( bool hubbub32_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -357,7 +357,7 @@ bool hubbub32_program_urgent_watermarks( bool hubbub32_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -503,7 +503,7 @@ bool hubbub32_program_stutter_watermarks( bool hubbub32_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -656,7 +656,7 @@ bool hubbub32_program_pstate_watermarks( bool hubbub32_program_usr_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -750,7 +750,7 @@ void hubbub32_force_usr_retraining_allow(struct hubbub *hubbub, bool allow) static bool hubbub32_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h index f073839a4b6d..e439ba0fa30f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h @@ -118,25 +118,25 @@ bool hubbub32_program_urgent_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub32_program_stutter_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub32_program_pstate_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); bool hubbub32_program_usr_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index f98def6c8c2d..fbcd6f7bc993 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -35,25 +35,6 @@ static bool is_dual_plane(enum surface_pixel_format format) return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA; } - -uint32_t dcn32_helper_mall_bytes_to_ways( - struct dc *dc, - uint32_t total_size_in_mall_bytes) -{ - uint32_t cache_lines_used, lines_per_way, total_cache_lines, num_ways; - - /* add 2 lines for worst case alignment */ - cache_lines_used = total_size_in_mall_bytes / dc->caps.cache_line_size + 2; - - total_cache_lines = dc->caps.max_cab_allocation_bytes / dc->caps.cache_line_size; - lines_per_way = total_cache_lines / dc->caps.cache_num_ways; - num_ways = cache_lines_used / lines_per_way; - if (cache_lines_used % lines_per_way > 0) - num_ways++; - - return num_ways; -} - uint32_t dcn32_helper_calculate_mall_bytes_for_cursor( struct dc *dc, struct pipe_ctx *pipe_ctx, @@ -112,8 +93,10 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp( if (context->bw_ctx.bw.dcn.mall_subvp_size_bytes > 0) { if (dc->debug.force_subvp_num_ways) { return dc->debug.force_subvp_num_ways; + } else if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) { + return dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes); } else { - return dcn32_helper_mall_bytes_to_ways(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes); + return 0; } } else { return 0; @@ -399,7 +382,7 @@ void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context, { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; bool disable_unbounded_requesting = dc->debug.disable_z9_mpc || dc->debug.disable_unbounded_requesting; for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c index 13be5f06d987..05783daa62ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_dio_link_encoder.c @@ -127,11 +127,6 @@ void dcn321_link_encoder_construct( * while doing the DP sink detect */ -/* if (dal_adapter_service_is_feature_supported(as, - FEATURE_DP_SINK_DETECT_POLL_DATA_PIN)) - enc10->base.features.flags.bits. - DP_SINK_DETECT_POLL_DATA_PIN = true;*/ - enc10->base.output_signals = SIGNAL_TYPE_DVI_SINGLE_LINK | SIGNAL_TYPE_DVI_DUAL_LINK | @@ -191,7 +186,6 @@ void dcn321_link_encoder_construct( __func__, result); } - if (enc10->base.ctx->dc->debug.hdmi20_disable) { + if (enc10->base.ctx->dc->debug.hdmi20_disable) enc10->base.features.flags.bits.HDMI_6GB_EN = 0; - } } diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile index 0e317e0c36a0..d5b4533d2f62 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn35/Makefile @@ -13,7 +13,7 @@ DCN35 = dcn35_dio_stream_encoder.o \ dcn35_dio_link_encoder.o dcn35_dccg.o \ dcn35_hubp.o dcn35_hubbub.o \ - dcn35_mmhubbub.o dcn35_opp.o dcn35_dpp.o dcn35_pg_cntl.o dcn35_dwb.o + dcn35_mmhubbub.o dcn35_opp.o dcn35_pg_cntl.o dcn35_dwb.o AMD_DAL_DCN35 = $(addprefix $(AMDDALPATH)/dc/dcn35/,$(DCN35)) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c index f1ba7bb792ea..58dd3c5bbff0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c @@ -49,15 +49,23 @@ static void dcn35_set_dppclk_enable(struct dccg *dccg, switch (dpp_inst) { case 0: REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, enable); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable); break; case 1: REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, enable); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable); break; case 2: REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, enable); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable); break; case 3: REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, enable); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable); break; default: break; @@ -100,6 +108,32 @@ static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst, dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; } +static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg, + uint32_t dpp_inst, uint32_t enable) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + return; + + switch (dpp_inst) { + case 0: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable); + break; + case 1: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable); + break; + case 2: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable); + break; + case 3: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable); + break; + default: + break; + } +} + static void dccg35_get_pixel_rate_div( struct dccg *dccg, uint32_t otg_inst, @@ -333,21 +367,28 @@ static void dccg35_set_dpstreamclk( /* enabled to select one of the DTBCLKs for pipe */ switch (dp_hpo_inst) { case 0: - REG_UPDATE_2(DPSTREAMCLK_CNTL, - DPSTREAMCLK0_EN, + REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, (src == REFCLK) ? 0 : 1, DPSTREAMCLK0_SRC_SEL, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, (src == REFCLK) ? 0 : 1); break; case 1: REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, (src == REFCLK) ? 0 : 1, DPSTREAMCLK1_SRC_SEL, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, (src == REFCLK) ? 0 : 1); break; case 2: REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, (src == REFCLK) ? 0 : 1, DPSTREAMCLK2_SRC_SEL, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, (src == REFCLK) ? 0 : 1); break; case 3: REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, (src == REFCLK) ? 0 : 1, DPSTREAMCLK3_SRC_SEL, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, (src == REFCLK) ? 0 : 1); break; default: BREAK_TO_DEBUGGER(); @@ -355,6 +396,47 @@ static void dccg35_set_dpstreamclk( } } + +static void dccg35_set_dpstreamclk_root_clock_gating( + struct dccg *dccg, + int dp_hpo_inst, + bool enable) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (dp_hpo_inst) { + case 0: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, enable ? 1 : 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, enable ? 1 : 0); + } + break; + case 1: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, enable ? 1 : 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, enable ? 1 : 0); + } + break; + case 2: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, enable ? 1 : 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, enable ? 1 : 0); + } + break; + case 3: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) { + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, enable ? 1 : 0); + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, enable ? 1 : 0); + } + break; + default: + BREAK_TO_DEBUGGER(); + return; + } +} + + + static void dccg35_set_physymclk_root_clock_gating( struct dccg *dccg, int phy_inst, @@ -369,22 +451,32 @@ static void dccg35_set_physymclk_root_clock_gating( case 0: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYA_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 1: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYB_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 2: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYC_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 3: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYD_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 4: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYE_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; default: BREAK_TO_DEBUGGER(); @@ -407,10 +499,16 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, 1, PHYASYMCLK_SRC_SEL, clk_src); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYA_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, 0, PHYASYMCLK_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYA_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 1: @@ -418,10 +516,16 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, 1, PHYBSYMCLK_SRC_SEL, clk_src); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYB_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, 0, PHYBSYMCLK_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYB_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 2: @@ -429,10 +533,16 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, 1, PHYCSYMCLK_SRC_SEL, clk_src); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYC_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, 0, PHYCSYMCLK_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYC_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 3: @@ -440,10 +550,16 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, 1, PHYDSYMCLK_SRC_SEL, clk_src); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYD_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, 0, PHYDSYMCLK_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYD_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 4: @@ -451,10 +567,16 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, 1, PHYESYMCLK_SRC_SEL, clk_src); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYE_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, 0, PHYESYMCLK_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, +// PHYE_REFCLK_ROOT_GATE_DISABLE, 1); } break; default: @@ -491,12 +613,12 @@ static void dccg35_dpp_root_clock_control( if (clock_on) { /* turn off the DTO and leave phase/modulo at max */ - dcn35_set_dppclk_enable(dccg, dpp_inst, 0); + dcn35_set_dppclk_enable(dccg, dpp_inst, 1); REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, DPPCLK0_DTO_PHASE, 0xFF, DPPCLK0_DTO_MODULO, 0xFF); } else { - dcn35_set_dppclk_enable(dccg, dpp_inst, 1); + dcn35_set_dppclk_enable(dccg, dpp_inst, 0); /* turn on the DTO to generate a 0hz clock */ REG_SET_2(DPPCLK_DTO_PARAM[dpp_inst], 0, DPPCLK0_DTO_PHASE, 0, @@ -575,18 +697,32 @@ void dccg35_init(struct dccg *dccg) dccg35_disable_symclk32_se(dccg, otg_inst); if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) - for (otg_inst = 0; otg_inst < 2; otg_inst++) + for (otg_inst = 0; otg_inst < 2; otg_inst++) { dccg31_disable_symclk32_le(dccg, otg_inst); + dccg31_set_symclk32_le_root_clock_gating(dccg, otg_inst, false); + } + +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// for (otg_inst = 0; otg_inst < 4; otg_inst++) +// dccg35_disable_symclk_se(dccg, otg_inst, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) - for (otg_inst = 0; otg_inst < 4; otg_inst++) - dccg314_set_dpstreamclk(dccg, REFCLK, otg_inst, + for (otg_inst = 0; otg_inst < 4; otg_inst++) { + dccg35_set_dpstreamclk(dccg, REFCLK, otg_inst, otg_inst); + dccg35_set_dpstreamclk_root_clock_gating(dccg, otg_inst, false); + } if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) for (otg_inst = 0; otg_inst < 5; otg_inst++) dccg35_set_physymclk_root_clock_gating(dccg, otg_inst, false); + + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) + for (otg_inst = 0; otg_inst < 4; otg_inst++) + dccg35_set_dppclk_root_clock_gating(dccg, otg_inst, 0); + /* dccg35_enable_global_fgcg_rep( dccg, dccg->ctx->dc->debug.enable_fine_grain_clock_gating.bits @@ -611,24 +747,32 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) DSCCLK0_DTO_PHASE, 0, DSCCLK0_DTO_MODULO, 0); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE_2(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, 0, DSCCLK1_DTO_MODULO, 0); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE_2(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, 0, DSCCLK2_DTO_MODULO, 0); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE_2(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, 0, DSCCLK3_DTO_MODULO, 0); REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1); break; default: BREAK_TO_DEBUGGER(); @@ -650,24 +794,32 @@ static void dccg35_disable_dscclk(struct dccg *dccg, REG_UPDATE_2(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, 0, DSCCLK0_DTO_MODULO, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 0); REG_UPDATE_2(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, 0, DSCCLK1_DTO_MODULO, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 0); REG_UPDATE_2(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, 0, DSCCLK2_DTO_MODULO, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, 0); REG_UPDATE_2(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, 0, DSCCLK3_DTO_MODULO, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 0); break; default: return; @@ -682,22 +834,32 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 1); break; } @@ -706,26 +868,36 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 1, SYMCLKA_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 1, SYMCLKB_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 1, SYMCLKC_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 1, SYMCLKD_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1); break; case 4: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 1, SYMCLKE_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1); break; } } @@ -786,26 +958,36 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 0, SYMCLKA_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 0, SYMCLKB_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 0, SYMCLKC_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 0, SYMCLKD_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 0, SYMCLKE_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0); break; } @@ -818,22 +1000,32 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 0); break; } } @@ -845,6 +1037,7 @@ static const struct dccg_funcs dccg35_funcs = { .get_dccg_ref_freq = dccg31_get_dccg_ref_freq, .dccg_init = dccg35_init, .set_dpstreamclk = dccg35_set_dpstreamclk, + .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, .enable_symclk32_se = dccg31_enable_symclk32_se, .disable_symclk32_se = dccg35_disable_symclk32_se, .enable_symclk32_le = dccg31_enable_symclk32_le, diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c index 81e349d5835b..20f810a6646c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c @@ -80,7 +80,6 @@ enum signal_type dcn35_get_dig_mode( default: return SIGNAL_TYPE_NONE; } - return SIGNAL_TYPE_NONE; } void dcn35_link_encoder_setup( @@ -119,7 +118,7 @@ void dcn35_link_encoder_setup( void dcn35_link_encoder_init(struct link_encoder *enc) { - enc32_hw_init(enc); + enc31_hw_init(enc); dcn35_link_encoder_set_fgcg(enc, enc->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dio); } @@ -184,6 +183,8 @@ void dcn35_link_encoder_construct( enc10->base.hpd_source = init_data->hpd_source; enc10->base.connector = init_data->connector; + if (enc10->base.connector.id == CONNECTOR_ID_USBC) + enc10->base.features.flags.bits.DP_IS_USB_C = 1; enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; @@ -238,8 +239,6 @@ void dcn35_link_encoder_construct( } enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; if (bp_funcs->get_connector_speed_cap_info) result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h index e1e560732a9d..d546a3676304 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.h @@ -37,7 +37,9 @@ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, HDCP_SOFT_RESET, mask_sh),\ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\ + LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_HDCP_CLOCK_ON, mask_sh),\ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\ LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\ LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \ @@ -114,7 +116,15 @@ LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\ LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\ LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\ - LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh) + LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, DISPCLK_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKA_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKB_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKC_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKD_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKE_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKF_G_HDCP_GATE_DIS, mask_sh),\ + LE_SF(DIO_CLK_CNTL, SYMCLKG_G_HDCP_GATE_DIS, mask_sh) void dcn35_link_encoder_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h index 499052329ebb..1212fcee38f2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.h @@ -28,7 +28,6 @@ #include "dcn30/dcn30_vpg.h" #include "dcn30/dcn30_afmt.h" #include "stream_encoder.h" -#include "dcn10/dcn10_link_encoder.h" #include "dcn20/dcn20_stream_encoder.h" /* Register bit field name change */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c index 339bf0c722dd..6293173ba2b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_hubbub.c @@ -111,7 +111,7 @@ static uint32_t convert_and_clamp( static bool hubbub35_program_stutter_z8_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { @@ -297,7 +297,7 @@ static void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub, static bool hubbub35_program_watermarks( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower) { diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 6d7a15dcf8a7..34adae7ab6e8 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -36,6 +36,7 @@ struct dc_dp_mst_stream_allocation_table; struct aux_payload; enum aux_return_code_type; +enum set_config_status; /* * Allocate memory accessible by the GPU @@ -200,7 +201,7 @@ int dm_helper_dmub_aux_transfer_sync( const struct dc_link *link, struct aux_payload *payload, enum aux_return_code_type *operation_result); -enum set_config_status; + int dm_helpers_dmub_set_config_sync(struct dc_context *ctx, const struct dc_link *link, struct set_config_cmd_payload *payload, diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h index d0eed3b4771e..9405c47ee2a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_services.h +++ b/drivers/gpu/drm/amd/display/dc/dm_services.h @@ -274,6 +274,16 @@ void dm_perf_trace_timestamp(const char *func_name, unsigned int line, struct dc #define PERF_TRACE() dm_perf_trace_timestamp(__func__, __LINE__, CTX) #define PERF_TRACE_CTX(__CTX) dm_perf_trace_timestamp(__func__, __LINE__, __CTX) +/* + * SMU message tracing + */ +void dm_trace_smu_msg(uint32_t msg_id, uint32_t param_in, struct dc_context *ctx); +void dm_trace_smu_delay(uint32_t delay, struct dc_context *ctx); + +#define TRACE_SMU_MSG(msg_id, param_in, ctx) dm_trace_smu_msg(msg_id, param_in, ctx) +#define TRACE_SMU_DELAY(response_delay, ctx) dm_trace_smu_delay(response_delay, ctx) + + /* * DMUB Interfaces */ diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c index 38ab9ad60ef8..74da9ebda016 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c @@ -1085,6 +1085,9 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc int minmum_z8_residency = dc->debug.minimum_z8_residency_time > 0 ? dc->debug.minimum_z8_residency_time : 1000; bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > (double)minmum_z8_residency; bool is_pwrseq0 = link->link_index == 0; + bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 || + link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr); + bool is_replay = link && link->replay_settings.replay_feature_enabled; /* Don't support multi-plane configurations */ if (stream_status->plane_count > 1) @@ -1092,8 +1095,8 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc if (is_pwrseq0 && context->bw_ctx.dml.vba.StutterPeriod > 5000.0) return DCN_ZSTATE_SUPPORT_ALLOW; - else if (is_pwrseq0 && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr) - return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; + else if (is_pwrseq0 && (is_psr || is_replay)) + return DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY; else return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW; } else { @@ -2369,7 +2372,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context, static struct _vcs_dpi_voltage_scaling_st construct_low_pstate_lvl(struct clk_limit_table *clk_table, unsigned int high_voltage_lvl) { - struct _vcs_dpi_voltage_scaling_st low_pstate_lvl; + struct _vcs_dpi_voltage_scaling_st low_pstate_lvl = {0}; int i; low_pstate_lvl.state = 1; @@ -2474,7 +2477,7 @@ void dcn201_populate_dml_writeback_from_context_fpu(struct dc *dc, int pipe_cnt, i, j; double max_calc_writeback_dispclk; double writeback_dispclk; - struct writeback_st dout_wb; + struct writeback_st dout_wb = {0}; dc_assert_fp_enabled(); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c index ccb4ad78f667..81f7b90849ce 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c @@ -260,7 +260,7 @@ void dcn30_fpu_populate_dml_writeback_from_context( int pipe_cnt, i, j; double max_calc_writeback_dispclk; double writeback_dispclk; - struct writeback_st dout_wb; + struct writeback_st dout_wb = {0}; dc_assert_fp_enabled(); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index e7f4a2d491cc..e0b52db2c210 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -3535,7 +3535,6 @@ static double TruncToValidBPP( return DesiredBPP; } } - return BPP_INVALID; } void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index deb6d162a2d5..59a902313200 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -485,6 +485,7 @@ void dcn31_calculate_wm_and_dlg_fp( { int i, pipe_idx, total_det = 0, active_hubp_count = 0; double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + uint32_t cstate_enter_plus_exit_z8_ns; dc_assert_fp_enabled(); @@ -504,6 +505,13 @@ void dcn31_calculate_wm_and_dlg_fp( pipes[0].clks_cfg.dcfclk_mhz = dcfclk; pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; + cstate_enter_plus_exit_z8_ns = + get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + if (get_stutter_period(&context->bw_ctx.dml, pipes, pipe_cnt) < dc->debug.minimum_z8_residency_time && + cstate_enter_plus_exit_z8_ns < dc->debug.minimum_z8_residency_time * 1000) + cstate_enter_plus_exit_z8_ns = dc->debug.minimum_z8_residency_time * 1000; + /* Set A: * All clocks min required * @@ -514,7 +522,7 @@ void dcn31_calculate_wm_and_dlg_fp( context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = cstate_enter_plus_exit_z8_ns; context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h index 8f9c8faed260..d2ae43a82ba5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h @@ -30,6 +30,7 @@ #define DCN3_15_DEFAULT_DET_SIZE 192 #define DCN3_15_MIN_COMPBUF_SIZE_KB 128 #define DCN3_16_DEFAULT_DET_SIZE 192 +#define DCN3_16_MIN_COMPBUF_SIZE_KB 128 void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes, int pipe_cnt); diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c index adea459e7d36..33cf824c5da1 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c @@ -3679,7 +3679,6 @@ static double TruncToValidBPP( return DesiredBPP; } } - return BPP_INVALID; } static noinline void CalculatePrefetchSchedulePerPlane( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c index fb21572750e8..21f637ae4add 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c @@ -310,7 +310,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; bool upscaled = false; const unsigned int max_allowed_vblank_nom = 1023; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c index 88e56889a68c..3242957d00c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c @@ -3788,7 +3788,6 @@ static double TruncToValidBPP( return DesiredBPP; } } - return BPP_INVALID; } static noinline void CalculatePrefetchSchedulePerPlane( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c index a0a65e099104..f6fe0a64beac 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c @@ -180,6 +180,9 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc = { .urgent_latency_adjustment_fabric_clock_reference_mhz = 3000, }; +static bool dcn32_apply_merge_split_flags_helper(struct dc *dc, struct dc_state *context, + bool *repopulate_pipes, int *split, bool *merge); + void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr) { /* defaults */ @@ -622,7 +625,7 @@ static bool dcn32_assign_subvp_pipe(struct dc *dc, * to combine this with SubVP can cause issues with the scheduling). * - Not TMZ surface */ - if (pipe->plane_state && !pipe->top_pipe && !dcn32_is_center_timing(pipe) && + if (pipe->plane_state && !pipe->top_pipe && !pipe->prev_odm_pipe && !dcn32_is_center_timing(pipe) && !(pipe->stream->timing.pix_clk_100hz / 10000 > DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ) && (!dcn32_is_psr_capable(pipe) || (context->stream_count == 1 && dc->caps.dmub_caps.subvp_psr)) && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_NONE && @@ -720,7 +723,7 @@ static bool dcn32_enough_pipes_for_subvp(struct dc *dc, struct dc_state *context */ static bool subvp_subvp_schedulable(struct dc *dc, struct dc_state *context) { - struct pipe_ctx *subvp_pipes[2]; + struct pipe_ctx *subvp_pipes[2] = {0}; struct dc_stream_state *phantom = NULL; uint32_t microschedule_lines = 0; uint32_t index = 0; @@ -1425,13 +1428,14 @@ static bool is_test_pattern_enabled( return false; } -static void dcn32_full_validate_bw_helper(struct dc *dc, +static bool dcn32_full_validate_bw_helper(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, int *vlevel, int *split, bool *merge, - int *pipe_cnt) + int *pipe_cnt, + bool *repopulate_pipes) { struct vba_vars_st *vba = &context->bw_ctx.dml.vba; unsigned int dc_pipe_idx = 0; @@ -1461,6 +1465,12 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, vba->VoltageLevel = *vlevel; } + /* Apply split and merge flags before checking for subvp */ + if (!dcn32_apply_merge_split_flags_helper(dc, context, repopulate_pipes, split, merge)) + return false; + memset(split, 0, MAX_PIPES * sizeof(int)); + memset(merge, 0, MAX_PIPES * sizeof(bool)); + /* Conditions for setting up phantom pipes for SubVP: * 1. Not force disable SubVP * 2. Full update (i.e. !fast_validate) @@ -1475,19 +1485,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported || dc->debug.force_subvp_mclk_switch)) { - dcn32_merge_pipes_for_subvp(dc, context); - memset(merge, 0, MAX_PIPES * sizeof(bool)); - vlevel_temp = *vlevel; - /* to re-initialize viewport after the pipe merge */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - - if (!pipe_ctx->plane_state || !pipe_ctx->stream) - continue; - - resource_build_scaling_params(pipe_ctx); - } while (!found_supported_config && dcn32_enough_pipes_for_subvp(dc, context) && dcn32_assign_subvp_pipe(dc, context, &dc_pipe_idx)) { @@ -1576,8 +1574,6 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, * add phantom pipes. If pipe split (ODM / MPC) is required, both the main * and phantom pipes will be split in the regular pipe splitting sequence. */ - memset(split, 0, MAX_PIPES * sizeof(int)); - memset(merge, 0, MAX_PIPES * sizeof(bool)); *vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, *vlevel, split, merge); vba->VoltageLevel = *vlevel; // Note: We can't apply the phantom pipes to hardware at this time. We have to wait @@ -1590,6 +1586,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc, try_odm_power_optimization_and_revalidate( dc, context, pipes, split, merge, vlevel, *pipe_cnt); + return true; } static bool is_dtbclk_required(struct dc *dc, struct dc_state *context) @@ -1929,106 +1926,23 @@ static bool dcn32_split_stream_for_mpc_or_odm( return true; } -bool dcn32_internal_validate_bw(struct dc *dc, - struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int *pipe_cnt_out, - int *vlevel_out, - bool fast_validate) +static bool dcn32_apply_merge_split_flags_helper( + struct dc *dc, + struct dc_state *context, + bool *repopulate_pipes, + int *split, + bool *merge) { - bool out = false; - bool repopulate_pipes = false; - int split[MAX_PIPES] = { 0 }; - bool merge[MAX_PIPES] = { false }; + int i, pipe_idx; bool newly_split[MAX_PIPES] = { false }; - int pipe_cnt, i, pipe_idx; - int vlevel = context->bw_ctx.dml.soc.num_states; struct vba_vars_st *vba = &context->bw_ctx.dml.vba; - dc_assert_fp_enabled(); - - ASSERT(pipes); - if (!pipes) - return false; - - // For each full update, remove all existing phantom pipes first - dc_state_remove_phantom_streams_and_planes(dc, context); - dc_state_release_phantom_streams_and_planes(dc, context); - - dc->res_pool->funcs->update_soc_for_wm_a(dc, context); - - pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); - - if (!pipe_cnt) { - out = true; - goto validate_out; - } - - dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); - context->bw_ctx.dml.soc.max_vratio_pre = dcn32_determine_max_vratio_prefetch(dc, context); - - if (!fast_validate) - dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt); - - if (fast_validate || - (dc->debug.dml_disallow_alternate_prefetch_modes && - (vlevel == context->bw_ctx.dml.soc.num_states || - vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported))) { - /* - * If dml_disallow_alternate_prefetch_modes is false, then we have already - * tried alternate prefetch modes during full validation. - * - * If mode is unsupported or there is no p-state support, then - * fall back to favouring voltage. - * - * If Prefetch mode 0 failed for this config, or passed with Max UCLK, then try - * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) - */ - context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = - dm_prefetch_support_none; - - context->bw_ctx.dml.validate_max_state = fast_validate; - vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); - - context->bw_ctx.dml.validate_max_state = false; - - if (vlevel < context->bw_ctx.dml.soc.num_states) { - memset(split, 0, sizeof(split)); - memset(merge, 0, sizeof(merge)); - vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); - // dcn20_validate_apply_pipe_split_flags can modify voltage level outside of DML - vba->VoltageLevel = vlevel; - } - } - - dml_log_mode_support_params(&context->bw_ctx.dml); - - if (vlevel == context->bw_ctx.dml.soc.num_states) - goto validate_fail; - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; - - if (!pipe->stream) - continue; - - if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled - && !dc->config.enable_windowed_mpo_odm - && pipe->plane_state && mpo_pipe - && memcmp(&mpo_pipe->plane_state->clip_rect, - &pipe->stream->src, - sizeof(struct rect)) != 0) { - ASSERT(mpo_pipe->plane_state != pipe->plane_state); - goto validate_fail; - } - pipe_idx++; - } - if (dc->config.enable_windowed_mpo_odm) { - repopulate_pipes = update_pipes_with_split_flags( - dc, context, vba, split, merge); + if (update_pipes_with_split_flags( + dc, context, vba, split, merge)) + *repopulate_pipes = true; } else { + /* the code below will be removed once windowed mpo odm is fully * enabled. */ @@ -2085,7 +1999,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); memset(&pipe->link_res, 0, sizeof(pipe->link_res)); - repopulate_pipes = true; + *repopulate_pipes = true; } else if (pipe->top_pipe && pipe->top_pipe->plane_state == pipe->plane_state) { struct pipe_ctx *top_pipe = pipe->top_pipe; struct pipe_ctx *bottom_pipe = pipe->bottom_pipe; @@ -2101,7 +2015,7 @@ bool dcn32_internal_validate_bw(struct dc *dc, memset(&pipe->plane_res, 0, sizeof(pipe->plane_res)); memset(&pipe->stream_res, 0, sizeof(pipe->stream_res)); memset(&pipe->link_res, 0, sizeof(pipe->link_res)); - repopulate_pipes = true; + *repopulate_pipes = true; } else ASSERT(0); /* Should never try to merge master pipe */ @@ -2140,15 +2054,15 @@ bool dcn32_internal_validate_bw(struct dc *dc, hsplit_pipe = dcn32_find_split_pipe(dc, context, old_index); ASSERT(hsplit_pipe); if (!hsplit_pipe) - goto validate_fail; + return false; if (!dcn32_split_stream_for_mpc_or_odm( dc, &context->res_ctx, pipe, hsplit_pipe, odm)) - goto validate_fail; + return false; newly_split[hsplit_pipe->pipe_idx] = true; - repopulate_pipes = true; + *repopulate_pipes = true; } if (split[i] == 4) { struct pipe_ctx *pipe_4to1; @@ -2163,11 +2077,11 @@ bool dcn32_internal_validate_bw(struct dc *dc, pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) - goto validate_fail; + return false; if (!dcn32_split_stream_for_mpc_or_odm( dc, &context->res_ctx, pipe, pipe_4to1, odm)) - goto validate_fail; + return false; newly_split[pipe_4to1->pipe_idx] = true; if (odm && old_pipe->next_odm_pipe && old_pipe->next_odm_pipe->next_odm_pipe @@ -2182,11 +2096,11 @@ bool dcn32_internal_validate_bw(struct dc *dc, pipe_4to1 = dcn32_find_split_pipe(dc, context, old_index); ASSERT(pipe_4to1); if (!pipe_4to1) - goto validate_fail; + return false; if (!dcn32_split_stream_for_mpc_or_odm( dc, &context->res_ctx, hsplit_pipe, pipe_4to1, odm)) - goto validate_fail; + return false; newly_split[pipe_4to1->pipe_idx] = true; } if (odm) @@ -2198,10 +2112,121 @@ bool dcn32_internal_validate_bw(struct dc *dc, if (pipe->plane_state) { if (!resource_build_scaling_params(pipe)) - goto validate_fail; + return false; } } + + for (i = 0; i < context->stream_count; i++) { + struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(&context->res_ctx, + context->streams[i]); + + if (otg_master) + resource_build_test_pattern_params(&context->res_ctx, otg_master); + } } + return true; +} + +bool dcn32_internal_validate_bw(struct dc *dc, + struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int *pipe_cnt_out, + int *vlevel_out, + bool fast_validate) +{ + bool out = false; + bool repopulate_pipes = false; + int split[MAX_PIPES] = { 0 }; + bool merge[MAX_PIPES] = { false }; + int pipe_cnt, i, pipe_idx; + int vlevel = context->bw_ctx.dml.soc.num_states; + struct vba_vars_st *vba = &context->bw_ctx.dml.vba; + + dc_assert_fp_enabled(); + + ASSERT(pipes); + if (!pipes) + return false; + + /* For each full update, remove all existing phantom pipes first */ + dc_state_remove_phantom_streams_and_planes(dc, context); + dc_state_release_phantom_streams_and_planes(dc, context); + + dc->res_pool->funcs->update_soc_for_wm_a(dc, context); + + pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate); + + if (!pipe_cnt) { + out = true; + goto validate_out; + } + + dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt); + context->bw_ctx.dml.soc.max_vratio_pre = dcn32_determine_max_vratio_prefetch(dc, context); + + if (!fast_validate) { + if (!dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, + &pipe_cnt, &repopulate_pipes)) + goto validate_fail; + } + + if (fast_validate || + (dc->debug.dml_disallow_alternate_prefetch_modes && + (vlevel == context->bw_ctx.dml.soc.num_states || + vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported))) { + /* + * If dml_disallow_alternate_prefetch_modes is false, then we have already + * tried alternate prefetch modes during full validation. + * + * If mode is unsupported or there is no p-state support, then + * fall back to favouring voltage. + * + * If Prefetch mode 0 failed for this config, or passed with Max UCLK, then try + * to support with Prefetch mode 1 (dm_prefetch_support_fclk_and_stutter == 2) + */ + context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final = + dm_prefetch_support_none; + + context->bw_ctx.dml.validate_max_state = fast_validate; + vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt); + + context->bw_ctx.dml.validate_max_state = false; + + if (vlevel < context->bw_ctx.dml.soc.num_states) { + memset(split, 0, sizeof(split)); + memset(merge, 0, sizeof(merge)); + vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge); + /* dcn20_validate_apply_pipe_split_flags can modify voltage level outside of DML */ + vba->VoltageLevel = vlevel; + } + } + + dml_log_mode_support_params(&context->bw_ctx.dml); + + if (vlevel == context->bw_ctx.dml.soc.num_states) + goto validate_fail; + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *mpo_pipe = pipe->bottom_pipe; + + if (!pipe->stream) + continue; + + if (vba->ODMCombineEnabled[vba->pipe_plane[pipe_idx]] != dm_odm_combine_mode_disabled + && !dc->config.enable_windowed_mpo_odm + && pipe->plane_state && mpo_pipe + && memcmp(&mpo_pipe->plane_state->clip_rect, + &pipe->stream->src, + sizeof(struct rect)) != 0) { + ASSERT(mpo_pipe->plane_state != pipe->plane_state); + goto validate_fail; + } + pipe_idx++; + } + + if (!dcn32_apply_merge_split_flags_helper(dc, context, &repopulate_pipes, split, merge)) + goto validate_fail; /* Actual dsc count per stream dsc validation*/ if (!dcn20_validate_dsc(dc, context)) { diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c index 80fccd4999a5..ba1310c8fd77 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c @@ -1650,6 +1650,8 @@ double dml32_TruncToValidBPP( MaxLinkBPP = 2 * MaxLinkBPP; } + *RequiredSlots = dml_ceil(DesiredBPP / MaxLinkBPP * 64, 1); + if (DesiredBPP == 0) { if (DSCEnable) { if (MaxLinkBPP < MinDSCBPP) @@ -1676,10 +1678,6 @@ double dml32_TruncToValidBPP( else return DesiredBPP; } - - *RequiredSlots = dml_ceil(DesiredBPP / MaxLinkBPP * 64, 1); - - return BPP_INVALID; } // TruncToValidBPP double dml32_RequiredDTBCLK( @@ -1975,8 +1973,8 @@ void dml32_CalculateVMRowAndSwath( unsigned int PTEBufferSizeInRequestsForChroma[DC__NUM_DPP__MAX]; unsigned int PDEAndMetaPTEBytesFrameY; unsigned int PDEAndMetaPTEBytesFrameC; - unsigned int MetaRowByteY[DC__NUM_DPP__MAX]; - unsigned int MetaRowByteC[DC__NUM_DPP__MAX]; + unsigned int MetaRowByteY[DC__NUM_DPP__MAX] = {0}; + unsigned int MetaRowByteC[DC__NUM_DPP__MAX] = {0}; unsigned int PixelPTEBytesPerRowY[DC__NUM_DPP__MAX]; unsigned int PixelPTEBytesPerRowC[DC__NUM_DPP__MAX]; unsigned int PixelPTEBytesPerRowY_one_row_per_frame[DC__NUM_DPP__MAX]; @@ -4291,7 +4289,7 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( unsigned int i, j, k; unsigned int SurfaceWithMinActiveFCLKChangeMargin = 0; unsigned int DRAMClockChangeSupportNumber = 0; - unsigned int LastSurfaceWithoutMargin; + unsigned int LastSurfaceWithoutMargin = 0; unsigned int DRAMClockChangeMethod = 0; bool FoundFirstSurfaceWithMinActiveFCLKChangeMargin = false; double MinActiveFCLKChangeMargin = 0.; @@ -5656,9 +5654,9 @@ void dml32_CalculateStutterEfficiency( double LastZ8StutterPeriod = 0.0; double LastStutterPeriod = 0.0; unsigned int TotalNumberOfActiveOTG = 0; - double doublePixelClock; - unsigned int doubleHTotal; - unsigned int doubleVTotal; + double doublePixelClock = 0; + unsigned int doubleHTotal = 0; + unsigned int doubleVTotal = 0; bool SameTiming = true; double DETBufferingTimeY; double SwathWidthYCriticalSurface = 0.0; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 21e0eef3269b..add169162f2a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -439,7 +439,7 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc, { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; bool upscaled = false; const unsigned int max_allowed_vblank_nom = 1023; @@ -577,6 +577,7 @@ void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context) { enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW; unsigned int i, plane_count = 0; + DC_LOGGER_INIT(dc->ctx->logger); for (i = 0; i < dc->res_pool->pipe_count; i++) { if (context->res_ctx.pipe_ctx[i].plane_state) @@ -602,11 +603,14 @@ void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context) if (is_pwrseq0 && allow_z10) support = DCN_ZSTATE_SUPPORT_ALLOW; else if (is_pwrseq0 && (is_psr || is_replay)) - support = allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY : DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY; + support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY; else if (allow_z8) support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY; } + DC_LOG_SMU("zstate_support: %d, StutterPeriod: %d\n", support, + (int)context->bw_ctx.dml.vba.StutterPeriod); + context->bw_ctx.bw.dcn.clk.zstate_support = support; } diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c index b3ffab77cf88..e4f333d4fb54 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c @@ -237,7 +237,6 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_51_soc = { .urgent_latency_adjustment_fabric_clock_component_us = 0, .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, .num_chans = 4, - .dram_clock_change_latency_us = 11.72, .dispclk_dppclk_vco_speed_mhz = 2400.0, }; @@ -474,7 +473,7 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc, { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; bool upscaled = false; const unsigned int max_allowed_vblank_nom = 1023; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile index acff3449b8d7..1c9498a72520 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile @@ -67,6 +67,7 @@ frame_warn_flag := -Wframe-larger-than=2048 endif endif +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2 CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_wrapper.o := $(dml2_ccflags) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c index 9be5ebf3a8c0..3e919f5c00ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c @@ -31,6 +31,8 @@ #include "dml_assert.h" #define DML2_MAX_FMT_420_BUFFER_WIDTH 4096 +#define TB_BORROWED_MAX 400 + // --------------------------- // Declaration Begins // --------------------------- @@ -2782,6 +2784,8 @@ static dml_float_t TruncToValidBPP( } } + *RequiredSlots = (dml_uint_t)(dml_ceil(DesiredBPP / MaxLinkBPP * 64, 1)); + if (DesiredBPP == 0) { if (DSCEnable) { if (MaxLinkBPP < MinDSCBPP) { @@ -2810,10 +2814,6 @@ static dml_float_t TruncToValidBPP( return DesiredBPP; } } - - *RequiredSlots = (dml_uint_t)(dml_ceil(DesiredBPP / MaxLinkBPP * 64, 1)); - - return __DML_DPP_INVALID__; } // TruncToValidBPP static void CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( @@ -3790,9 +3790,9 @@ static void CalculateStutterEfficiency(struct display_mode_lib_scratch_st *scrat dml_bool_t FoundCriticalSurface = false; dml_uint_t TotalNumberOfActiveOTG = 0; - dml_float_t SinglePixelClock; - dml_uint_t SingleHTotal; - dml_uint_t SingleVTotal; + dml_float_t SinglePixelClock = 0; + dml_uint_t SingleHTotal = 0; + dml_uint_t SingleVTotal = 0; dml_bool_t SameTiming = true; dml_float_t LastStutterPeriod = 0.0; @@ -9460,8 +9460,10 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc /* Copy the calculated watermarks to mp.Watermark as the getter functions are * implemented by the DML team to copy the calculated values from the mp.Watermark interface. + * &mode_lib->mp.Watermark and &locals->Watermark are the same address, memcpy may lead to + * unexpected behavior. memmove should be used. */ - memcpy(&mode_lib->mp.Watermark, CalculateWatermarks_params->Watermark, sizeof(struct Watermarks)); + memmove(&mode_lib->mp.Watermark, CalculateWatermarks_params->Watermark, sizeof(struct Watermarks)); for (k = 0; k < mode_lib->ms.num_active_planes; ++k) { if (mode_lib->ms.cache_display_cfg.writeback.WritebackEnable[k] == true) { @@ -10214,6 +10216,7 @@ dml_get_var_func(fraction_of_urgent_bandwidth_imm_flip, dml_float_t, mode_lib->m dml_get_var_func(urgent_latency, dml_float_t, mode_lib->mp.UrgentLatency); dml_get_var_func(clk_dcf_deepsleep, dml_float_t, mode_lib->mp.DCFCLKDeepSleep); dml_get_var_func(wm_writeback_dram_clock_change, dml_float_t, mode_lib->mp.Watermark.WritebackDRAMClockChangeWatermark); +dml_get_var_func(wm_writeback_urgent, dml_float_t, mode_lib->mp.Watermark.WritebackUrgentWatermark); dml_get_var_func(stutter_efficiency, dml_float_t, mode_lib->mp.StutterEfficiency); dml_get_var_func(stutter_efficiency_no_vblank, dml_float_t, mode_lib->mp.StutterEfficiencyNotIncludingVBlank); dml_get_var_func(stutter_efficiency_z8, dml_float_t, mode_lib->mp.Z8StutterEfficiency); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.h b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.h index 8452485684f5..3116b88e99dc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.h @@ -94,6 +94,7 @@ dml_get_var_decl(wm_usr_retraining, dml_float_t); dml_get_var_decl(urgent_latency, dml_float_t); dml_get_var_decl(wm_writeback_dram_clock_change, dml_float_t); +dml_get_var_decl(wm_writeback_urgent, dml_float_t); dml_get_var_decl(stutter_efficiency_no_vblank, dml_float_t); dml_get_var_decl(stutter_efficiency, dml_float_t); dml_get_var_decl(stutter_efficiency_z8, dml_float_t); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_lib_defines.h b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_lib_defines.h index de63364be01d..14d389525296 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_lib_defines.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_lib_defines.h @@ -41,6 +41,7 @@ #define DCN_DML__VM_PRESENT__1 1 #define DCN_DML__HOST_VM_PRESENT 1 #define DCN_DML__HOST_VM_PRESENT__1 1 +#define DCN_DML__DWB 1 #include "dml_depedencies.h" @@ -59,6 +60,7 @@ #define __DML_NUM_PLANES__ DCN_DML__NUM_PLANE #define __DML_NUM_CURSORS__ DCN_DML__NUM_CURSOR #define __DML_DPP_INVALID__ 0 +#define __DML_NUM_DMB__ DCN_DML__DWB #define __DML_PIPE_NO_PLANE__ 99 #define __DML_MAX_STATE_ARRAY_SIZE__ DCN_DML__NUM_PWR_STATE diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index a52c594e1ba4..ad2a6b4769fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -88,7 +88,8 @@ static int find_disp_cfg_idx_by_plane_id(struct dml2_dml_to_dc_pipe_mapping *map return i; } - return -1; + ASSERT(false); + return __DML2_WRAPPER_MAX_STREAMS_PLANES__; } static int find_disp_cfg_idx_by_stream_id(struct dml2_dml_to_dc_pipe_mapping *mapping, unsigned int stream_id) @@ -100,7 +101,8 @@ static int find_disp_cfg_idx_by_stream_id(struct dml2_dml_to_dc_pipe_mapping *ma return i; } - return -1; + ASSERT(false); + return __DML2_WRAPPER_MAX_STREAMS_PLANES__; } // The master pipe of a stream is defined as the top pipe in odm slice 0 @@ -793,8 +795,8 @@ static void map_pipes_for_plane(struct dml2_context *ctx, struct dc_state *state free_unused_pipes_for_plane(ctx, state, plane, &scratch->pipe_pool, stream->stream_id, plane_index); } -static unsigned int get_mpc_factor(struct dml2_context *ctx, - const struct dc_state *state, +static unsigned int get_target_mpc_factor(struct dml2_context *ctx, + struct dc_state *state, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, const struct dc_stream_status *status, @@ -805,10 +807,10 @@ static unsigned int get_mpc_factor(struct dml2_context *ctx, unsigned int cfg_idx; unsigned int mpc_factor; - get_plane_id(ctx, state, status->plane_states[plane_idx], - stream->stream_id, plane_idx, &plane_id); - cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id); if (ctx->architecture == dml2_architecture_20) { + get_plane_id(ctx, state, status->plane_states[plane_idx], + stream->stream_id, plane_idx, &plane_id); + cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id); mpc_factor = (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx]; } else { mpc_factor = 1; @@ -822,16 +824,18 @@ static unsigned int get_mpc_factor(struct dml2_context *ctx, return mpc_factor; } -static unsigned int get_odm_factor( +static unsigned int get_target_odm_factor( const struct dml2_context *ctx, + struct dc_state *state, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, const struct dc_stream_state *stream) { - unsigned int cfg_idx = find_disp_cfg_idx_by_stream_id( - mapping, stream->stream_id); + unsigned int cfg_idx; - if (ctx->architecture == dml2_architecture_20) + if (ctx->architecture == dml2_architecture_20) { + cfg_idx = find_disp_cfg_idx_by_stream_id( + mapping, stream->stream_id); switch (disp_cfg->hw.ODMMode[cfg_idx]) { case dml_odm_mode_bypass: return 1; @@ -842,42 +846,94 @@ static unsigned int get_odm_factor( default: break; } + } ASSERT(false); return 1; } +static unsigned int get_source_odm_factor(const struct dml2_context *ctx, + struct dc_state *state, + const struct dc_stream_state *stream) +{ + struct pipe_ctx *otg_master = ctx->config.callbacks.get_otg_master_for_stream(&state->res_ctx, stream); + + return ctx->config.callbacks.get_odm_slice_count(otg_master); +} + +static unsigned int get_source_mpc_factor(const struct dml2_context *ctx, + struct dc_state *state, + const struct dc_plane_state *plane) +{ + struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0}; + int dpp_pipe_count = ctx->config.callbacks.get_dpp_pipes_for_plane(plane, + &state->res_ctx, dpp_pipes); + + ASSERT(dpp_pipe_count > 0); + return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]); +} + + static void populate_mpc_factors_for_stream( struct dml2_context *ctx, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, - const struct dc_state *state, + struct dc_state *state, unsigned int stream_idx, - unsigned int odm_factor, - unsigned int mpc_factors[MAX_PIPES]) + struct dml2_pipe_combine_factor odm_factor, + struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES]) { const struct dc_stream_status *status = &state->stream_status[stream_idx]; int i; - for (i = 0; i < status->plane_count; i++) - if (odm_factor == 1) - mpc_factors[i] = get_mpc_factor( - ctx, state, disp_cfg, mapping, status, - state->streams[stream_idx], i); - else - mpc_factors[i] = 1; + for (i = 0; i < status->plane_count; i++) { + mpc_factors[i].source = get_source_mpc_factor(ctx, state, status->plane_states[i]); + mpc_factors[i].target = (odm_factor.target == 1) ? + get_target_mpc_factor(ctx, state, disp_cfg, mapping, status, state->streams[stream_idx], i) : 1; + } } static void populate_odm_factors(const struct dml2_context *ctx, const struct dml_display_cfg_st *disp_cfg, struct dml2_dml_to_dc_pipe_mapping *mapping, - const struct dc_state *state, - unsigned int odm_factors[MAX_PIPES]) + struct dc_state *state, + struct dml2_pipe_combine_factor odm_factors[MAX_PIPES]) { int i; - for (i = 0; i < state->stream_count; i++) - odm_factors[i] = get_odm_factor( - ctx, disp_cfg, mapping, state->streams[i]); + for (i = 0; i < state->stream_count; i++) { + odm_factors[i].source = get_source_odm_factor(ctx, state, state->streams[i]); + odm_factors[i].target = get_target_odm_factor( + ctx, state, disp_cfg, mapping, state->streams[i]); + } +} + +static bool unmap_dc_pipes_for_stream(struct dml2_context *ctx, + struct dc_state *state, + const struct dc_state *existing_state, + const struct dc_stream_state *stream, + const struct dc_stream_status *status, + struct dml2_pipe_combine_factor odm_factor, + struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES]) +{ + int plane_idx; + bool result = true; + + for (plane_idx = 0; plane_idx < status->plane_count; plane_idx++) + if (mpc_factors[plane_idx].target < mpc_factors[plane_idx].source) + result &= ctx->config.callbacks.update_pipes_for_plane_with_slice_count( + state, + existing_state, + ctx->config.callbacks.dc->res_pool, + status->plane_states[plane_idx], + mpc_factors[plane_idx].target); + if (odm_factor.target < odm_factor.source) + result &= ctx->config.callbacks.update_pipes_for_stream_with_slice_count( + state, + existing_state, + ctx->config.callbacks.dc->res_pool, + stream, + odm_factor.target); + return result; } static bool map_dc_pipes_for_stream(struct dml2_context *ctx, @@ -885,40 +941,27 @@ static bool map_dc_pipes_for_stream(struct dml2_context *ctx, const struct dc_state *existing_state, const struct dc_stream_state *stream, const struct dc_stream_status *status, - unsigned int odm_factor, - unsigned int mpc_factors[MAX_PIPES]) + struct dml2_pipe_combine_factor odm_factor, + struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES]) { int plane_idx; bool result = true; - if (odm_factor == 1) - /* - * ODM and MPC combines are by DML design mutually exclusive. - * ODM factor of 1 means MPC factors may be greater than 1. - * In this case, we want to set ODM factor to 1 first to free up - * pipe resources from previous ODM configuration before setting - * up MPC combine to acquire more pipe resources. - */ - result &= ctx->config.callbacks.update_pipes_for_stream_with_slice_count( - state, - existing_state, - ctx->config.callbacks.dc->res_pool, - stream, - odm_factor); for (plane_idx = 0; plane_idx < status->plane_count; plane_idx++) - result &= ctx->config.callbacks.update_pipes_for_plane_with_slice_count( - state, - existing_state, - ctx->config.callbacks.dc->res_pool, - status->plane_states[plane_idx], - mpc_factors[plane_idx]); - if (odm_factor > 1) + if (mpc_factors[plane_idx].target > mpc_factors[plane_idx].source) + result &= ctx->config.callbacks.update_pipes_for_plane_with_slice_count( + state, + existing_state, + ctx->config.callbacks.dc->res_pool, + status->plane_states[plane_idx], + mpc_factors[plane_idx].target); + if (odm_factor.target > odm_factor.source) result &= ctx->config.callbacks.update_pipes_for_stream_with_slice_count( state, existing_state, ctx->config.callbacks.dc->res_pool, stream, - odm_factor); + odm_factor.target); return result; } @@ -928,20 +971,20 @@ static bool map_dc_pipes_with_callbacks(struct dml2_context *ctx, struct dml2_dml_to_dc_pipe_mapping *mapping, const struct dc_state *existing_state) { - unsigned int odm_factors[MAX_PIPES]; - unsigned int mpc_factors_for_stream[MAX_PIPES]; int i; bool result = true; - populate_odm_factors(ctx, disp_cfg, mapping, state, odm_factors); - for (i = 0; i < state->stream_count; i++) { + populate_odm_factors(ctx, disp_cfg, mapping, state, ctx->pipe_combine_scratch.odm_factors); + for (i = 0; i < state->stream_count; i++) populate_mpc_factors_for_stream(ctx, disp_cfg, mapping, state, - i, odm_factors[i], mpc_factors_for_stream); - result &= map_dc_pipes_for_stream(ctx, state, existing_state, - state->streams[i], - &state->stream_status[i], - odm_factors[i], mpc_factors_for_stream); - } + i, ctx->pipe_combine_scratch.odm_factors[i], ctx->pipe_combine_scratch.mpc_factors[i]); + for (i = 0; i < state->stream_count; i++) + result &= unmap_dc_pipes_for_stream(ctx, state, existing_state, state->streams[i], + &state->stream_status[i], ctx->pipe_combine_scratch.odm_factors[i], ctx->pipe_combine_scratch.mpc_factors[i]); + for (i = 0; i < state->stream_count; i++) + result &= map_dc_pipes_for_stream(ctx, state, existing_state, state->streams[i], + &state->stream_status[i], ctx->pipe_combine_scratch.odm_factors[i], ctx->pipe_combine_scratch.mpc_factors[i]); + return result; } @@ -1037,6 +1080,12 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s ASSERT(false); } } + + if (ctx->config.callbacks.build_test_pattern_params && + pipe->stream && + pipe->prev_odm_pipe == NULL && + pipe->top_pipe == NULL) + ctx->config.callbacks.build_test_pattern_params(&state->res_ctx, pipe); } return true; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h index 2f91244a7b01..1538b708d8be 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h @@ -30,6 +30,8 @@ #include "dml2_dc_types.h" struct dml2_context; +struct dml2_dml_to_dc_pipe_mapping; +struct dml_display_cfg_st; /* * dml2_map_dc_pipes - Creates a pipe linkage in dc_state based on current display config. diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h index 1cf8a884c0fb..9dab4e43c511 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h @@ -109,10 +109,21 @@ enum dml2_architecture { dml2_architecture_20, }; +struct dml2_pipe_combine_factor { + unsigned int source; + unsigned int target; +}; + +struct dml2_pipe_combine_scratch { + struct dml2_pipe_combine_factor odm_factors[MAX_PIPES]; + struct dml2_pipe_combine_factor mpc_factors[MAX_PIPES][MAX_PIPES]; +}; + struct dml2_context { enum dml2_architecture architecture; struct dml2_configuration_options config; struct dml2_helper_det_policy_scratch det_helper_scratch; + struct dml2_pipe_combine_scratch pipe_combine_scratch; union { struct { struct display_mode_lib_st dml_core_ctx; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index a20f28a5d2e7..a41812598ce8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -29,6 +29,7 @@ #include "dml2_translation_helper.h" #define NUM_DCFCLK_STAS 5 +#define NUM_DCFCLK_STAS_NEW 8 void dml2_init_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out) { @@ -249,12 +250,21 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, { struct dml2_policy_build_synthetic_soc_states_scratch *s = &dml2->v20.scratch.create_scratch.build_synthetic_socbb_scratch; struct dml2_policy_build_synthetic_soc_states_params *p = &dml2->v20.scratch.build_synthetic_socbb_params; - unsigned int dcfclk_stas_mhz[NUM_DCFCLK_STAS]; + unsigned int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0}; + unsigned int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0}; + unsigned int dml_project = dml2->v20.dml_core_ctx.project; + unsigned int i = 0; unsigned int transactions_per_mem_clock = 16; // project specific, depends on used Memory type - p->dcfclk_stas_mhz = dcfclk_stas_mhz; - p->num_dcfclk_stas = NUM_DCFCLK_STAS; + if (dml_project == dml_project_dcn351) { + p->dcfclk_stas_mhz = dcfclk_stas_mhz_new; + p->num_dcfclk_stas = NUM_DCFCLK_STAS_NEW; + } else { + p->dcfclk_stas_mhz = dcfclk_stas_mhz; + p->num_dcfclk_stas = NUM_DCFCLK_STAS; + } + p->in_bbox = in_bbox; p->out_states = out; p->in_states = &dml2->v20.scratch.create_scratch.in_states; @@ -432,8 +442,7 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, } dml2_policy_build_synthetic_soc_states(s, p); - if (dml2->v20.dml_core_ctx.project == dml_project_dcn35 || - dml2->v20.dml_core_ctx.project == dml_project_dcn351) { + if (dml2->v20.dml_core_ctx.project == dml_project_dcn35) { // Override last out_state with data from last in_state // This will ensure that out_state contains max fclk memcpy(&p->out_states->state_array[p->out_states->num_states - 1], @@ -1052,7 +1061,46 @@ static void dml2_populate_pipe_to_plane_index_mapping(struct dml2_context *dml2, plane_index = 0; } } +static void populate_dml_writeback_cfg_from_stream_state(struct dml_writeback_cfg_st *out, + unsigned int location, const struct dc_stream_state *in) +{ + if (in->num_wb_info > 0) { + for (int i = 0; i < __DML_NUM_DMB__; i++) { + const struct dc_writeback_info *wb_info = &in->writeback_info[i]; + /*current dml support 1 dwb per stream, limitation*/ + if (wb_info->wb_enabled) { + out->WritebackEnable[location] = wb_info->wb_enabled; + out->ActiveWritebacksPerSurface[location] = wb_info->dwb_params.cnv_params.src_width; + out->WritebackDestinationWidth[location] = wb_info->dwb_params.dest_width; + out->WritebackDestinationHeight[location] = wb_info->dwb_params.dest_height; + out->WritebackSourceWidth[location] = wb_info->dwb_params.cnv_params.crop_en ? + wb_info->dwb_params.cnv_params.crop_width : + wb_info->dwb_params.cnv_params.src_width; + + out->WritebackSourceHeight[location] = wb_info->dwb_params.cnv_params.crop_en ? + wb_info->dwb_params.cnv_params.crop_height : + wb_info->dwb_params.cnv_params.src_height; + /*current design does not have chroma scaling, need to follow up*/ + out->WritebackHTaps[location] = wb_info->dwb_params.scaler_taps.h_taps > 0 ? + wb_info->dwb_params.scaler_taps.h_taps : 1; + out->WritebackVTaps[location] = wb_info->dwb_params.scaler_taps.v_taps > 0 ? + wb_info->dwb_params.scaler_taps.v_taps : 1; + + out->WritebackHRatio[location] = wb_info->dwb_params.cnv_params.crop_en ? + (double)wb_info->dwb_params.cnv_params.crop_width / + (double)wb_info->dwb_params.dest_width : + (double)wb_info->dwb_params.cnv_params.src_width / + (double)wb_info->dwb_params.dest_width; + out->WritebackVRatio[location] = wb_info->dwb_params.cnv_params.crop_en ? + (double)wb_info->dwb_params.cnv_params.crop_height / + (double)wb_info->dwb_params.dest_height : + (double)wb_info->dwb_params.cnv_params.src_height / + (double)wb_info->dwb_params.dest_height; + } + } + } +} void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg) { int i = 0, j = 0, k = 0; @@ -1097,6 +1145,10 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]); populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context); + /*Call site for populate_dml_writeback_cfg_from_stream_state*/ + populate_dml_writeback_cfg_from_stream_state(&dml_dispcfg->writeback, + disp_cfg_stream_location, context->streams[i]); + switch (context->streams[i]->debug.force_odm_combine_segments) { case 2: dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_stream_location] = dml_odm_use_policy_combine_2to1; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c index f15d1dbad6a9..0f8b3336e26d 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c @@ -224,7 +224,7 @@ static int find_dml_pipe_idx_by_plane_id(struct dml2_context *ctx, unsigned int static bool get_plane_id(struct dml2_context *dml2, const struct dc_state *state, const struct dc_plane_state *plane, unsigned int stream_id, unsigned int plane_index, unsigned int *plane_id) { - int i, j; + unsigned int i, j; bool is_plane_duplicate = dml2->v20.scratch.plane_duplicate_exists; if (!plane_id) @@ -327,6 +327,8 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id); } + if (dml_pipe_idx == 0xFFFFFFFF) + continue; ASSERT(in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id_valid[dml_pipe_idx]); ASSERT(in_ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_stream_id[dml_pipe_idx] == context->res_ctx.pipe_ctx[dc_pipe_ctx_index].stream->stream_id); @@ -374,10 +376,16 @@ void dml2_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *cont context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz; context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz; + context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v20.dml_core_ctx.states.state_array[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx].dppclk_mhz * 1000; context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v20.dml_core_ctx.states.state_array[in_ctx->v20.scratch.mode_support_params.out_lowest_state_idx].dispclk_mhz * 1000; + + if (dc->config.forced_clocks || dc->debug.max_disp_clk) { + context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz; + context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz ; + } } void dml2_extract_watermark_set(struct dcn_watermarks *watermark, struct display_mode_lib_st *dml_core_ctx) @@ -396,6 +404,71 @@ void dml2_extract_watermark_set(struct dcn_watermarks *watermark, struct display watermark->cstate_pstate.cstate_exit_z8_ns = dml_get_wm_z8_stutter(dml_core_ctx) * 1000; } +unsigned int dml2_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark) +{ + unsigned int time_per_byte = 0; + unsigned int total_free_entry = 0xb40; + unsigned int buf_lh_capability; + unsigned int max_scaled_time; + + if (mode == PACKED_444) /* packed mode 32 bpp */ + time_per_byte = time_per_pixel/4; + else if (mode == PACKED_444_FP16) /* packed mode 64 bpp */ + time_per_byte = time_per_pixel/8; + + if (time_per_byte == 0) + time_per_byte = 1; + + buf_lh_capability = (total_free_entry*time_per_byte*32) >> 6; /* time_per_byte is in u6.6*/ + max_scaled_time = buf_lh_capability - urgent_watermark; + return max_scaled_time; +} + +void dml2_extract_writeback_wm(struct dc_state *context, struct display_mode_lib_st *dml_core_ctx) +{ + int i, j = 0;; + struct mcif_arb_params *wb_arb_params = NULL; + struct dcn_bw_writeback *bw_writeback = NULL; + enum mmhubbub_wbif_mode wbif_mode = PACKED_444_FP16; /*for now*/ + + if (context->stream_count != 0) { + for (i = 0; i < context->stream_count; i++) { + if (context->streams[i]->num_wb_info != 0) + j++; + } + } + if (j == 0) /*no dwb */ + return; + for (i = 0; i < __DML_NUM_DMB__; i++) { + bw_writeback = &context->bw_ctx.bw.dcn.bw_writeback; + wb_arb_params = &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[i]; + + for (j = 0 ; j < 4; j++) { + /*current dml only has one set of watermark, need to follow up*/ + bw_writeback->mcif_wb_arb[i].cli_watermark[j] = + dml_get_wm_writeback_urgent(dml_core_ctx) * 1000; + bw_writeback->mcif_wb_arb[i].pstate_watermark[j] = + dml_get_wm_writeback_dram_clock_change(dml_core_ctx) * 1000; + } + if (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk != 0) { + /* time_per_pixel should be in u6.6 format */ + bw_writeback->mcif_wb_arb[i].time_per_pixel = + (1000000 << 6) / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; + } + bw_writeback->mcif_wb_arb[i].slice_lines = 32; + bw_writeback->mcif_wb_arb[i].arbitration_slice = 2; + bw_writeback->mcif_wb_arb[i].max_scaled_time = + dml2_calc_max_scaled_time(wb_arb_params->time_per_pixel, + wbif_mode, wb_arb_params->cli_watermark[0]); + /*not required any more*/ + bw_writeback->mcif_wb_arb[i].dram_speed_change_duration = + dml_get_wm_writeback_dram_clock_change(dml_core_ctx) * 1000; + + } +} void dml2_initialize_det_scratch(struct dml2_context *in_ctx) { int i; @@ -468,6 +541,9 @@ bool dml2_verify_det_buffer_configuration(struct dml2_context *in_ctx, struct dc dml_pipe_idx = find_dml_pipe_idx_by_plane_id(in_ctx, plane_id); else dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(in_ctx, display_state->res_ctx.pipe_ctx[i].stream->stream_id); + + if (dml_pipe_idx == 0xFFFFFFFF) + continue; total_det_allocated += dml_get_det_buffer_size_kbytes(&in_ctx->v20.dml_core_ctx, dml_pipe_idx); if (total_det_allocated > max_det_size) { need_recalculation = true; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h index 5842d6d3c4b6..04fcfe637119 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.h @@ -40,9 +40,14 @@ void dml2_util_copy_dml_output(struct dml_output_cfg_st *dml_output_array, unsig unsigned int dml2_util_get_maximum_odm_combine_for_output(bool force_odm_4to1, enum dml_output_encoder_class encoder, bool dsc_enabled); void dml2_copy_clocks_to_dc_state(struct dml2_dcn_clocks *out_clks, struct dc_state *context); void dml2_extract_watermark_set(struct dcn_watermarks *watermark, struct display_mode_lib_st *dml_core_ctx); +void dml2_extract_writeback_wm(struct dc_state *context, struct display_mode_lib_st *dml_core_ctx); int dml2_helper_find_dml_pipe_idx_by_stream_id(struct dml2_context *ctx, unsigned int stream_id); bool is_dtbclk_required(const struct dc *dc, struct dc_state *context); bool dml2_is_stereo_timing(const struct dc_stream_state *stream); +unsigned int dml2_calc_max_scaled_time( + unsigned int time_per_pixel, + enum mmhubbub_wbif_mode mode, + unsigned int urgent_watermark); /* * dml2_dc_construct_pipes - This function will determine if we need additional pipes based diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 72cca367062e..9412d5384a41 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -570,6 +570,7 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s struct dml2_dcn_clocks out_clks; unsigned int result = 0; bool need_recalculation = false; + uint32_t cstate_enter_plus_exit_z8_ns; if (!context || context->stream_count == 0) return true; @@ -639,8 +640,17 @@ static bool dml2_validate_and_build_resource(const struct dc *in_dc, struct dc_s dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.b, &dml2->v20.dml_core_ctx); memcpy(&context->bw_ctx.bw.dcn.watermarks.c, &dml2->v20.g6_temp_read_watermark_set, sizeof(context->bw_ctx.bw.dcn.watermarks.c)); dml2_extract_watermark_set(&context->bw_ctx.bw.dcn.watermarks.d, &dml2->v20.dml_core_ctx); + dml2_extract_writeback_wm(context, &dml2->v20.dml_core_ctx); //copy for deciding zstate use context->bw_ctx.dml.vba.StutterPeriod = context->bw_ctx.dml2->v20.dml_core_ctx.mp.StutterPeriod; + + cstate_enter_plus_exit_z8_ns = context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns; + + if (context->bw_ctx.dml.vba.StutterPeriod < in_dc->debug.minimum_z8_residency_time && + cstate_enter_plus_exit_z8_ns < in_dc->debug.minimum_z8_residency_time * 1000) + cstate_enter_plus_exit_z8_ns = in_dc->debug.minimum_z8_residency_time * 1000; + + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = cstate_enter_plus_exit_z8_ns; } return result; @@ -681,13 +691,13 @@ static void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *d } } -bool dml2_validate(const struct dc *in_dc, struct dc_state *context, bool fast_validate) +bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2, bool fast_validate) { bool out = false; - if (!(context->bw_ctx.dml2)) + if (!dml2) return false; - dml2_apply_debug_options(in_dc, context->bw_ctx.dml2); + dml2_apply_debug_options(in_dc, dml2); /* Use dml_validate_only for fast_validate path */ diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index cc662d682fd4..4a8bd2f4195e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -71,6 +71,7 @@ struct dml2_dcn_clocks { struct dml2_dc_callbacks { struct dc *dc; bool (*build_scaling_params)(struct pipe_ctx *pipe_ctx); + void (*build_test_pattern_params)(struct resource_context *res_ctx, struct pipe_ctx *otg_master); bool (*can_support_mclk_switch_using_fw_based_vblank_stretch)(struct dc *dc, struct dc_state *context); bool (*acquire_secondary_pipe_for_mpc_odm)(const struct dc *dc, struct dc_state *state, struct pipe_ctx *pri_pipe, struct pipe_ctx *sec_pipe, bool odm); bool (*update_pipes_for_stream_with_slice_count)( @@ -86,8 +87,23 @@ struct dml2_dc_callbacks { const struct dc_plane_state *plane, int slice_count); int (*get_odm_slice_index)(const struct pipe_ctx *opp_head); + int (*get_odm_slice_count)(const struct pipe_ctx *opp_head); int (*get_mpc_slice_index)(const struct pipe_ctx *dpp_pipe); + int (*get_mpc_slice_count)(const struct pipe_ctx *dpp_pipe); struct pipe_ctx *(*get_opp_head)(const struct pipe_ctx *pipe_ctx); + struct pipe_ctx *(*get_otg_master_for_stream)( + struct resource_context *res_ctx, + const struct dc_stream_state *stream); + int (*get_opp_heads_for_otg_master)(const struct pipe_ctx *otg_master, + struct resource_context *res_ctx, + struct pipe_ctx *opp_heads[MAX_PIPES]); + int (*get_dpp_pipes_for_plane)(const struct dc_plane_state *plane, + struct resource_context *res_ctx, + struct pipe_ctx *dpp_pipes[MAX_PIPES]); + struct dc_stream_status *(*get_stream_status)( + struct dc_state *state, + const struct dc_stream_state *stream); + struct dc_stream_state *(*get_stream_from_id)(const struct dc_state *state, unsigned int id); }; struct dml2_dc_svp_callbacks { @@ -96,10 +112,10 @@ struct dml2_dc_svp_callbacks { struct dc_stream_state* (*create_phantom_stream)(const struct dc *dc, struct dc_state *state, struct dc_stream_state *main_stream); - struct dc_plane_state* (*create_phantom_plane)(struct dc *dc, + struct dc_plane_state* (*create_phantom_plane)(const struct dc *dc, struct dc_state *state, struct dc_plane_state *main_plane); - enum dc_status (*add_phantom_stream)(struct dc *dc, + enum dc_status (*add_phantom_stream)(const struct dc *dc, struct dc_state *state, struct dc_stream_state *phantom_stream, struct dc_stream_state *main_stream); @@ -108,7 +124,7 @@ struct dml2_dc_svp_callbacks { struct dc_stream_state *stream, struct dc_plane_state *plane_state, struct dc_state *context); - enum dc_status (*remove_phantom_stream)(struct dc *dc, + enum dc_status (*remove_phantom_stream)(const struct dc *dc, struct dc_state *state, struct dc_stream_state *stream); void (*release_phantom_plane)(const struct dc *dc, @@ -121,6 +137,15 @@ struct dml2_dc_svp_callbacks { enum mall_stream_type (*get_pipe_subvp_type)(const struct dc_state *state, const struct pipe_ctx *pipe_ctx); enum mall_stream_type (*get_stream_subvp_type)(const struct dc_state *state, const struct dc_stream_state *stream); struct dc_stream_state *(*get_paired_subvp_stream)(const struct dc_state *state, const struct dc_stream_state *stream); + bool (*remove_phantom_streams_and_planes)( + const struct dc *dc, + struct dc_state *state); + void (*release_phantom_streams_and_planes)( + const struct dc *dc, + struct dc_state *state); + unsigned int (*calculate_mall_ways_from_bytes)( + const struct dc *dc, + unsigned int total_size_in_mall_bytes); }; struct dml2_clks_table_entry { @@ -191,6 +216,8 @@ struct dml2_configuration_options { unsigned int max_segments_per_hubp; unsigned int det_segment_size; bool map_dc_pipes_with_callbacks; + + bool use_clock_dc_limits; }; /* @@ -244,6 +271,7 @@ void dml2_reinit(const struct dc *in_dc, */ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, + struct dml2_context *dml2, bool fast_validate); /* diff --git a/drivers/gpu/drm/amd/display/dc/dpp/Makefile b/drivers/gpu/drm/amd/display/dc/dpp/Makefile new file mode 100644 index 000000000000..99bd36073561 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/Makefile @@ -0,0 +1,77 @@ + +# Copyright 2022 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# Makefile for the 'dpp' sub-component of DAL. +# +ifdef CONFIG_DRM_AMD_DC_FP +############################################################################### +# DCN +############################################################################### + +DPP_DCN10 = dcn10_dpp.o dcn10_dpp_dscl.o dcn10_dpp_cm.o + +AMD_DAL_DPP_DCN10 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn10/,$(DPP_DCN10)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN10) + +############################################################################### + +DPP_DCN20 = dcn20_dpp.o dcn20_dpp_cm.o + +AMD_DAL_DPP_DCN20 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn20/,$(DPP_DCN20)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN20) + +############################################################################### + +DPP_DCN201 = dcn201_dpp.o + +AMD_DAL_DPP_DCN201 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn201/,$(DPP_DCN201)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN201) + +############################################################################### + +DPP_DCN30 = dcn30_dpp.o dcn30_dpp_cm.o + +AMD_DAL_DPP_DCN30 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn30/,$(DPP_DCN30)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN30) + +############################################################################### + +DPP_DCN32 = dcn32_dpp.o + +AMD_DAL_DPP_DCN32 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn32/,$(DPP_DCN32)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN32) + +############################################################################### + +DPP_DCN35 = dcn35_dpp.o + +AMD_DAL_DPP_DCN35 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn35/,$(DPP_DCN35)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN35) + +############################################################################### + +endif \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/CMakeLists.txt new file mode 100644 index 000000000000..1318c6fba3e7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/CMakeLists.txt @@ -0,0 +1,6 @@ +dal3_subdirectory_sources( + dcn10_dpp.c + dcn10_dpp_cm.c + dcn10_dpp_dscl.c + dcn10_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c index 4e391fd1d71c..e1da48b05d00 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c @@ -28,7 +28,7 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn10_dpp.h" +#include "dcn10/dcn10_dpp.h" #include "basics/conversion.h" #define NUM_PHASES 64 diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h index a039eedc7c24..c48139bed11f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h @@ -1090,7 +1090,8 @@ type DPP_CLOCK_ENABLE; \ type CM_HDR_MULT_COEF; \ type CUR0_FP_BIAS; \ - type CUR0_FP_SCALE; + type CUR0_FP_SCALE;\ + type DISPCLK_R_GATE_DISABLE; struct dcn_dpp_shift { TF_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c index 2f994a3a0b9c..006e23842016 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_cm.c @@ -28,9 +28,9 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn10_dpp.h" +#include "dcn10/dcn10_dpp.h" #include "basics/conversion.h" -#include "dcn10_cm_common.h" +#include "dcn10/dcn10_cm_common.h" #define NUM_PHASES 64 #define HORZ_MAX_TAPS 8 @@ -234,7 +234,7 @@ void dpp1_cm_get_gamut_remap(struct dpp *dpp_base, struct dpp_grph_csc_adjustment *adjust) { struct dcn10_dpp *dpp = TO_DCN10_DPP(dpp_base); - uint16_t arr_reg_val[12]; + uint16_t arr_reg_val[12] = {0}; enum gamut_remap_select select; read_gamut_remap(dpp, arr_reg_val, &select); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c index 5ca9ab8a76e8..808bca9fb804 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c @@ -28,7 +28,7 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn10_dpp.h" +#include "dcn10/dcn10_dpp.h" #include "basics/conversion.h" diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/CMakeLists.txt new file mode 100644 index 000000000000..9c2d7096348e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/CMakeLists.txt @@ -0,0 +1,5 @@ +dal3_subdirectory_sources( + dcn20_dpp.c + dcn20_dpp_cm.c + dcn20_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c index 1516c0a48726..56ebd7164dd7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c @@ -28,7 +28,7 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn20_dpp.h" +#include "dcn20/dcn20_dpp.h" #include "basics/conversion.h" #define NUM_PHASES 64 diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h index 672cde46c4b9..49cb25c9cb36 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h @@ -736,7 +736,7 @@ bool dpp20_program_shaper( bool dpp20_program_3dlut( struct dpp *dpp_base, - struct tetrahedral_params *params); + const struct tetrahedral_params *params); void dpp2_cnv_set_alpha_keyer( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c index 58dc69926e8a..31613372e214 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c @@ -28,7 +28,7 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn20_dpp.h" +#include "dcn20/dcn20_dpp.h" #include "basics/conversion.h" #include "dcn10/dcn10_cm_common.h" @@ -274,7 +274,7 @@ void dpp2_cm_get_gamut_remap(struct dpp *dpp_base, struct dpp_grph_csc_adjustment *adjust) { struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base); - uint16_t arr_reg_val[12]; + uint16_t arr_reg_val[12] = {0}; enum dcn20_gamut_remap_select select; read_gamut_remap(dpp, arr_reg_val, &select); @@ -1114,15 +1114,15 @@ static void dpp20_select_3dlut_ram_mask( bool dpp20_program_3dlut( struct dpp *dpp_base, - struct tetrahedral_params *params) + const struct tetrahedral_params *params) { enum dc_lut_mode mode; bool is_17x17x17; bool is_12bits_color_channel; - struct dc_rgb *lut0; - struct dc_rgb *lut1; - struct dc_rgb *lut2; - struct dc_rgb *lut3; + const struct dc_rgb *lut0; + const struct dc_rgb *lut1; + const struct dc_rgb *lut2; + const struct dc_rgb *lut3; int lut_size0; int lut_size; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn201/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/CMakeLists.txt new file mode 100644 index 000000000000..7711cd3c47a7 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/CMakeLists.txt @@ -0,0 +1,4 @@ +dal3_subdirectory_sources( + dcn201_dpp.c + dcn201_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn201/dcn201_dpp.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c index f809a7d21033..345202fee40f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c @@ -28,7 +28,7 @@ #include "core_types.h" #include "reg_helper.h" -#include "dcn201_dpp.h" +#include "dcn201/dcn201_dpp.h" #include "basics/conversion.h" #define REG(reg)\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/dcn201/dcn201_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.h diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/CMakeLists.txt new file mode 100644 index 000000000000..0faee2a1e32b --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/CMakeLists.txt @@ -0,0 +1,5 @@ +dal3_subdirectory_sources( + dcn30_dpp.c + dcn30_dpp_cm.c + dcn30_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c index a3a769aad042..f8c0cee34080 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c @@ -26,9 +26,9 @@ #include "dm_services.h" #include "core_types.h" #include "reg_helper.h" -#include "dcn30_dpp.h" +#include "dcn30/dcn30_dpp.h" #include "basics/conversion.h" -#include "dcn30_cm_common.h" +#include "dcn30/dcn30_cm_common.h" #define REG(reg)\ dpp->tf_regs->reg @@ -293,9 +293,11 @@ void dpp3_cnv_setup ( break; case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX: pixel_format = 112; + alpha_en = 0; break; case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX: pixel_format = 113; + alpha_en = 0; break; case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010: pixel_format = 114; @@ -319,9 +321,11 @@ void dpp3_cnv_setup ( break; case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT: pixel_format = 118; + alpha_en = 0; break; case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT: pixel_format = 119; + alpha_en = 0; break; default: break; @@ -1384,15 +1388,15 @@ static void dpp3_select_3dlut_ram_mask( } static bool dpp3_program_3dlut(struct dpp *dpp_base, - struct tetrahedral_params *params) + const struct tetrahedral_params *params) { enum dc_lut_mode mode; bool is_17x17x17; bool is_12bits_color_channel; - struct dc_rgb *lut0; - struct dc_rgb *lut1; - struct dc_rgb *lut2; - struct dc_rgb *lut3; + const struct dc_rgb *lut0; + const struct dc_rgb *lut1; + const struct dc_rgb *lut2; + const struct dc_rgb *lut3; int lut_size0; int lut_size; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h index 2ac8045a87a1..269f437c1633 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h @@ -132,6 +132,8 @@ SRI(CM_POST_CSC_B_C33_C34, CM, id), \ SRI(CM_MEM_PWR_CTRL, CM, id), \ SRI(CM_CONTROL, CM, id), \ + SRI(CM_TEST_DEBUG_INDEX, CM, id), \ + SRI(CM_TEST_DEBUG_DATA, CM, id), \ SRI(FORMAT_CONTROL, CNVC_CFG, id), \ SRI(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ SRI(CURSOR0_CONTROL, CNVC_CUR, id), \ @@ -294,6 +296,7 @@ TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \ TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \ TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \ + TF_SF(CM0_CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_INDEX, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \ TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \ @@ -426,6 +429,7 @@ type CM_GAMCOR_LUT_DATA; \ type CM_GAMCOR_LUT_WRITE_COLOR_MASK; \ type CM_GAMCOR_LUT_READ_COLOR_SEL; \ + type CM_GAMCOR_LUT_READ_DBG; \ type CM_GAMCOR_LUT_HOST_SEL; \ type CM_GAMCOR_LUT_CONFIG_MODE; \ type CM_GAMCOR_LUT_STATUS; \ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c index 2f5b3fbd3507..82eca0e7b7d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dpp_cm.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c @@ -26,9 +26,9 @@ #include "dm_services.h" #include "core_types.h" #include "reg_helper.h" -#include "dcn30_dpp.h" +#include "dcn30/dcn30_dpp.h" #include "basics/conversion.h" -#include "dcn30_cm_common.h" +#include "dcn30/dcn30_cm_common.h" #define REG(reg)\ dpp->tf_regs->reg @@ -445,7 +445,7 @@ void dpp3_cm_get_gamut_remap(struct dpp *dpp_base, struct dpp_grph_csc_adjustment *adjust) { struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); - uint16_t arr_reg_val[12]; + uint16_t arr_reg_val[12] = {0}; int select; read_gamut_remap(dpp, arr_reg_val, &select); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn32/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/CMakeLists.txt new file mode 100644 index 000000000000..7743edc4599f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/CMakeLists.txt @@ -0,0 +1,4 @@ +dal3_subdirectory_sources( + dcn32_dpp.c + dcn32_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c similarity index 99% rename from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c rename to drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c index 681e75c6dbaf..41679997b44d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c @@ -26,7 +26,7 @@ #include "dm_services.h" #include "core_types.h" #include "reg_helper.h" -#include "dcn32_dpp.h" +#include "dcn32/dcn32_dpp.h" #include "basics/conversion.h" #include "dcn30/dcn30_cm_common.h" diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn35/CMakeLists.txt b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/CMakeLists.txt new file mode 100644 index 000000000000..91df5db26435 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/CMakeLists.txt @@ -0,0 +1,4 @@ +dal3_subdirectory_sources( + dcn35_dpp.c + dcn35_dpp.h +) diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.c new file mode 100644 index 000000000000..e16274fee31d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.c @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "core_types.h" +#include "dcn35/dcn35_dpp.h" +#include "reg_helper.h" + +#define REG(reg) dpp->tf_regs->reg + +#define CTX dpp->base.ctx + +#undef FN +#define FN(reg_name, field_name) \ + ((const struct dcn35_dpp_shift *)(dpp->tf_shift))->field_name, \ + ((const struct dcn35_dpp_mask *)(dpp->tf_mask))->field_name + +void dpp35_dppclk_control( + struct dpp *dpp_base, + bool dppclk_div, + bool enable) +{ + struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base); + + if (enable) { + if (dpp->tf_mask->DPPCLK_RATE_CONTROL) + REG_UPDATE_2(DPP_CONTROL, + DPPCLK_RATE_CONTROL, dppclk_div, + DPP_CLOCK_ENABLE, 1); + else + REG_UPDATE_2(DPP_CONTROL, + DPP_CLOCK_ENABLE, 1, + DISPCLK_R_GATE_DISABLE, 1); + } else + REG_UPDATE_2(DPP_CONTROL, + DPP_CLOCK_ENABLE, 0, + DISPCLK_R_GATE_DISABLE, 0); +} + +static struct dpp_funcs dcn35_dpp_funcs = { + .dpp_program_gamcor_lut = dpp3_program_gamcor_lut, + .dpp_read_state = dpp30_read_state, + .dpp_reset = dpp_reset, + .dpp_set_scaler = dpp1_dscl_set_scaler_manual_scale, + .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps, + .dpp_set_gamut_remap = dpp3_cm_set_gamut_remap, + .dpp_set_csc_adjustment = NULL, + .dpp_set_csc_default = NULL, + .dpp_program_regamma_pwl = NULL, + .dpp_set_pre_degam = dpp3_set_pre_degam, + .dpp_program_input_lut = NULL, + .dpp_full_bypass = dpp1_full_bypass, + .dpp_setup = dpp3_cnv_setup, + .dpp_program_degamma_pwl = NULL, + .dpp_program_cm_dealpha = dpp3_program_cm_dealpha, + .dpp_program_cm_bias = dpp3_program_cm_bias, + + .dpp_program_blnd_lut = NULL, // BLNDGAM is removed completely in DCN3.2 DPP + .dpp_program_shaper_lut = NULL, // CM SHAPER block is removed in DCN3.2 DPP, (it is in MPCC, programmable before or after BLND) + .dpp_program_3dlut = NULL, // CM 3DLUT block is removed in DCN3.2 DPP, (it is in MPCC, programmable before or after BLND) + + .dpp_program_bias_and_scale = NULL, + .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer, + .set_cursor_attributes = dpp3_set_cursor_attributes, + .set_cursor_position = dpp1_set_cursor_position, + .set_optional_cursor_attributes = dpp1_cnv_set_optional_cursor_attributes, + .dpp_dppclk_control = dpp35_dppclk_control, + .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier, + .dpp_get_gamut_remap = dpp3_cm_get_gamut_remap, +}; + + +bool dpp35_construct( + struct dcn3_dpp *dpp, struct dc_context *ctx, + uint32_t inst, const struct dcn3_dpp_registers *tf_regs, + const struct dcn35_dpp_shift *tf_shift, + const struct dcn35_dpp_mask *tf_mask) +{ + bool ret = dpp32_construct(dpp, ctx, inst, tf_regs, + (const struct dcn3_dpp_shift *)(tf_shift), + (const struct dcn3_dpp_mask *)(tf_mask)); + + dpp->base.funcs = &dcn35_dpp_funcs; + return ret; +} + +void dpp35_set_fgcg(struct dcn3_dpp *dpp, bool enable) +{ + REG_UPDATE(DPP_CONTROL, DPP_FGCG_REP_DIS, !enable); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.h similarity index 87% rename from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h rename to drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.h index 09b84307cd9e..135872d88219 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn35/dcn35_dpp.h @@ -31,7 +31,9 @@ #define DPP_REG_LIST_SH_MASK_DCN35(mask_sh) \ DPP_REG_LIST_SH_MASK_DCN30_COMMON(mask_sh), \ - TF_SF(DPP_TOP0_DPP_CONTROL, DPP_FGCG_REP_DIS, mask_sh) + TF_SF(DPP_TOP0_DPP_CONTROL, DPP_FGCG_REP_DIS, mask_sh), \ + TF_SF(DPP_TOP0_DPP_CONTROL, DPP_FGCG_REP_DIS, mask_sh), \ + TF_SF(DPP_TOP0_DPP_CONTROL, DISPCLK_R_GATE_DISABLE, mask_sh) #define DPP_REG_FIELD_LIST_DCN35(type) \ struct { \ @@ -47,6 +49,11 @@ struct dcn35_dpp_mask { DPP_REG_FIELD_LIST_DCN35(uint32_t); }; +void dpp35_dppclk_control( + struct dpp *dpp_base, + bool dppclk_div, + bool enable); + bool dpp35_construct(struct dcn3_dpp *dpp3, struct dc_context *ctx, uint32_t inst, const struct dcn3_dpp_registers *tf_regs, const struct dcn35_dpp_shift *tf_shift, diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index ac41f9c0a283..150ef23440a2 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -458,7 +458,7 @@ bool dc_dsc_compute_bandwidth_range( bool is_dsc_possible = false; struct dsc_enc_caps dsc_enc_caps; struct dsc_enc_caps dsc_common_caps; - struct dc_dsc_config config; + struct dc_dsc_config config = {0}; struct dc_dsc_config_options options = {0}; options.dsc_min_slice_height_override = dsc_min_slice_height_override; @@ -868,9 +868,9 @@ static bool setup_dsc_config( struct dc_dsc_config *dsc_cfg) { struct dsc_enc_caps dsc_common_caps; - int max_slices_h; - int min_slices_h; - int num_slices_h; + int max_slices_h = 0; + int min_slices_h = 0; + int num_slices_h = 0; int pic_width; int slice_width; int target_bpp; @@ -1055,7 +1055,12 @@ static bool setup_dsc_config( if (!is_dsc_possible) goto done; - dsc_cfg->num_slices_v = pic_height/slice_height; + if (slice_height > 0) { + dsc_cfg->num_slices_v = pic_height / slice_height; + } else { + is_dsc_possible = false; + goto done; + } if (target_bandwidth_kbps > 0) { is_dsc_possible = decide_dsc_target_bpp_x16( diff --git a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c index 36d6c1646a51..59864130cf83 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/rc_calc_dpi.c @@ -101,7 +101,6 @@ int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, { int ret; struct drm_dsc_config dsc_cfg; - unsigned long long tmp; dsc_params->pps = *pps; dsc_params->pps.initial_scale_value = 8 * rc->rc_model_size / (rc->rc_model_size - rc->initial_fullness_offset); @@ -112,9 +111,9 @@ int dscc_compute_dsc_parameters(const struct drm_dsc_config *pps, dsc_cfg.mux_word_size = dsc_params->pps.bits_per_component <= 10 ? 48 : 64; ret = drm_dsc_compute_rc_parameters(&dsc_cfg); - tmp = (unsigned long long)dsc_cfg.slice_chunk_size * 0x10000000 + (dsc_cfg.slice_width - 1); - do_div(tmp, (uint32_t)dsc_cfg.slice_width); //ROUND-UP - dsc_params->bytes_per_pixel = (uint32_t)tmp; + dsc_params->bytes_per_pixel = + (uint32_t)(div_u64(((uint64_t)dsc_cfg.slice_chunk_size * 0x10000000 + (dsc_cfg.slice_width - 1)), + (uint32_t)dsc_cfg.slice_width)); /* Round-up */ copy_pps_fields(&dsc_params->pps, &dsc_cfg); dsc_params->rc_buffer_model_size = dsc_cfg.rc_bits; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_translate_dcn21.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_translate_dcn21.c index d734e3a134d1..2840ed5c57d8 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_translate_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn21/hw_translate_dcn21.c @@ -95,10 +95,6 @@ static bool offset_to_id( return true; default: ASSERT_CRITICAL(false); -#ifdef PALLADIUM_SUPPORTED - *en = GPIO_DDC_LINE_DDC1; - return true; -#endif return false; } break; @@ -184,11 +180,6 @@ static bool offset_to_id( /* UNEXPECTED */ default: /* case REG(DC_GPIO_SYNCA_A): not exista */ -#ifdef PALLADIUM_SUPPORTED - *id = GPIO_ID_HPD; - *en = GPIO_DDC_LINE_DDC1; - return true; -#endif ASSERT_CRITICAL(false); return false; } @@ -308,10 +299,6 @@ static bool id_to_offset( break; default: ASSERT_CRITICAL(false); -#ifdef PALLADIUM_SUPPORTED - info->mask = DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK; - result = true; -#endif result = false; } break; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index 3ede6e02c3a7..663c17f52779 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -128,7 +128,7 @@ struct gpio *dal_gpio_service_create_irq( uint32_t offset, uint32_t mask) { - enum gpio_id id; + enum gpio_id id = 0; uint32_t en; if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { @@ -144,7 +144,7 @@ struct gpio *dal_gpio_service_create_generic_mux( uint32_t offset, uint32_t mask) { - enum gpio_id id; + enum gpio_id id = 0; uint32_t en; struct gpio *generic; @@ -178,7 +178,7 @@ struct gpio_pin_info dal_gpio_get_generic_pin_info( enum gpio_id id, uint32_t en) { - struct gpio_pin_info pin; + struct gpio_pin_info pin = {0}; if (service->translate.funcs->id_to_offset) { service->translate.funcs->id_to_offset(id, en, &pin); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile index 9e8e9de51a92..cf8aa23b4415 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile @@ -180,7 +180,7 @@ AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN35) ############################################################################### -HWSS_DCN351 = dcn351_init.o +HWSS_DCN351 = dcn351_hwseq.o dcn351_init.o AMD_DAL_HWSS_DCN351 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn351/,$(HWSS_DCN351)) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 0ba1feaf96c0..0d3ea291eeee 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -249,7 +249,7 @@ static bool dce110_enable_display_power_gating( return false; } -static void build_prescale_params(struct ipp_prescale_params *prescale_params, +static void dce110_prescale_params(struct ipp_prescale_params *prescale_params, const struct dc_plane_state *plane_state) { prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED; @@ -289,16 +289,14 @@ dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, if (ipp == NULL) return false; - if (plane_state->in_transfer_func) - tf = plane_state->in_transfer_func; + tf = &plane_state->in_transfer_func; - build_prescale_params(&prescale_params, plane_state); + dce110_prescale_params(&prescale_params, plane_state); ipp->funcs->ipp_program_prescale(ipp, &prescale_params); - if (plane_state->gamma_correction && - !plane_state->gamma_correction->is_identity && + if (!plane_state->gamma_correction.is_identity && dce_use_lut(plane_state->format)) - ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction); + ipp->funcs->ipp_program_input_lut(ipp, &plane_state->gamma_correction); if (tf == NULL) { /* Default case if no input transfer function specified */ @@ -614,11 +612,10 @@ dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, xfm->funcs->opp_power_on_regamma_lut(xfm, true); xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->out_transfer_func && - stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) { + if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED && + stream->out_transfer_func.tf == TRANSFER_FUNCTION_SRGB) { xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB); - } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func, + } else if (dce110_translate_regamma_to_hw_format(&stream->out_transfer_func, &xfm->regamma_params)) { xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params); xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER); @@ -1192,16 +1189,6 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst, link_enc->transmitter - TRANSMITTER_UNIPHY_A); } - - if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - /* TODO: This looks like a bug to me as we are disabling HPO IO when - * we are just disabling a single HPO stream. Shouldn't we disable HPO - * HW control only when HPOs for all streams are disabled? - */ - if (pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control) - pipe_ctx->stream->ctx->dc->hwseq->funcs.setup_hpo_hw_control( - pipe_ctx->stream->ctx->dc->hwseq, false); - } } void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, @@ -1550,7 +1537,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( } if (pipe_ctx->stream_res.audio != NULL) { - struct audio_output audio_output; + struct audio_output audio_output = {0}; build_audio_output(context, pipe_ctx, &audio_output); @@ -2201,7 +2188,7 @@ static void dce110_setup_audio_dto( struct dc *dc, struct dc_state *context) { - int i; + unsigned int i; /* program audio wall clock. use HDMI as clock source if HDMI * audio active. Otherwise, use DP as clock source @@ -2273,7 +2260,7 @@ static void dce110_setup_audio_dto( continue; if (pipe_ctx->stream_res.audio != NULL) { - struct audio_output audio_output; + struct audio_output audio_output = {0}; build_audio_output(context, pipe_ctx, &audio_output); @@ -2288,6 +2275,19 @@ static void dce110_setup_audio_dto( } } +static bool dce110_is_hpo_enabled(struct dc_state *context) +{ + int i; + + for (i = 0; i < MAX_HPO_DP2_ENCODERS; i++) { + if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i]) { + return true; + } + } + + return false; +} + enum dc_status dce110_apply_ctx_to_hw( struct dc *dc, struct dc_state *context) @@ -2296,6 +2296,8 @@ enum dc_status dce110_apply_ctx_to_hw( struct dc_bios *dcb = dc->ctx->dc_bios; enum dc_status status; int i; + bool was_hpo_enabled = dce110_is_hpo_enabled(dc->current_state); + bool is_hpo_enabled = dce110_is_hpo_enabled(context); /* reset syncd pipes from disabled pipes */ if (dc->config.use_pipe_ctx_sync_logic) @@ -2338,6 +2340,10 @@ enum dc_status dce110_apply_ctx_to_hw( dce110_setup_audio_dto(dc, context); + if (dc->hwseq->funcs.setup_hpo_hw_control && was_hpo_enabled != is_hpo_enabled) { + dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, is_hpo_enabled); + } + for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index 314798400b16..0c4aef8ffe2c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -367,7 +367,7 @@ static void dcn10_log_color_state(struct dc *dc, dc->caps.color.dpp.ocsc); DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n"); - for (i = 0; i < pool->pipe_count; i++) { + for (i = 0; i < pool->mpcc_count; i++) { struct mpcc_state s = {0}; pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); @@ -1366,6 +1366,7 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context) struct dce_hwseq *hws = dc->hwseq; struct hubbub *hubbub = dc->res_pool->hubbub; bool can_apply_seamless_boot = false; + bool tg_enabled[MAX_PIPES] = {false}; for (i = 0; i < context->stream_count; i++) { if (context->streams[i]->apply_seamless_boot_optimization) { @@ -1447,6 +1448,7 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context) // requesting data while in PSR. tg->funcs->tg_init(tg); hubp->power_gated = true; + tg_enabled[i] = true; continue; } @@ -1488,6 +1490,20 @@ void dcn10_init_pipes(struct dc *dc, struct dc_state *context) tg->funcs->tg_init(tg); } + /* Clean up MPC tree */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (tg_enabled[i]) { + if (dc->res_pool->opps[i]->mpc_tree_params.opp_list) { + if (dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot) { + int bot_id = dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot->mpcc_id; + + if ((bot_id < MAX_MPCC) && (bot_id < MAX_PIPES) && (!tg_enabled[bot_id])) + dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + } + } + } + } + /* Power gate DSCs */ if (hws->funcs.dsc_pg_control != NULL) { uint32_t num_opps = 0; @@ -1813,14 +1829,12 @@ bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, if (dpp_base == NULL) return false; - if (plane_state->in_transfer_func) - tf = plane_state->in_transfer_func; + tf = &plane_state->in_transfer_func; - if (plane_state->gamma_correction && - !dpp_base->ctx->dc->debug.always_use_regamma - && !plane_state->gamma_correction->is_identity + if (!dpp_base->ctx->dc->debug.always_use_regamma + && !plane_state->gamma_correction.is_identity && dce_use_lut(plane_state->format)) - dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction); + dpp_base->funcs->dpp_program_input_lut(dpp_base, &plane_state->gamma_correction); if (tf == NULL) dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS); @@ -1861,7 +1875,7 @@ bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, #define MAX_NUM_HW_POINTS 0x200 static void log_tf(struct dc_context *ctx, - struct dc_transfer_func *tf, uint32_t hw_points_num) + const struct dc_transfer_func *tf, uint32_t hw_points_num) { // DC_LOG_GAMMA is default logging of all hw points // DC_LOG_ALL_GAMMA logs all points, not only hw points @@ -1898,16 +1912,15 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM; - if (stream->out_transfer_func && - stream->out_transfer_func->type == TF_TYPE_PREDEFINED && - stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) + if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED && + stream->out_transfer_func.tf == TRANSFER_FUNCTION_SRGB) dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB); /* dcn10_translate_regamma_to_hw_format takes 750us, only do it when full * update. */ else if (cm_helper_translate_curve_to_hw_format(dc->ctx, - stream->out_transfer_func, + &stream->out_transfer_func, &dpp->regamma_params, false)) { dpp->funcs->dpp_program_regamma_pwl( dpp, @@ -1915,10 +1928,9 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, } else dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS); - if (stream->ctx && - stream->out_transfer_func) { + if (stream->ctx) { log_tf(stream->ctx, - stream->out_transfer_func, + &stream->out_transfer_func, dpp->regamma_params.hw_points_num); } @@ -2173,7 +2185,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size, struct dc_crtc_timing *hw_crtc_timing; uint64_t phase[MAX_PIPES]; uint64_t modulo[MAX_PIPES]; - unsigned int pclk; + unsigned int pclk = 0; uint32_t embedded_pix_clk_100hz; uint16_t embedded_h_total; @@ -2264,7 +2276,7 @@ void dcn10_enable_vblanks_synchronization( struct dc_context *dc_ctx = dc->ctx; struct output_pixel_processor *opp; struct timing_generator *tg; - int i, width, height, master; + int i, width = 0, height = 0, master; DC_LOGGER_INIT(dc_ctx->logger); @@ -2330,7 +2342,7 @@ void dcn10_enable_timing_synchronization( struct dc_context *dc_ctx = dc->ctx; struct output_pixel_processor *opp; struct timing_generator *tg; - int i, width, height; + int i, width = 0, height = 0; DC_LOGGER_INIT(dc_ctx->logger); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 8b3536c380b8..7d833fa6dd77 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -155,7 +155,7 @@ void dcn20_log_color_state(struct dc *dc, DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE" " OGAM mode\n"); - for (i = 0; i < pool->pipe_count; i++) { + for (i = 0; i < pool->mpcc_count; i++) { struct mpcc_state s = {0}; pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); @@ -403,7 +403,7 @@ void dcn20_init_blank( struct output_pixel_processor *opp = NULL; struct output_pixel_processor *bottom_opp = NULL; uint32_t num_opps, opp_id_src0, opp_id_src1; - uint32_t otg_active_width, otg_active_height; + uint32_t otg_active_width = 0, otg_active_height = 0; /* program opp dpg blank color */ color_space = COLOR_SPACE_SRGB; @@ -873,6 +873,22 @@ enum dc_status dcn20_enable_stream_timing( return DC_ERROR_UNEXPECTED; } + if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { + struct dccg *dccg = dc->res_pool->dccg; + struct timing_generator *tg = pipe_ctx->stream_res.tg; + struct dtbclk_dto_params dto_params = {0}; + + if (dccg->funcs->set_dtbclk_p_src) + dccg->funcs->set_dtbclk_p_src(dccg, DTBCLK0, tg->inst); + + dto_params.otg_inst = tg->inst; + dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; + dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); + dto_params.timing = &pipe_ctx->stream->timing; + dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); + dccg->funcs->set_dtbclk_dto(dccg, &dto_params); + } + if (dc_is_hdmi_tmds_signal(stream->signal)) { stream->link->phy_state.symclk_ref_cnts.otg = 1; if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF) @@ -959,22 +975,6 @@ enum dc_status dcn20_enable_stream_timing( pipe_ctx->stream_res.tg->funcs->phantom_crtc_post_enable(pipe_ctx->stream_res.tg); } - if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - struct dccg *dccg = dc->res_pool->dccg; - struct timing_generator *tg = pipe_ctx->stream_res.tg; - struct dtbclk_dto_params dto_params = {0}; - - if (dccg->funcs->set_dtbclk_p_src) - dccg->funcs->set_dtbclk_p_src(dccg, DTBCLK0, tg->inst); - - dto_params.otg_inst = tg->inst; - dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; - dto_params.num_odm_segments = get_odm_segment_count(pipe_ctx); - dto_params.timing = &pipe_ctx->stream->timing; - dto_params.ref_dtbclk_khz = dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(dc->clk_mgr); - dccg->funcs->set_dtbclk_dto(dccg, &dto_params); - } - return DC_OK; } @@ -1011,7 +1011,7 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, { int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - struct pwl_params *params = NULL; + const struct pwl_params *params = NULL; /* * program OGAM only for the top pipe * if there is a pipe split then fix diagnostic is required: @@ -1022,19 +1022,19 @@ bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx, if (mpc->funcs->power_on_mpc_mem_pwr) mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true); if (pipe_ctx->top_pipe == NULL - && mpc->funcs->set_output_gamma && stream->out_transfer_func) { - if (stream->out_transfer_func->type == TF_TYPE_HWPWL) - params = &stream->out_transfer_func->pwl; - else if (pipe_ctx->stream->out_transfer_func->type == + && mpc->funcs->set_output_gamma) { + if (stream->out_transfer_func.type == TF_TYPE_HWPWL) + params = &stream->out_transfer_func.pwl; + else if (pipe_ctx->stream->out_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS && cm_helper_translate_curve_to_hw_format(dc->ctx, - stream->out_transfer_func, + &stream->out_transfer_func, &mpc->blender_params, false)) params = &mpc->blender_params; /* * there is no ROM */ - if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) + if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED) BREAK_TO_DEBUGGER(); } /* @@ -1050,17 +1050,15 @@ bool dcn20_set_blend_lut( { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; bool result = true; - struct pwl_params *blend_lut = NULL; + const struct pwl_params *blend_lut = NULL; - if (plane_state->blend_tf) { - if (plane_state->blend_tf->type == TF_TYPE_HWPWL) - blend_lut = &plane_state->blend_tf->pwl; - else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format(plane_state->ctx, - plane_state->blend_tf, - &dpp_base->regamma_params, false); - blend_lut = &dpp_base->regamma_params; - } + if (plane_state->blend_tf.type == TF_TYPE_HWPWL) + blend_lut = &plane_state->blend_tf.pwl; + else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { + cm_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->blend_tf, + &dpp_base->regamma_params, false); + blend_lut = &dpp_base->regamma_params; } result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut); @@ -1072,24 +1070,21 @@ bool dcn20_set_shaper_3dlut( { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; bool result = true; - struct pwl_params *shaper_lut = NULL; + const struct pwl_params *shaper_lut = NULL; - if (plane_state->in_shaper_func) { - if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL) - shaper_lut = &plane_state->in_shaper_func->pwl; - else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm_helper_translate_curve_to_hw_format(plane_state->ctx, - plane_state->in_shaper_func, - &dpp_base->shaper_params, true); - shaper_lut = &dpp_base->shaper_params; - } + if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL) + shaper_lut = &plane_state->in_shaper_func.pwl; + else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + cm_helper_translate_curve_to_hw_format(plane_state->ctx, + &plane_state->in_shaper_func, + &dpp_base->shaper_params, true); + shaper_lut = &dpp_base->shaper_params; } result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut); - if (plane_state->lut3d_func && - plane_state->lut3d_func->state.bits.initialized == 1) + if (plane_state->lut3d_func.state.bits.initialized == 1) result = dpp_base->funcs->dpp_program_3dlut(dpp_base, - &plane_state->lut3d_func->lut_3d); + &plane_state->lut3d_func.lut_3d); else result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL); @@ -1112,15 +1107,7 @@ bool dcn20_set_input_transfer_func(struct dc *dc, hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state); hws->funcs.set_blend_lut(pipe_ctx, plane_state); - if (plane_state->in_transfer_func) - tf = plane_state->in_transfer_func; - - - if (tf == NULL) { - dpp_base->funcs->dpp_set_degamma(dpp_base, - IPP_DEGAMMA_MODE_BYPASS); - return true; - } + tf = &plane_state->in_transfer_func; if (tf->type == TF_TYPE_HWPWL || tf->type == TF_TYPE_DISTRIBUTED_POINTS) use_degamma_ram = true; @@ -1917,9 +1904,11 @@ static void dcn20_program_pipe( dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes(dc->res_pool->hubbub); } - if (dc->res_pool->hubbub->funcs->program_det_size && pipe_ctx->update_flags.bits.det_size) - dc->res_pool->hubbub->funcs->program_det_size( - dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb); + if (pipe_ctx->update_flags.bits.det_size) { + if (dc->res_pool->hubbub->funcs->program_det_size) + dc->res_pool->hubbub->funcs->program_det_size( + dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb); + } if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) dcn20_update_dchubp_dpp(dc, pipe_ctx, context); @@ -2080,9 +2069,11 @@ void dcn20_program_front_end_for_ctx( * turned on (i.e. in an MCLK switch) which can come in too late and cause issues with * DET allocation. */ - if (hubbub->funcs->program_det_size && (context->res_ctx.pipe_ctx[i].update_flags.bits.disable || - (context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) - hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); + if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable || + (context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) { + if (hubbub->funcs->program_det_size) + hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); + } hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); } @@ -2892,11 +2883,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link); struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc; - if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { - if (dc->hwseq->funcs.setup_hpo_hw_control) - dc->hwseq->funcs.setup_hpo_hw_control(dc->hwseq, true); - } - if (dc->link_srv->dp_is_128b_132b_signal(pipe_ctx)) { dto_params.otg_inst = tg->inst; dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c index 884e3e323338..ef6488165b8f 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_init.c @@ -67,6 +67,7 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .setup_stereo = dcn10_setup_stereo, .set_avmute = dce110_set_avmute, .log_hw_state = dcn10_log_hw_state, + .log_color_state = dcn20_log_color_state, .get_hw_state = dcn10_get_hw_state, .clear_status_bits = dcn10_clear_status_bits, .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c index d5769f38874f..6be846635a79 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn201/dcn201_hwseq.c @@ -167,7 +167,7 @@ void dcn201_init_blank( struct tg_color black_color = {0}; struct output_pixel_processor *opp = NULL; uint32_t num_opps, opp_id_src0, opp_id_src1; - uint32_t otg_active_width, otg_active_height; + uint32_t otg_active_width = 0, otg_active_height = 0; /* program opp dpg blank color */ color_space = COLOR_SPACE_SRGB; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c index 7252f5f781f0..804be977ea47 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn21/dcn21_hwseq.c @@ -66,7 +66,7 @@ static void mmhub_update_page_table_config(struct dcn_hubbub_phys_addr_config *c int dcn21_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config) { - struct dcn_hubbub_phys_addr_config config; + struct dcn_hubbub_phys_addr_config config = {0}; config.system_aperture.fb_top = pa_config->system_aperture.fb_top; config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c index 8bc3d01537bb..ed9141a67db3 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c @@ -166,7 +166,7 @@ void dcn30_log_color_state(struct dc *dc, "C21 C22 C23 C24 " "C31 C32 C33 C34 \n"); - for (i = 0; i < pool->pipe_count; i++) { + for (i = 0; i < pool->mpcc_count; i++) { struct mpcc_state s = {0}; pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s); @@ -223,16 +223,14 @@ bool dcn30_set_blend_lut( { struct dpp *dpp_base = pipe_ctx->plane_res.dpp; bool result = true; - struct pwl_params *blend_lut = NULL; + const struct pwl_params *blend_lut = NULL; - if (plane_state->blend_tf) { - if (plane_state->blend_tf->type == TF_TYPE_HWPWL) - blend_lut = &plane_state->blend_tf->pwl; - else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm3_helper_translate_curve_to_hw_format( - plane_state->blend_tf, &dpp_base->regamma_params, false); - blend_lut = &dpp_base->regamma_params; - } + if (plane_state->blend_tf.type == TF_TYPE_HWPWL) + blend_lut = &plane_state->blend_tf.pwl; + else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { + cm3_helper_translate_curve_to_hw_format( + &plane_state->blend_tf, &dpp_base->regamma_params, false); + blend_lut = &dpp_base->regamma_params; } result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut); @@ -300,27 +298,24 @@ bool dcn30_set_input_transfer_func(struct dc *dc, struct dpp *dpp_base = pipe_ctx->plane_res.dpp; enum dc_transfer_func_predefined tf; bool result = true; - struct pwl_params *params = NULL; + const struct pwl_params *params = NULL; if (dpp_base == NULL || plane_state == NULL) return false; tf = TRANSFER_FUNCTION_UNITY; - if (plane_state->in_transfer_func && - plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED) - tf = plane_state->in_transfer_func->tf; + if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED) + tf = plane_state->in_transfer_func.tf; dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); - if (plane_state->in_transfer_func) { - if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL) - params = &plane_state->in_transfer_func->pwl; - else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && - cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func, - &dpp_base->degamma_params, false)) - params = &dpp_base->degamma_params; - } + if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL) + params = &plane_state->in_transfer_func.pwl; + else if (plane_state->in_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS && + cm3_helper_translate_curve_to_hw_format(&plane_state->in_transfer_func, + &dpp_base->degamma_params, false)) + params = &dpp_base->degamma_params; result = dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params); @@ -378,24 +373,24 @@ bool dcn30_set_output_transfer_func(struct dc *dc, { int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - struct pwl_params *params = NULL; + const struct pwl_params *params = NULL; bool ret = false; /* program OGAM or 3DLUT only for the top pipe*/ if (pipe_ctx->top_pipe == NULL) { /*program rmu shaper and 3dlut in MPC*/ ret = dcn30_set_mpc_shaper_3dlut(pipe_ctx, stream); - if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) { - if (stream->out_transfer_func->type == TF_TYPE_HWPWL) - params = &stream->out_transfer_func->pwl; - else if (pipe_ctx->stream->out_transfer_func->type == + if (ret == false && mpc->funcs->set_output_gamma) { + if (stream->out_transfer_func.type == TF_TYPE_HWPWL) + params = &stream->out_transfer_func.pwl; + else if (pipe_ctx->stream->out_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS && cm3_helper_translate_curve_to_hw_format( - stream->out_transfer_func, + &stream->out_transfer_func, &mpc->blender_params, false)) params = &mpc->blender_params; /* there are no ROM LUTs in OUTGAM */ - if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) + if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED) BREAK_TO_DEBUGGER(); } } @@ -804,7 +799,7 @@ void dcn30_init_hw(struct dc *dc) // Get DMCUB capabilities dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv); dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; - dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; } void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) @@ -818,7 +813,7 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) enable); /* Wait for two frame to make sure AV mute is sent out */ - if (enable) { + if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) { pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); @@ -890,7 +885,7 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) { union dmub_rb_cmd cmd; uint32_t tmr_delay = 0, tmr_scale = 0; - struct dc_cursor_attributes cursor_attr; + struct dc_cursor_attributes cursor_attr = {0}; bool cursor_cache_enable = false; struct dc_stream_state *stream = NULL; struct dc_plane_state *plane = NULL; @@ -946,7 +941,8 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB8888 && plane->address.page_table_base.quad_part == 0 && dc->hwss.does_plane_fit_in_mall && - dc->hwss.does_plane_fit_in_mall(dc, plane, + dc->hwss.does_plane_fit_in_mall(dc, plane->plane_size.surface_pitch, + plane->plane_size.surface_size.height, plane->format, cursor_cache_enable ? &cursor_attr : NULL)) { unsigned int v_total = stream->adjust.v_total_max ? stream->adjust.v_total_max : stream->timing.v_total; @@ -1076,11 +1072,15 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable) return true; } -bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr) +bool dcn30_does_plane_fit_in_mall(struct dc *dc, + unsigned int pitch, + unsigned int height, + enum surface_pixel_format format, + struct dc_cursor_attributes *cursor_attr) { // add meta size? - unsigned int surface_size = plane->plane_size.surface_pitch * plane->plane_size.surface_size.height * - (plane->format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); + unsigned int surface_size = pitch * height * + (format >= SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616 ? 8 : 4); unsigned int mall_size = dc->caps.mall_size_total; unsigned int cursor_size = 0; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h index 638f018a3cb5..76b16839486a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.h @@ -71,7 +71,10 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx); void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx); -bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, +bool dcn30_does_plane_fit_in_mall(struct dc *dc, + unsigned int pitch, + unsigned int height, + enum surface_pixel_format format, struct dc_cursor_attributes *cursor_attr); bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c index a760f0c6fe98..1c8abb417b6e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c @@ -273,7 +273,7 @@ void dcn31_init_hw(struct dc *dc) // Get DMCUB capabilities dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv); dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; - dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; } void dcn31_dsc_pg_control( @@ -479,7 +479,7 @@ void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool p int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config) { - struct dcn_hubbub_phys_addr_config config; + struct dcn_hubbub_phys_addr_config config = {0}; config.system_aperture.fb_top = pa_config->system_aperture.fb_top; config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c index 093f4387553c..0d8a05cf8b1a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c @@ -82,7 +82,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) if (enable) { struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; enum optc_dsc_mode optc_dsc_mode; /* Enable DSC hw block */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 7668229438da..b8e884368dc6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -239,8 +239,10 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c // Convert number of cache lines required to number of ways if (dc->debug.force_mall_ss_num_ways > 0) { num_ways = dc->debug.force_mall_ss_num_ways; + } else if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) { + num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, mall_ss_size_bytes); } else { - num_ways = dcn32_helper_mall_bytes_to_ways(dc, mall_ss_size_bytes); + num_ways = 0; } return num_ways; @@ -261,7 +263,9 @@ bool dcn32_apply_idle_power_optimizations(struct dc *dc, bool enable) for (i = 0; i < dc->current_state->stream_count; i++) { /* MALL SS messaging is not supported with PSR at this time */ if (dc->current_state->streams[i] != NULL && - dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED) + dc->current_state->streams[i]->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && + (dc->current_state->stream_count > 1 || (!dc->current_state->streams[i]->dpms_off && + dc->current_state->stream_status[i].plane_count > 0))) return false; } @@ -475,39 +479,35 @@ bool dcn32_set_mcm_luts( int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; bool result = true; - struct pwl_params *lut_params = NULL; + const struct pwl_params *lut_params = NULL; // 1D LUT - if (plane_state->blend_tf) { - if (plane_state->blend_tf->type == TF_TYPE_HWPWL) - lut_params = &plane_state->blend_tf->pwl; - else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) { - cm3_helper_translate_curve_to_hw_format(plane_state->blend_tf, - &dpp_base->regamma_params, false); - lut_params = &dpp_base->regamma_params; - } + if (plane_state->blend_tf.type == TF_TYPE_HWPWL) + lut_params = &plane_state->blend_tf.pwl; + else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) { + cm3_helper_translate_curve_to_hw_format(&plane_state->blend_tf, + &dpp_base->regamma_params, false); + lut_params = &dpp_base->regamma_params; } result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id); lut_params = NULL; // Shaper - if (plane_state->in_shaper_func) { - if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL) - lut_params = &plane_state->in_shaper_func->pwl; - else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) { - // TODO: dpp_base replace - ASSERT(false); - cm3_helper_translate_curve_to_hw_format(plane_state->in_shaper_func, - &dpp_base->shaper_params, true); - lut_params = &dpp_base->shaper_params; - } + if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL) + lut_params = &plane_state->in_shaper_func.pwl; + else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) { + // TODO: dpp_base replace + ASSERT(false); + cm3_helper_translate_curve_to_hw_format(&plane_state->in_shaper_func, + &dpp_base->shaper_params, true); + lut_params = &dpp_base->shaper_params; } result = mpc->funcs->program_shaper(mpc, lut_params, mpcc_id); // 3D - if (plane_state->lut3d_func && plane_state->lut3d_func->state.bits.initialized == 1) - result = mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func->lut_3d, mpcc_id); + if (plane_state->lut3d_func.state.bits.initialized == 1) + result = mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id); else result = mpc->funcs->program_3dlut(mpc, NULL, mpcc_id); @@ -524,27 +524,24 @@ bool dcn32_set_input_transfer_func(struct dc *dc, enum dc_transfer_func_predefined tf; bool result = true; - struct pwl_params *params = NULL; + const struct pwl_params *params = NULL; if (mpc == NULL || plane_state == NULL) return false; tf = TRANSFER_FUNCTION_UNITY; - if (plane_state->in_transfer_func && - plane_state->in_transfer_func->type == TF_TYPE_PREDEFINED) - tf = plane_state->in_transfer_func->tf; + if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED) + tf = plane_state->in_transfer_func.tf; dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf); - if (plane_state->in_transfer_func) { - if (plane_state->in_transfer_func->type == TF_TYPE_HWPWL) - params = &plane_state->in_transfer_func->pwl; - else if (plane_state->in_transfer_func->type == TF_TYPE_DISTRIBUTED_POINTS && - cm3_helper_translate_curve_to_hw_format(plane_state->in_transfer_func, - &dpp_base->degamma_params, false)) - params = &dpp_base->degamma_params; - } + if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL) + params = &plane_state->in_transfer_func.pwl; + else if (plane_state->in_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS && + cm3_helper_translate_curve_to_hw_format(&plane_state->in_transfer_func, + &dpp_base->degamma_params, false)) + params = &dpp_base->degamma_params; dpp_base->funcs->dpp_program_gamcor_lut(dpp_base, params); @@ -562,24 +559,24 @@ bool dcn32_set_output_transfer_func(struct dc *dc, { int mpcc_id = pipe_ctx->plane_res.hubp->inst; struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc; - struct pwl_params *params = NULL; + const struct pwl_params *params = NULL; bool ret = false; /* program OGAM or 3DLUT only for the top pipe*/ if (resource_is_pipe_type(pipe_ctx, OPP_HEAD)) { /*program shaper and 3dlut in MPC*/ ret = dcn32_set_mpc_shaper_3dlut(pipe_ctx, stream); - if (ret == false && mpc->funcs->set_output_gamma && stream->out_transfer_func) { - if (stream->out_transfer_func->type == TF_TYPE_HWPWL) - params = &stream->out_transfer_func->pwl; - else if (pipe_ctx->stream->out_transfer_func->type == + if (ret == false && mpc->funcs->set_output_gamma) { + if (stream->out_transfer_func.type == TF_TYPE_HWPWL) + params = &stream->out_transfer_func.pwl; + else if (pipe_ctx->stream->out_transfer_func.type == TF_TYPE_DISTRIBUTED_POINTS && cm3_helper_translate_curve_to_hw_format( - stream->out_transfer_func, + &stream->out_transfer_func, &mpc->blender_params, false)) params = &mpc->blender_params; /* there are no ROM LUTs in OUTGAM */ - if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED) + if (stream->out_transfer_func.type == TF_TYPE_PREDEFINED) BREAK_TO_DEBUGGER(); } } @@ -956,10 +953,10 @@ void dcn32_init_hw(struct dc *dc) dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; dc->caps.dmub_caps.subvp_psr = dc->ctx->dmub_srv->dmub->feature_caps.subvp_psr_support; dc->caps.dmub_caps.gecc_enable = dc->ctx->dmub_srv->dmub->feature_caps.gecc_enable; - dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; if (dc->ctx->dmub_srv->dmub->fw_version < - DMUB_FW_VERSION(7, 0, 35)) { + DMUB_FW_VERSION(7, 0, 35)) { dc->debug.force_disable_subvp = true; dc->debug.disable_fpo_optimizations = true; } @@ -992,7 +989,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) if (enable) { struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; enum optc_dsc_mode optc_dsc_mode; /* Enable DSC hw block */ @@ -1545,7 +1542,7 @@ void dcn32_init_blank( struct output_pixel_processor *opp = NULL; struct output_pixel_processor *bottom_opp = NULL; uint32_t num_opps, opp_id_src0, opp_id_src1; - uint32_t otg_active_width, otg_active_height; + uint32_t otg_active_width = 0, otg_active_height = 0; uint32_t i; /* program opp dpg blank color */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index a5560b3fc39b..d4989d15e2f1 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -349,7 +349,7 @@ void dcn35_init_hw(struct dc *dc) if (dc->ctx->dmub_srv) { dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv); dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr; - dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch; + dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver; } if (dc->res_pool->pg_cntl) { @@ -373,7 +373,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) if (enable) { struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; enum optc_dsc_mode optc_dsc_mode; /* Enable DSC hw block */ @@ -495,6 +495,17 @@ void dcn35_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, } } +void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hpo_inst, bool clock_on) +{ + if (!hws->ctx->dc->debug.root_clock_optimization.bits.dpstream) + return; + + if (hws->ctx->dc->res_pool->dccg->funcs->set_dpstreamclk_root_clock_gating) { + hws->ctx->dc->res_pool->dccg->funcs->set_dpstreamclk_root_clock_gating( + hws->ctx->dc->res_pool->dccg, dp_hpo_inst, clock_on); + } +} + void dcn35_dsc_pg_control( struct dce_hwseq *hws, unsigned int dsc_inst, @@ -679,6 +690,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) struct hubbub *hubbub = dc->res_pool->hubbub; struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; bool can_apply_seamless_boot = false; + bool tg_enabled[MAX_PIPES] = {false}; for (i = 0; i < context->stream_count; i++) { if (context->streams[i]->apply_seamless_boot_optimization) { @@ -760,6 +772,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) // requesting data while in PSR. tg->funcs->tg_init(tg); hubp->power_gated = true; + tg_enabled[i] = true; continue; } @@ -801,6 +814,20 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context) tg->funcs->tg_init(tg); } + /* Clean up MPC tree */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (tg_enabled[i]) { + if (dc->res_pool->opps[i]->mpc_tree_params.opp_list) { + if (dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot) { + int bot_id = dc->res_pool->opps[i]->mpc_tree_params.opp_list->mpcc_bot->mpcc_id; + + if ((bot_id < MAX_MPCC) && (bot_id < MAX_PIPES) && (!tg_enabled[bot_id])) + dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL; + } + } + } + } + if (pg_cntl != NULL) { if (pg_cntl->funcs->dsc_pg_control != NULL) { uint32_t num_opps = 0; @@ -961,6 +988,9 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, if (!hpo_frl_stream_enc_acquired && !hpo_dp_stream_enc_acquired) update_state->pg_res_update[PG_HPO] = true; + if (hpo_frl_stream_enc_acquired) + update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true; + update_state->pg_res_update[PG_DWB] = true; for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -978,8 +1008,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, if (pipe_ctx->plane_res.dpp) update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false; - if ((pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) && - pipe_ctx->plane_res.mpcc_inst >= 0) + if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false; if (pipe_ctx->stream_res.dsc) @@ -987,6 +1016,9 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, if (pipe_ctx->stream_res.opp) update_state->pg_pipe_res_update[PG_OPP][pipe_ctx->stream_res.opp->inst] = false; + + if (pipe_ctx->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false; } /*domain24 controls all the otg, mpc, opp, as long as one otg is still up, avoid enabling OTG PG*/ for (i = 0; i < dc->res_pool->timing_generator_count; i++) { @@ -1044,6 +1076,9 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, if (j == PG_OPTC && new_pipe->stream_res.tg) update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true; + + if (j == PG_DPSTREAM && new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true; } } else if (cur_pipe->plane_state == new_pipe->plane_state || cur_pipe == new_pipe) { @@ -1073,6 +1108,11 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, cur_pipe->stream_res.tg != new_pipe->stream_res.tg && new_pipe->stream_res.tg) update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true; + + if (j == PG_DPSTREAM && + cur_pipe->stream_res.hpo_dp_stream_enc != new_pipe->stream_res.hpo_dp_stream_enc && + new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true; } } } @@ -1088,6 +1128,9 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, if (hpo_frl_stream_enc_acquired || hpo_dp_stream_enc_acquired) update_state->pg_res_update[PG_HPO] = true; + if (hpo_frl_stream_enc_acquired) + update_state->pg_pipe_res_update[PG_HDMISTREAM][0] = true; + } /** @@ -1212,14 +1255,19 @@ void dcn35_root_clock_control(struct dc *dc, if (!pg_cntl) return; /*enable root clock first when power up*/ - if (power_on) + if (power_on) { for (i = 0; i < dc->res_pool->pipe_count; i++) { if (update_state->pg_pipe_res_update[PG_HUBP][i] && update_state->pg_pipe_res_update[PG_DPP][i]) { if (dc->hwseq->funcs.dpp_root_clock_control) dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); } + if (update_state->pg_pipe_res_update[PG_DPSTREAM][i]) + if (dc->hwseq->funcs.dpstream_root_clock_control) + dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } + + } for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) { if (update_state->pg_pipe_res_update[PG_DSC][i]) { if (power_on) { @@ -1232,14 +1280,19 @@ void dcn35_root_clock_control(struct dc *dc, } } /*disable root clock first when power down*/ - if (!power_on) + if (!power_on) { for (i = 0; i < dc->res_pool->pipe_count; i++) { if (update_state->pg_pipe_res_update[PG_HUBP][i] && update_state->pg_pipe_res_update[PG_DPP][i]) { if (dc->hwseq->funcs.dpp_root_clock_control) dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on); } + if (update_state->pg_pipe_res_update[PG_DPSTREAM][i]) + if (dc->hwseq->funcs.dpstream_root_clock_control) + dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } + + } } void dcn35_prepare_bandwidth( @@ -1280,22 +1333,6 @@ void dcn35_optimize_bandwidth( } } -void dcn35_set_idle_state(const struct dc *dc, bool allow_idle) -{ - // TODO: Find a more suitable communcation - if (dc->clk_mgr->funcs->set_idle_state) - dc->clk_mgr->funcs->set_idle_state(dc->clk_mgr, allow_idle); -} - -uint32_t dcn35_get_idle_state(const struct dc *dc) -{ - // TODO: Find a more suitable communcation - if (dc->clk_mgr->funcs->get_idle_state) - return dc->clk_mgr->funcs->get_idle_state(dc->clk_mgr); - - return 0; -} - void dcn35_set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, struct dc_crtc_timing_adjust adjust) { @@ -1353,3 +1390,31 @@ void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx, set_static_screen_control(pipe_ctx[i]->stream_res.tg, triggers, params->num_frames); } + +void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx, + int num_pipes, uint32_t v_total_min, uint32_t v_total_max) +{ + int i = 0; + struct long_vtotal_params params = {0}; + + params.vertical_total_max = v_total_max; + params.vertical_total_min = v_total_min; + + for (i = 0; i < num_pipes; i++) { + if (!pipe_ctx[i]) + continue; + + if (pipe_ctx[i]->stream) { + struct dc_crtc_timing *timing = &pipe_ctx[i]->stream->timing; + + if (timing) + params.vertical_blank_start = timing->v_total - timing->v_front_porch; + else + params.vertical_blank_start = 0; + + if ((pipe_ctx[i]->stream_res.tg != NULL) && pipe_ctx[i]->stream_res.tg->funcs && + pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal) + pipe_ctx[i]->stream_res.tg->funcs->set_long_vtotal(pipe_ctx[i]->stream_res.tg, ¶ms); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index c354efa6c1b2..a731c8880d60 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -37,6 +37,8 @@ void dcn35_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool pow void dcn35_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on); +void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hpo_inst, bool clock_on); + void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable); @@ -84,13 +86,13 @@ void dcn35_dsc_pg_control( unsigned int dsc_inst, bool power_on); -void dcn35_set_idle_state(const struct dc *dc, bool allow_idle); -uint32_t dcn35_get_idle_state(const struct dc *dc); - void dcn35_set_drr(struct pipe_ctx **pipe_ctx, int num_pipes, struct dc_crtc_timing_adjust adjust); void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_params *params); +void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx, + int num_pipes, uint32_t v_total_min, uint32_t v_total_max); + #endif /* __DC_HWSS_DCN35_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index a93073055e7b..df3bf77f3fb4 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -121,8 +121,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = { .hw_block_power_up = dcn35_hw_block_power_up, .hw_block_power_down = dcn35_hw_block_power_down, .root_clock_control = dcn35_root_clock_control, - .set_idle_state = dcn35_set_idle_state, - .get_idle_state = dcn35_get_idle_state + .set_long_vtotal = dcn35_set_long_vblank, }; static const struct hwseq_private_funcs dcn35_private_funcs = { @@ -148,6 +147,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { //.hubp_pg_control = dcn35_hubp_pg_control, .enable_power_gating_plane = dcn35_enable_power_gating_plane, .dpp_root_clock_control = dcn35_dpp_root_clock_control, + .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/Makefile index b24ad27fe6ef..a4b3c1e99ec6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/Makefile @@ -1,16 +1,27 @@ # -# (c) Copyright 2022 Advanced Micro Devices, Inc. All the rights reserved +# Copyright (c) 2022-2024 Advanced Micro Devices, Inc. # -# All rights reserved. This notice is intended as a precaution against -# inadvertent publication and does not imply publication or any waiver -# of confidentiality. The year included in the foregoing notice is the -# year of creation of the work. +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: # -# Authors: AMD +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. # # Makefile for DCN351. -DCN351 = dcn351_init.o +DCN351 = dcn351_hwseq.o dcn351_init.o AMD_DAL_DCN351 = $(addprefix $(AMDDALPATH)/dc/dcn351/,$(DCN351)) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.c new file mode 100644 index 000000000000..93fe5b262a3d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.c @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright 2024 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + * + */ + +#include "core_types.h" +#include "resource.h" +#include "dcn351_hwseq.h" +#include "dcn35/dcn35_hwseq.h" + +#define DC_LOGGER_INIT(logger) \ + struct dal_logger *dc_logger = logger + +#define DC_LOGGER \ + dc_logger + +void dcn351_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state) +{ + int i, j; + + dcn35_calc_blocks_to_gate(dc, context, update_state); + + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (!update_state->pg_pipe_res_update[PG_HUBP][i] && + !update_state->pg_pipe_res_update[PG_DPP][i]) { + for (j = i - 1; j >= 0; j--) { + update_state->pg_pipe_res_update[PG_HUBP][j] = false; + update_state->pg_pipe_res_update[PG_DPP][j] = false; + } + + break; + } + } +} + +void dcn351_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state) +{ + int i, j; + + dcn35_calc_blocks_to_ungate(dc, context, update_state); + + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + for (j = i - 1; j >= 0; j--) { + update_state->pg_pipe_res_update[PG_HUBP][j] = true; + update_state->pg_pipe_res_update[PG_DPP][j] = true; + } + + break; + } + } +} + +/** + * dcn351_hw_block_power_down() - power down sequence + * + * The following sequence describes the ON-OFF (ONO) for power down: + * + * ONO Region 11, DCPG 19: dsc3 + * ONO Region 10, DCPG 3: dchubp3, dpp3 + * ONO Region 9, DCPG 18: dsc2 + * ONO Region 8, DCPG 2: dchubp2, dpp2 + * ONO Region 7, DCPG 17: dsc1 + * ONO Region 6, DCPG 1: dchubp1, dpp1 + * ONO Region 5, DCPG 16: dsc0 + * ONO Region 4, DCPG 0: dchubp0, dpp0 + * ONO Region 3, DCPG 25: hpo - SKIPPED. Should be kept on + * ONO Region 2, DCPG 24: mpc opp optc dwb + * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will pwr dwn at IPS2 entry + * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED. will be pwr dwn after lono timer is armed + * + * @dc: Current DC state + * @update_state: update PG sequence states for HW block + */ +void dcn351_hw_block_power_down(struct dc *dc, + struct pg_block_update *update_state) +{ + int i = 0; + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; + + if (!pg_cntl || dc->debug.ignore_pg) + return; + + for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) { + if (update_state->pg_pipe_res_update[PG_DSC][i]) { + if (pg_cntl->funcs->dsc_pg_control) + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false); + } + + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (pg_cntl->funcs->hubp_dpp_pg_control) + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false); + } + } + + // domain25 currently always on. + + /* this will need all the clients to unregister optc interrupts, let dmubfw handle this */ + if (pg_cntl->funcs->plane_otg_pg_control) + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false); + + // domain23 currently always on. + // domain22 currently always on. +} + +/** + * dcn351_hw_block_power_up() - power up sequence + * + * The following sequence describes the ON-OFF (ONO) for power up: + * + * ONO Region 0, DCPG 22: dccg dio dcio - SKIPPED + * ONO Region 1, DCPG 23: dchubbub dchvm dchubbubmem - SKIPPED. PMFW will power up at IPS2 exit + * ONO Region 2, DCPG 24: mpc opp optc dwb + * ONO Region 3, DCPG 25: hpo - SKIPPED + * ONO Region 4, DCPG 0: dchubp0, dpp0 + * ONO Region 5, DCPG 16: dsc0 + * ONO Region 6, DCPG 1: dchubp1, dpp1 + * ONO Region 7, DCPG 17: dsc1 + * ONO Region 8, DCPG 2: dchubp2, dpp2 + * ONO Region 9, DCPG 18: dsc2 + * ONO Region 10, DCPG 3: dchubp3, dpp3 + * ONO Region 11, DCPG 19: dsc3 + * + * @dc: Current DC state + * @update_state: update PG sequence states for HW block + */ +void dcn351_hw_block_power_up(struct dc *dc, + struct pg_block_update *update_state) +{ + int i = 0; + struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl; + + if (!pg_cntl || dc->debug.ignore_pg) + return; + + // domain22 currently always on. + // domain23 currently always on. + + /* this will need all the clients to unregister optc interrupts, let dmubfw handle this */ + if (pg_cntl->funcs->plane_otg_pg_control) + pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true); + + // domain25 currently always on. + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (update_state->pg_pipe_res_update[PG_HUBP][i] && + update_state->pg_pipe_res_update[PG_DPP][i]) { + if (pg_cntl->funcs->hubp_dpp_pg_control) + pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true); + } + + if (update_state->pg_pipe_res_update[PG_DSC][i]) { + if (pg_cntl->funcs->dsc_pg_control) + pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true); + } + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.h similarity index 56% rename from drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c rename to drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.h index 3341ef71009b..6d8f3bfb668e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_hwseq.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: MIT */ /* - * Copyright 2023 Advanced Micro Devices, Inc. + * Copyright 2024 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,30 +24,18 @@ * */ -#include "core_types.h" -#include "dcn35_dpp.h" -#include "reg_helper.h" +#ifndef __DC_HWSS_DCN351_H__ +#define __DC_HWSS_DCN351_H__ -#define REG(reg) dpp->tf_regs->reg +#include "hw_sequencer_private.h" -#define CTX dpp->base.ctx +void dcn351_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state); +void dcn351_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, + struct pg_block_update *update_state); +void dcn351_hw_block_power_up(struct dc *dc, + struct pg_block_update *update_state); +void dcn351_hw_block_power_down(struct dc *dc, + struct pg_block_update *update_state); -#undef FN -#define FN(reg_name, field_name) \ - ((const struct dcn35_dpp_shift *)(dpp->tf_shift))->field_name, \ - ((const struct dcn35_dpp_mask *)(dpp->tf_mask))->field_name - -bool dpp35_construct(struct dcn3_dpp *dpp, struct dc_context *ctx, - uint32_t inst, const struct dcn3_dpp_registers *tf_regs, - const struct dcn35_dpp_shift *tf_shift, - const struct dcn35_dpp_mask *tf_mask) -{ - return dpp32_construct(dpp, ctx, inst, tf_regs, - (const struct dcn3_dpp_shift *)(tf_shift), - (const struct dcn3_dpp_mask *)(tf_mask)); -} - -void dpp35_set_fgcg(struct dcn3_dpp *dpp, bool enable) -{ - REG_UPDATE(DPP_CONTROL, DPP_FGCG_REP_DIS, !enable); -} +#endif /* __DC_HWSS_DCN351_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index 670255c9bc82..a53092cd619b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -32,6 +32,7 @@ #include "dcn31/dcn31_hwseq.h" #include "dcn32/dcn32_hwseq.h" #include "dcn35/dcn35_hwseq.h" +#include "dcn351/dcn351_hwseq.h" #include "dcn351_init.h" @@ -120,8 +121,6 @@ static const struct hw_sequencer_funcs dcn351_funcs = { .hw_block_power_up = dcn35_hw_block_power_up, .hw_block_power_down = dcn35_hw_block_power_down, .root_clock_control = dcn35_root_clock_control, - .set_idle_state = dcn35_set_idle_state, - .get_idle_state = dcn35_get_idle_state }; static const struct hwseq_private_funcs dcn351_private_funcs = { @@ -147,6 +146,7 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { //.hubp_pg_control = dcn35_hubp_pg_control, .enable_power_gating_plane = dcn35_enable_power_gating_plane, .dpp_root_clock_control = dcn35_dpp_root_clock_control, + .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index f89f205e42a1..7c339e7e7117 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -377,7 +377,10 @@ struct hw_sequencer_funcs { /* Idle Optimization Related */ bool (*apply_idle_power_optimizations)(struct dc *dc, bool enable); - bool (*does_plane_fit_in_mall)(struct dc *dc, struct dc_plane_state *plane, + bool (*does_plane_fit_in_mall)(struct dc *dc, + unsigned int pitch, + unsigned int height, + enum surface_pixel_format format, struct dc_cursor_attributes *cursor_attr); void (*commit_subvp_config)(struct dc *dc, struct dc_state *context); void (*enable_phantom_streams)(struct dc *dc, struct dc_state *context); @@ -424,11 +427,10 @@ struct hw_sequencer_funcs { struct pg_block_update *update_state); void (*root_clock_control)(struct dc *dc, struct pg_block_update *update_state, bool power_on); - void (*set_idle_state)(const struct dc *dc, bool allow_idle); - uint32_t (*get_idle_state)(const struct dc *dc); bool (*is_pipe_topology_transition_seamless)(struct dc *dc, const struct dc_state *cur_ctx, const struct dc_state *new_ctx); + void (*set_long_vtotal)(struct pipe_ctx **pipe_ctx, int num_pipes, uint32_t v_total_min, uint32_t v_total_max); }; void color_space_to_black_color( @@ -478,9 +480,10 @@ void hwss_build_fast_sequence(struct dc *dc, struct dc_dmub_cmd *dc_dmub_cmd, unsigned int dmub_cmd_count, struct block_sequence block_sequence[], - int *num_steps, + unsigned int *num_steps, struct pipe_ctx *pipe_ctx, - struct dc_stream_status *stream_status); + struct dc_stream_status *stream_status, + struct dc_state *context); void hwss_send_dmcub_cmd(union block_sequence_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h index 554cfab5ab24..341219cf4144 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h @@ -120,6 +120,10 @@ struct hwseq_private_funcs { struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on); + void (*dpstream_root_clock_control)( + struct dce_hwseq *hws, + unsigned int dpp_inst, + bool clock_on); void (*dpp_pg_control)(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h index b1b72e688f74..028b2f971e36 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -90,6 +90,9 @@ struct resource_funcs { void (*update_soc_for_wm_a)( struct dc *dc, struct dc_state *context); + unsigned int (*calculate_mall_ways_from_bytes)( + const struct dc *dc, + unsigned int total_size_in_mall_bytes); /** * @populate_dml_pipes - Populate pipe data struct * @@ -336,7 +339,9 @@ struct stream_resource { }; struct plane_resource { + /* scl_data is scratch space required to program a plane */ struct scaler_data scl_data; + /* Below pointers to hw objects are required to enable the plane */ struct hubp *hubp; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -496,7 +501,7 @@ struct dcn_bw_writeback { struct dcn_bw_output { struct dc_clocks clk; - struct dcn_watermark_set watermarks; + union dcn_watermark_set watermarks; struct dcn_bw_writeback bw_writeback; int compbuf_size_kb; unsigned int mall_ss_size_bytes; @@ -515,6 +520,7 @@ struct bw_context { union bw_output bw; struct display_mode_lib dml; struct dml2_context *dml2; + struct dml2_context *dml2_dc_power_source; }; struct dc_dmub_cmd { @@ -522,25 +528,6 @@ struct dc_dmub_cmd { enum dm_dmub_wait_type wait_type; }; -struct dc_scratch_space { - /* used to temporarily backup plane states of a stream during - * dc update. The reason is that plane states are overwritten - * with surface updates in dc update. Once they are overwritten - * current state is no longer valid. We want to temporarily - * store current value in plane states so we can still recover - * a valid current state during dc update. - */ - struct dc_plane_state plane_states[MAX_SURFACE_NUM]; - struct dc_gamma gamma_correction[MAX_SURFACE_NUM]; - struct dc_transfer_func in_transfer_func[MAX_SURFACE_NUM]; - struct dc_3dlut lut3d_func[MAX_SURFACE_NUM]; - struct dc_transfer_func in_shaper_func[MAX_SURFACE_NUM]; - struct dc_transfer_func blend_tf[MAX_SURFACE_NUM]; - - struct dc_stream_state stream_state; - struct dc_transfer_func out_transfer_func; -}; - /** * struct dc_state - The full description of a state requested by users */ @@ -623,8 +610,7 @@ struct dc_state { unsigned int stutter_period_us; } perf_params; - - struct dc_scratch_space scratch; + enum dc_power_source_type power_source; }; struct replay_context { diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h index 9e4ddc985240..55529c5f471c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h @@ -31,7 +31,7 @@ #define __DCN_CALCS_H__ #include "bw_fixed.h" -#include "../dml/display_mode_lib.h" +#include "dml/display_mode_lib.h" struct dc; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 17e014d3bdc8..4f7480f60c85 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -281,8 +281,6 @@ struct clk_mgr_funcs { void (*set_low_power_state)(struct clk_mgr *clk_mgr); void (*exit_low_power_state)(struct clk_mgr *clk_mgr); bool (*is_ips_supported)(struct clk_mgr *clk_mgr); - void (*set_idle_state)(struct clk_mgr *clk_mgr, bool allow_idle); - uint32_t (*get_idle_state)(struct clk_mgr *clk_mgr); void (*init_clocks)(struct clk_mgr *clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h index f4d4a68c91dc..4ba18ea57aad 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -349,7 +349,7 @@ struct clk_mgr_internal { enum dm_pp_clocks_state cur_min_clks_state; bool periodic_retraining_disabled; - unsigned int cur_phyclk_req_table[MAX_PIPES * 2]; + unsigned int cur_phyclk_req_table[MAX_LINKS]; bool smu_present; void *wm_range_table; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index b9a06bf84cc9..d4c7885fc916 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -59,6 +59,7 @@ enum dentist_dispclk_change_mode { struct dp_dto_params { int otg_inst; enum signal_type signal; + enum streamclk_source clk_src; uint64_t pixclk_hz; uint64_t refclk_hz; }; @@ -105,6 +106,10 @@ struct dccg_funcs { void (*otg_drop_pixel)(struct dccg *dccg, uint32_t otg_inst); void (*dccg_init)(struct dccg *dccg); + void (*set_dpstreamclk_root_clock_gating)( + struct dccg *dccg, + int dp_hpo_inst, + bool enable); void (*set_dpstreamclk)( struct dccg *dccg, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 2ae7484d18af..305fdc127bfc 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -160,7 +160,7 @@ struct hubbub_funcs { bool (*program_watermarks)( struct hubbub *hubbub, - struct dcn_watermark_set *watermarks, + union dcn_watermark_set *watermarks, unsigned int refclk_mhz, bool safe_to_lower); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index 0f24afbf4388..ca8de345d039 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -322,7 +322,7 @@ struct dpp_funcs { const struct pwl_params *params); bool (*dpp_program_3dlut)( struct dpp *dpp, - struct tetrahedral_params *params); + const struct tetrahedral_params *params); void (*dpp_cnv_set_alpha_keyer)( struct dpp *dpp_base, struct cnv_color_keyer_params *color_keyer); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h index 729ca0064e94..063efc8128a7 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dwb.h @@ -147,9 +147,10 @@ struct dwb_caps { unsigned int support_ogam :1; unsigned int support_wbscl :1; unsigned int support_ocsc :1; - unsigned int support_stereo :1; + unsigned int support_stereo :1; + unsigned int support_4k_120p :1; } caps; - unsigned int reserved2[9]; /* Reserved for future use, MUST BE 0. */ + unsigned int reserved2[10]; /* Reserved for future use, MUST BE 0. */ }; struct dwbc { @@ -166,8 +167,9 @@ struct dwbc { bool dwb_is_drc; int wb_src_plane_inst;/*hubp, mpcc, inst*/ uint32_t mask_id; - int otg_inst; - bool mvc_cfg; + int otg_inst; + bool mvc_cfg; + struct dc_dwb_params params; }; struct dwbc_funcs { @@ -192,6 +194,10 @@ struct dwbc_funcs { struct dwbc *dwbc, enum dwb_frame_capture_enable enable); + void (*dwb_set_scaler)( + struct dwbc *dwbc, + struct dc_dwb_params *params); + void (*set_stereo)( struct dwbc *dwbc, struct dwb_stereo_params *stereo_params); @@ -205,9 +211,11 @@ struct dwbc_funcs { struct dwbc *dwbc, struct dwb_warmup_params *warmup_params); - + bool (*dwb_get_mcifbuf_line)( + struct dwbc *dwbc, unsigned int *buf_idx, + unsigned int *cur_line, + unsigned int *over_run); #if defined(CONFIG_DRM_AMD_DC_FP) - void (*dwb_program_output_csc)( struct dwbc *dwbc, enum dc_color_space color_space, @@ -216,17 +224,17 @@ struct dwbc_funcs { bool (*dwb_ogam_set_output_transfer_func)( struct dwbc *dwbc, const struct dc_transfer_func *in_transfer_func_dwb_ogam); - +#endif //TODO: merge with output_transfer_func? bool (*dwb_ogam_set_input_transfer_func)( struct dwbc *dwbc, const struct dc_transfer_func *in_transfer_func_dwb_ogam); -#endif + + void (*get_drr_time_stamp)( + struct dwbc *dwbc, uint32_t *time_stamp); + bool (*get_dwb_status)( struct dwbc *dwbc); - void (*dwb_set_scaler)( - struct dwbc *dwbc, - struct dc_dwb_params *params); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h index dcae23faeee3..c80ebb407add 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h @@ -44,10 +44,11 @@ */ #define MAX_PIPES 6 #define MAX_PHANTOM_PIPES (MAX_PIPES / 2) +#define MAX_LINKS (MAX_PIPES * 2) #define MAX_DIG_LINK_ENCODERS 7 #define MAX_DWB_PIPES 1 #define MAX_HPO_DP2_ENCODERS 4 -#define MAX_HPO_DP2_LINK_ENCODERS 2 +#define MAX_HPO_DP2_LINK_ENCODERS 4 struct gamma_curve { uint32_t offset; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index dbe7afa9d3a2..af9183f5d69b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h @@ -163,12 +163,11 @@ struct link_encoder_funcs { enum signal_type (*get_dig_mode)( struct link_encoder *enc); + void (*set_dio_phy_mux)( struct link_encoder *enc, enum encoder_type_select sel, uint32_t hpo_inst); - void (*set_dig_output_mode)( - struct link_encoder *enc, uint8_t pix_per_container); }; /* diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index b72fb314d804..86c12cd6f47d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -50,11 +50,13 @@ struct dcn_watermarks { uint32_t usr_retraining_ns; }; -struct dcn_watermark_set { - struct dcn_watermarks a; - struct dcn_watermarks b; - struct dcn_watermarks c; - struct dcn_watermarks d; +union dcn_watermark_set { + struct { + struct dcn_watermarks a; + struct dcn_watermarks b; + struct dcn_watermarks c; + struct dcn_watermarks d; + }; // legacy }; struct dce_watermarks { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/optc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/optc.h index 9a8bf6ec70ea..8d32e525f05a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/optc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/optc.h @@ -93,6 +93,8 @@ struct dcn_otg_state { uint32_t vertical_interrupt1_line; uint32_t vertical_interrupt2_en; uint32_t vertical_interrupt2_line; + uint32_t otg_master_update_lock; + uint32_t otg_double_buffer_control; }; void optc1_read_otg_state(struct optc *optc1, struct dcn_otg_state *s); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index a15efadb9183..75b9ec21f297 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h @@ -178,10 +178,6 @@ struct stream_encoder_funcs { void (*stop_dp_info_packets)( struct stream_encoder *enc); - void (*reset_fifo)( - struct stream_encoder *enc - ); - void (*dp_blank)( struct dc_link *link, struct stream_encoder *enc); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index ffad8fe16c54..cd68ecc242c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -64,6 +64,12 @@ struct drr_params { bool immediate_flip; }; +struct long_vtotal_params { + uint32_t vertical_total_min; + uint32_t vertical_total_max; + uint32_t vertical_blank_start; +}; + #define LEFT_EYE_3D_PRIMARY_SURFACE 1 #define RIGHT_EYE_3D_PRIMARY_SURFACE 0 @@ -331,6 +337,7 @@ struct timing_generator_funcs { void (*init_odm)(struct timing_generator *tg); void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg); + void (*set_long_vtotal)(struct timing_generator *optc, const struct long_vtotal_params *params); void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg); }; diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/vpg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/vpg.h new file mode 100644 index 000000000000..51da368f5c3e --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/vpg.h @@ -0,0 +1,53 @@ +/* + * Copyright 2024 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: AMD + */ + +#ifndef __DC_VPG_H__ +#define __DC_VPG_H__ + +struct dc_context; +struct dc_info_packet; + +struct vpg; + +struct vpg_funcs { + void (*update_generic_info_packet)( + struct vpg *vpg, + uint32_t packet_index, + const struct dc_info_packet *info_packet, + bool immediate_update); + + void (*vpg_poweron)( + struct vpg *vpg); + + void (*vpg_powerdown)( + struct vpg *vpg); +}; + +struct vpg { + const struct vpg_funcs *funcs; + struct dc_context *ctx; + int inst; +}; + +#endif /* DC_INC_VPG_H_ */ \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index bf29fc58ea6a..7ab8ba5e23ed 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -288,7 +288,7 @@ struct link_service { struct dc_link *link, uint32_t coasting_vtotal); bool (*edp_replay_residency)(const struct dc_link *link, unsigned int *residency, const bool is_start, - const bool is_alpm); + const enum pr_residency_mode mode); bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link, const unsigned int *power_opts, uint32_t coasting_vtotal); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 77a60aa9f27b..361ad6b16b96 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -508,6 +508,17 @@ int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( struct resource_context *new_res_ctx, const struct resource_pool *pool); +/* + * Look for a free pipe in new resource context that is used as a secondary DPP + * pipe in current resource context. + * return - FREE_PIPE_INDEX_NOT_FOUND if free pipe is not found, otherwise + * pipe idx of the free pipe + */ +int resource_find_free_pipe_used_as_cur_sec_dpp( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool); + /* * Look for a free pipe in new resource context that is used as a secondary DPP * pipe in any MPCC combine in current resource context. @@ -573,13 +584,6 @@ bool get_temp_dp_link_res(struct dc_link *link, struct link_resource *link_res, struct dc_link_settings *link_settings); -#if defined(CONFIG_DRM_AMD_DC_FP) -struct hpo_dp_link_encoder *resource_get_hpo_dp_link_enc_for_det_lt( - const struct resource_context *res_ctx, - const struct resource_pool *pool, - const struct dc_link *link); -#endif - void reset_syncd_pipes_from_disabled_pipes(struct dc *dc, struct dc_state *context); @@ -615,4 +619,10 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc, struct pipe_ctx *pipe_ctx); bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream); + +/* Setup dc callbacks for dml2 + * @dc: the display core structure + * @dml2_options: struct to hold callbacks + */ +void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuration_options *dml2_options); #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c index 1c0d89e675da..bb576a9c5fdb 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c @@ -211,8 +211,12 @@ bool dce110_vblank_set(struct irq_service *irq_service, info->ext_id); uint8_t pipe_offset = dal_irq_src - IRQ_TYPE_VBLANK; - struct timing_generator *tg = - dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; + struct timing_generator *tg; + + if (pipe_offset >= MAX_PIPES) + return false; + + tg = dc->current_state->res_ctx.pipe_ctx[pipe_offset].stream_res.tg; if (enable) { if (!tg || !tg->funcs->arm_vert_intr(tg, 2)) { diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c index 22b24749c9d2..8d1a1cc94a8b 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c @@ -884,7 +884,7 @@ void dp_set_preferred_link_settings(struct dc *dc, { int i; struct pipe_ctx *pipe; - struct dc_stream_state *link_stream; + struct dc_stream_state *link_stream = 0; struct dc_link_settings store_settings = *link_setting; link->preferred_link_setting = store_settings; diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c index fbcd8fb58ea8..c8c55f196f8d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c +++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_trace.c @@ -24,7 +24,6 @@ */ #include "link_dp_trace.h" #include "link/protocols/link_dpcd.h" -#include "link.h" void dp_trace_init(struct dc_link *link) { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index b8c4a04dd175..0d523dc43d02 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -516,8 +516,8 @@ static void query_hdcp_capability(enum signal_type signal, struct dc_link *link) static void read_current_link_settings_on_detect(struct dc_link *link) { union lane_count_set lane_count_set = {0}; - uint8_t link_bw_set; - uint8_t link_rate_set; + uint8_t link_bw_set = 0; + uint8_t link_rate_set = 0; uint32_t read_dpcd_retry_cnt = 10; enum dc_status status = DC_ERROR_UNEXPECTED; int i; diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c index a72de44a5747..b53ad18dbfbc 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c @@ -55,6 +55,8 @@ #include "dccg.h" #include "clk_mgr.h" #include "atomfirmware.h" +#include "vpg.h" + #define DC_LOGGER \ dc_logger #define DC_LOGGER_INIT(logger) \ @@ -67,7 +69,6 @@ #define RETIMER_REDRIVER_INFO(...) \ DC_LOG_RETIMER_REDRIVER( \ __VA_ARGS__) -#include "dc/dcn30/dcn30_vpg.h" #define MAX_MTP_SLOT_COUNT 64 #define LINK_TRAINING_ATTEMPTS 4 @@ -127,7 +128,7 @@ void link_blank_dp_stream(struct dc_link *link, bool hw_init) if (link->ep_type == DISPLAY_ENDPOINT_PHY && link->link_enc->funcs->get_dig_frontend && link->link_enc->funcs->is_dig_enabled(link->link_enc)) { - unsigned int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc); + int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc); if (fe != ENGINE_ID_UNKNOWN) for (j = 0; j < dc->res_pool->stream_enc_count; j++) { @@ -725,7 +726,7 @@ static void set_avmute(struct pipe_ctx *pipe_ctx, bool enable) static void enable_mst_on_sink(struct dc_link *link, bool enable) { - unsigned char mstmCntl; + unsigned char mstmCntl = 0; core_link_read_dpcd(link, DP_MSTM_CTRL, &mstmCntl, 1); if (enable) @@ -803,7 +804,7 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) if (enable) { struct dsc_config dsc_cfg; - struct dsc_optc_config dsc_optc_cfg; + struct dsc_optc_config dsc_optc_cfg = {0}; enum optc_dsc_mode optc_dsc_mode; /* Enable DSC hw block */ @@ -1575,7 +1576,7 @@ static bool write_128b_132b_sst_payload_allocation_table( break; } } else { - union dpcd_rev dpcdRev; + union dpcd_rev dpcdRev = {0}; if (core_link_read_dpcd( link, @@ -2119,7 +2120,7 @@ static enum dc_status enable_link_dp_mst( struct pipe_ctx *pipe_ctx) { struct dc_link *link = pipe_ctx->stream->link; - unsigned char mstm_cntl; + unsigned char mstm_cntl = 0; /* sink signal type after MST branch is MST. Multiple MST sinks * share one link. Link DP PHY is enable or training only once. @@ -2285,6 +2286,7 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) struct dc_stream_state *stream = pipe_ctx->stream; struct dc_link *link = stream->sink->link; struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg; + enum dp_panel_mode panel_mode_dp = dp_get_panel_mode(link); DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); @@ -2311,6 +2313,8 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx) dc->hwss.disable_audio_stream(pipe_ctx); + edp_set_panel_assr(link, pipe_ctx, &panel_mode_dp, false); + update_psp_stream_config(pipe_ctx, true); dc->hwss.blank_stream(pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 289f5d133342..a01d0842bf8e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -992,7 +992,7 @@ enum dp_link_encoding mst_decide_link_encoding_format(const struct dc_link *link static void read_dp_device_vendor_id(struct dc_link *link) { - struct dp_device_vendor_id dp_id; + struct dp_device_vendor_id dp_id = {0}; /* read IEEE branch device id */ core_link_read_dpcd( @@ -1087,7 +1087,7 @@ static void get_active_converter_info( } if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { - uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/ + uint8_t det_caps[16] = {0}; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/ union dwnstream_port_caps_byte0 *port_caps = (union dwnstream_port_caps_byte0 *)det_caps; if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, @@ -1172,7 +1172,7 @@ static void get_active_converter_info( set_dongle_type(link->ddc, link->dpcd_caps.dongle_type); { - struct dp_sink_hw_fw_revision dp_hw_fw_revision; + struct dp_sink_hw_fw_revision dp_hw_fw_revision = {0}; core_link_read_dpcd( link, @@ -1242,7 +1242,7 @@ static void apply_usbc_combo_phy_reset_wa(struct dc_link *link, bool dp_overwrite_extended_receiver_cap(struct dc_link *link) { - uint8_t dpcd_data[16]; + uint8_t dpcd_data[16] = {0}; uint32_t read_dpcd_retry_cnt = 3; enum dc_status status = DC_ERROR_UNEXPECTED; union dp_downstream_port_present ds_port = { 0 }; @@ -1408,7 +1408,7 @@ static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id) static void retrieve_cable_id(struct dc_link *link) { - union dp_cable_id usbc_cable_id; + union dp_cable_id usbc_cable_id = {0}; link->dpcd_caps.cable_id.raw = 0; core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX, @@ -1475,7 +1475,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link) enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) { - uint8_t lttpr_dpcd_data[8]; + uint8_t lttpr_dpcd_data[8] = {0}; enum dc_status status; bool is_lttpr_present; @@ -1931,8 +1931,8 @@ void detect_edp_sink_caps(struct dc_link *link) uint32_t entry; uint32_t link_rate_in_khz; enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; - uint8_t backlight_adj_cap; - uint8_t general_edp_cap; + uint8_t backlight_adj_cap = 0; + uint8_t general_edp_cap = 0; retrieve_link_cap(link); link->dpcd_caps.edp_supported_link_rates_count = 0; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c index 5491b707cec8..68a8fd7f84d0 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c @@ -166,7 +166,7 @@ static uint8_t get_lowest_dpia_index(struct dc_link *link) uint8_t idx = 0xFF; int i; - for (i = 0; i < MAX_PIPES * 2; ++i) { + for (i = 0; i < MAX_LINKS; ++i) { if (!dc_struct->links[i] || dc_struct->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) @@ -196,7 +196,7 @@ static int get_host_router_total_dp_tunnel_bw(const struct dc *dc, uint8_t hr_in struct dc_link *link_dpia_primary, *link_dpia_secondary; int total_bw = 0; - for (uint8_t i = 0; i < (MAX_PIPES * 2) - 1; ++i) { + for (uint8_t i = 0; i < MAX_LINKS - 1; ++i) { if (!dc->links[i] || dc->links[i]->ep_type != DISPLAY_ENDPOINT_USB4_DPIA) continue; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index ba69874be5a4..0fcf0b8530ac 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -120,7 +120,7 @@ bool dp_parse_link_loss_status( static bool handle_hpd_irq_psr_sink(struct dc_link *link) { - union dpcd_psr_configuration psr_configuration; + union dpcd_psr_configuration psr_configuration = {0}; if (!link->psr_settings.psr_feature_enabled) return false; @@ -186,9 +186,9 @@ static bool handle_hpd_irq_psr_sink(struct dc_link *link) static void handle_hpd_irq_replay_sink(struct dc_link *link) { - union dpcd_replay_configuration replay_configuration; + union dpcd_replay_configuration replay_configuration = {0}; /*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/ - union psr_error_status replay_error_status; + union psr_error_status replay_error_status = {0}; if (!link->replay_settings.replay_feature_enabled) return; @@ -280,7 +280,7 @@ void dp_handle_link_loss(struct dc_link *link) static void read_dpcd204h_on_irq_hpd(struct dc_link *link, union hpd_irq_data *irq_data) { enum dc_status retval; - union lane_align_status_updated dpcd_lane_status_updated; + union lane_align_status_updated dpcd_lane_status_updated = {0}; retval = core_link_read_dpcd( link, @@ -320,7 +320,7 @@ enum dc_status dp_read_hpd_rx_irq_data( /* Read 14 bytes in a single read and then copy only the required fields. * This is more efficient than doing it in two separate AUX reads. */ - uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1]; + uint8_t tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI + 1] = {0}; retval = core_link_read_dpcd( link, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c index e538c67d3ed9..1818970b8eaf 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c @@ -1071,7 +1071,7 @@ enum dc_status dpcd_set_link_settings( * MUX chip gets link rate set back before link training. */ if (link->connector_signal == SIGNAL_TYPE_EDP) { - uint8_t supported_link_rates[16]; + uint8_t supported_link_rates[16] = {0}; core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, supported_link_rates, sizeof(supported_link_rates)); @@ -1587,21 +1587,7 @@ bool perform_link_training_with_retries( msleep(delay_dp_power_up_in_ms); } - if (panel_mode == DP_PANEL_MODE_EDP) { - struct cp_psp *cp_psp = &stream->ctx->cp_psp; - - if (cp_psp && cp_psp->funcs.enable_assr) { - /* ASSR is bound to fail with unsigned PSP - * verstage used during devlopment phase. - * Report and continue with eDP panel mode to - * perform eDP link training with right settings - */ - bool result; - result = cp_psp->funcs.enable_assr(cp_psp->handle, link); - if (!result && link->panel_mode != DP_PANEL_MODE_EDP) - panel_mode = DP_PANEL_MODE_DEFAULT; - } - } + edp_set_panel_assr(link, pipe_ctx, &panel_mode, true); dp_set_panel_mode(link, panel_mode); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c index 5d36bab0029c..edb21d21952a 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c @@ -291,7 +291,7 @@ static enum link_training_result dpia_training_cr_non_transparent( { enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ - enum dc_status status; + enum dc_status status = DC_ERROR_UNEXPECTED; uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */ uint32_t retry_count = 0; uint32_t wait_time_microsec = TRAINING_AUX_RD_INTERVAL; /* From DP spec, CR read interval is always 100us. */ @@ -617,7 +617,7 @@ static enum link_training_result dpia_training_eq_non_transparent( enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ; uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */ uint32_t retries_eq = 0; - enum dc_status status; + enum dc_status status = DC_ERROR_UNEXPECTED; enum dc_dp_training_pattern tr_pattern; uint32_t wait_time_microsec = 0; enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c index c5de6ed5bf58..a72c898b64fa 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c @@ -130,7 +130,7 @@ static uint32_t dpcd_get_next_partition_size(const uint32_t address, const uint3 * XXX: Do not allow any two address ranges in this array to overlap */ static const struct dpcd_address_range mandatory_dpcd_blocks[] = { - { DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT }}; + { DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, DP_PHY_REPEATER_128B132B_RATES }}; /* * extend addresses to read all mandatory blocks together diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index 3baa2bdd6dd6..ad9aca790dd7 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -38,6 +38,7 @@ #include "dc/dc_dmub_srv.h" #include "dce/dmub_replay.h" #include "abm.h" +#include "resource.h" #define DC_LOGGER \ link->ctx->logger #define DC_LOGGER_INIT(logger) @@ -320,8 +321,8 @@ bool edp_is_ilr_optimization_required(struct dc_link *link, struct dc_crtc_timing *crtc_timing) { struct dc_link_settings link_setting; - uint8_t link_bw_set; - uint8_t link_rate_set; + uint8_t link_bw_set = 0; + uint8_t link_rate_set = 0; uint32_t req_bw; union lane_count_set lane_count_set = {0}; @@ -1055,7 +1056,7 @@ bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal) } bool edp_replay_residency(const struct dc_link *link, - unsigned int *residency, const bool is_start, const bool is_alpm) + unsigned int *residency, const bool is_start, const enum pr_residency_mode mode) { struct dc *dc = link->ctx->dc; struct dmub_replay *replay = dc->res_pool->replay; @@ -1064,8 +1065,11 @@ bool edp_replay_residency(const struct dc_link *link, if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst)) return false; + if (!residency) + return false; + if (replay != NULL && link->replay_settings.replay_feature_enabled) - replay->funcs->replay_residency(replay, panel_inst, residency, is_start, is_alpm); + replay->funcs->replay_residency(replay, panel_inst, residency, is_start, mode); else *residency = 0; @@ -1145,3 +1149,66 @@ int edp_get_target_backlight_pwm(const struct dc_link *link) return (int) abm->funcs->get_target_backlight(abm); } + +static void edp_set_assr_enable(const struct dc *pDC, struct dc_link *link, + struct link_resource *link_res, bool enable) +{ + union dmub_rb_cmd cmd; + bool use_hpo_dp_link_enc = false; + uint8_t link_enc_index = 0; + uint8_t phy_type = 0; + uint8_t phy_id = 0; + + if (!pDC->config.use_assr_psp_message) + return; + + memset(&cmd, 0, sizeof(cmd)); + + link_enc_index = link->link_enc->transmitter - TRANSMITTER_UNIPHY_A; + + if (link_res->hpo_dp_link_enc) { + link_enc_index = link_res->hpo_dp_link_enc->inst; + use_hpo_dp_link_enc = true; + } + + if (enable) + phy_type = ((dp_get_panel_mode(link) == DP_PANEL_MODE_EDP) ? 1 : 0); + + phy_id = resource_transmitter_to_phy_idx(pDC, link->link_enc->transmitter); + + cmd.assr_enable.header.type = DMUB_CMD__PSP; + cmd.assr_enable.header.sub_type = DMUB_CMD__PSP_ASSR_ENABLE; + cmd.assr_enable.assr_data.enable = enable; + cmd.assr_enable.assr_data.phy_port_type = phy_type; + cmd.assr_enable.assr_data.phy_port_id = phy_id; + cmd.assr_enable.assr_data.link_enc_index = link_enc_index; + cmd.assr_enable.assr_data.hpo_mode = use_hpo_dp_link_enc; + + dc_wake_and_execute_dmub_cmd(pDC->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +} + +void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx, + enum dp_panel_mode *panel_mode, bool enable) +{ + struct link_resource *link_res = &pipe_ctx->link_res; + struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp; + + if (*panel_mode != DP_PANEL_MODE_EDP) + return; + + if (link->dc->config.use_assr_psp_message) { + edp_set_assr_enable(link->dc, link, link_res, enable); + } else if (cp_psp && cp_psp->funcs.enable_assr && enable) { + /* ASSR is bound to fail with unsigned PSP + * verstage used during devlopment phase. + * Report and continue with eDP panel mode to + * perform eDP link training with right settings + */ + bool result; + + result = cp_psp->funcs.enable_assr(cp_psp->handle, link); + + if (!result && link->panel_mode != DP_PANEL_MODE_EDP) + *panel_mode = DP_PANEL_MODE_DEFAULT; + } +} diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index a158c6234d42..cb6d95cc36e4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -61,7 +61,7 @@ bool edp_send_replay_cmd(struct dc_link *link, union dmub_replay_cmd_set *cmd_data); bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal); bool edp_replay_residency(const struct dc_link *link, - unsigned int *residency, const bool is_start, const bool is_alpm); + unsigned int *residency, const bool is_start, const enum pr_residency_mode mode); bool edp_get_replay_state(const struct dc_link *link, uint64_t *state); bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link, const unsigned int *power_opts, uint32_t coasting_vtotal); @@ -76,4 +76,6 @@ bool edp_receiver_ready_T9(struct dc_link *link); bool edp_receiver_ready_T7(struct dc_link *link); bool edp_power_alpm_dpcd_enable(struct dc_link *link, bool enable); void edp_set_panel_power(struct dc_link *link, bool powerOn); +void edp_set_panel_assr(struct dc_link *link, struct pipe_ctx *pipe_ctx, + enum dp_panel_mode *panel_mode, bool enable); #endif /* __DC_LINK_EDP_POWER_CONTROL_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c index e3d729ab5b9f..caa617883f62 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hpd.c @@ -35,7 +35,7 @@ bool link_get_hpd_state(struct dc_link *link) { - uint32_t state; + uint32_t state = 0; dal_gpio_lock_pin(link->hpd_gpio); dal_gpio_get_value(link->hpd_gpio, &state); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c index 0e8f4f36c87c..5574bc628053 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c @@ -945,10 +945,19 @@ void optc1_set_drr( OTG_FORCE_LOCK_ON_EVENT, 0, OTG_SET_V_TOTAL_MIN_MASK_EN, 0, OTG_SET_V_TOTAL_MIN_MASK, 0); - } - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); + // Setup manual flow control for EOF via TRIG_A + optc->funcs->setup_manual_trigger(optc); + + } else { + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + optc->funcs->set_vtotal_min_max(optc, 0, 0); + } } void optc1_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max) @@ -1383,6 +1392,9 @@ void optc1_read_otg_state(struct optc *optc1, REG_GET(OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, &s->vertical_interrupt2_line); + + s->otg_master_update_lock = REG_READ(OTG_MASTER_UPDATE_LOCK); + s->otg_double_buffer_control = REG_READ(OTG_DOUBLE_BUFFER_CONTROL); } bool optc1_get_otg_active_size(struct timing_generator *optc, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h index 6c2e84d3967f..2f3bd7648ba7 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h @@ -129,6 +129,8 @@ struct dcn_optc_registers { uint32_t OTG_V_TOTAL_MID; uint32_t OTG_V_TOTAL_MIN; uint32_t OTG_V_TOTAL_CONTROL; + uint32_t OTG_V_COUNT_STOP_CONTROL; + uint32_t OTG_V_COUNT_STOP_CONTROL2; uint32_t OTG_TRIGA_CNTL; uint32_t OTG_TRIGA_MANUAL_TRIG; uint32_t OTG_MANUAL_FLOW_CONTROL; @@ -515,12 +517,15 @@ struct dcn_optc_registers { type MANUAL_FLOW_CONTROL;\ type MANUAL_FLOW_CONTROL_SEL; +#define V_TOTAL_REGS(type) + #define TG_REG_FIELD_LIST(type) \ TG_REG_FIELD_LIST_DCN1_0(type)\ type OTG_V_SYNC_MODE;\ type OTG_DRR_TRIGGER_WINDOW_START_X;\ type OTG_DRR_TRIGGER_WINDOW_END_X;\ type OTG_DRR_V_TOTAL_CHANGE_LIMIT;\ + V_TOTAL_REGS(type)\ type OTG_OUT_MUX;\ type OTG_M_CONST_DTO_PHASE;\ type OTG_M_CONST_DTO_MODULO;\ @@ -581,7 +586,9 @@ struct dcn_optc_registers { type OTG_CRC1_WINDOWB_X_END_READBACK;\ type OTG_CRC1_WINDOWB_Y_START_READBACK;\ type OTG_CRC1_WINDOWB_Y_END_READBACK;\ - type OPTC_FGCG_REP_DIS; + type OPTC_FGCG_REP_DIS;\ + type OTG_V_COUNT_STOP;\ + type OTG_V_COUNT_STOP_TIMER; struct dcn_optc_shift { TG_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c index 58bdbd859bf9..d6f095b4555d 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c @@ -462,16 +462,6 @@ void optc2_setup_manual_trigger(struct timing_generator *optc) { struct optc *optc1 = DCN10TG_FROM_TG(optc); - /* Set the min/max selectors unconditionally so that - * DMCUB fw may change OTG timings when necessary - * TODO: Remove the w/a after fixing the issue in DMCUB firmware - */ - REG_UPDATE_4(OTG_V_TOTAL_CONTROL, - OTG_V_TOTAL_MIN_SEL, 1, - OTG_V_TOTAL_MAX_SEL, 1, - OTG_FORCE_LOCK_ON_EVENT, 0, - OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - REG_SET_8(OTG_TRIGA_CNTL, 0, OTG_TRIGA_SOURCE_SELECT, 21, OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index f07a4c7e48bc..52eab8fccb7f 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -267,9 +267,6 @@ static void optc32_setup_manual_trigger(struct timing_generator *optc) OTG_V_TOTAL_MAX_SEL, 1, OTG_FORCE_LOCK_ON_EVENT, 0, OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); } } diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c index 5b1547508850..d393be30dff8 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -32,6 +32,7 @@ #include "reg_helper.h" #include "dc.h" #include "dcn_calc_math.h" +#include "dc_dmub_srv.h" #define REG(reg)\ optc1->tg_regs->reg @@ -213,6 +214,167 @@ static bool optc35_configure_crc(struct timing_generator *optc, return true; } +static void optc35_setup_manual_trigger(struct timing_generator *optc) +{ + if (!optc || !optc->ctx) + return; + + struct optc *optc1 = DCN10TG_FROM_TG(optc); + struct dc *dc = optc->ctx->dc; + + if (dc->caps.dmub_caps.mclk_sw && !dc->debug.disable_fams) + dc_dmub_srv_set_drr_manual_trigger_cmd(dc, optc->inst); + else { + /* + * MIN_MASK_EN is gone and MASK is now always enabled. + * + * To get it to it work with manual trigger we need to make sure + * we program the correct bit. + */ + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ + + // Setup manual flow control for EOF via TRIG_A + if (optc->funcs && optc->funcs->setup_manual_trigger) + optc->funcs->setup_manual_trigger(optc); + } +} + +void optc35_set_drr( + struct timing_generator *optc, + const struct drr_params *params) +{ + if (!optc || !params) + return; + + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t max_otg_v_total = optc1->max_v_total - 1; + + if (params != NULL && + params->vertical_total_max > 0 && + params->vertical_total_min > 0) { + + if (params->vertical_total_mid != 0) { + + REG_SET(OTG_V_TOTAL_MID, 0, + OTG_V_TOTAL_MID, params->vertical_total_mid - 1); + + REG_UPDATE_2(OTG_V_TOTAL_CONTROL, + OTG_VTOTAL_MID_REPLACING_MAX_EN, 1, + OTG_VTOTAL_MID_FRAME_NUM, + (uint8_t)params->vertical_total_mid_frame_num); + + } + + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, + params->vertical_total_min - 1, params->vertical_total_max - 1); + optc35_setup_manual_trigger(optc); + } else { + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, 0, 0); + } + + REG_WRITE(OTG_V_COUNT_STOP_CONTROL, max_otg_v_total); + REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, 0); +} + +static void optc35_set_long_vtotal( + struct timing_generator *optc, + const struct long_vtotal_params *params) +{ + if (!optc || !params) + return; + + struct optc *optc1 = DCN10TG_FROM_TG(optc); + uint32_t vcount_stop_timer = 0, vcount_stop = 0; + uint32_t max_otg_v_total = optc1->max_v_total - 1; + + if (params->vertical_total_min <= max_otg_v_total && params->vertical_total_max <= max_otg_v_total) + return; + + if (params->vertical_total_max == 0 || params->vertical_total_min == 0) { + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, 0, 0); + } else if (params->vertical_total_max == params->vertical_total_min) { + vcount_stop = params->vertical_blank_start; + vcount_stop_timer = params->vertical_total_max - max_otg_v_total; + + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_V_TOTAL_MIN_SEL, 1, + OTG_V_TOTAL_MAX_SEL, 1, + OTG_FORCE_LOCK_ON_EVENT, 0, + OTG_SET_V_TOTAL_MIN_MASK, 0); + + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, max_otg_v_total, max_otg_v_total); + + REG_WRITE(OTG_V_COUNT_STOP_CONTROL, vcount_stop); + REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, vcount_stop_timer); + } else { + // Variable rate, keep DRR trigger mask + if (params->vertical_total_min > max_otg_v_total) { + // cannot be supported + // If MAX_OTG_V_COUNT < DRR trigger < v_total_min < v_total_max, + // DRR trigger will drop the vtotal counting directly to a new frame. + // But it should trigger between v_total_min and v_total_max. + ASSERT(0); + + REG_UPDATE_4(OTG_V_TOTAL_CONTROL, + OTG_SET_V_TOTAL_MIN_MASK, 0, + OTG_V_TOTAL_MIN_SEL, 0, + OTG_V_TOTAL_MAX_SEL, 0, + OTG_FORCE_LOCK_ON_EVENT, 0); + + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, 0, 0); + + REG_WRITE(OTG_V_COUNT_STOP_CONTROL, max_otg_v_total); + REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, 0); + } else { + // For total_min <= MAX_OTG_V_COUNT and total_max > MAX_OTG_V_COUNT + vcount_stop = params->vertical_total_min; + vcount_stop_timer = params->vertical_total_max - max_otg_v_total; + + // Example: + // params->vertical_total_min 1000 + // params->vertical_total_max 2000 + // MAX_OTG_V_COUNT_STOP = 1500 + // + // If DRR event not happened, + // time 0,1,2,3,4,...1000,1001,........,1500,1501,1502, ...1999 + // vcount 0,1,2,3,4....1000...................,1001,1002,1003,...1399 + // vcount2 0,1,2,3,4,..499, + // else (DRR event happened, ex : at line 1004) + // time 0,1,2,3,4,...1000,1001.....1004, 0 + // vcount 0,1,2,3,4....1000,.............. 0 (new frame) + // vcount2 0,1,2, 3, - + if (optc->funcs && optc->funcs->set_vtotal_min_max) + optc->funcs->set_vtotal_min_max(optc, + params->vertical_total_min - 1, max_otg_v_total); + optc35_setup_manual_trigger(optc); + + REG_WRITE(OTG_V_COUNT_STOP_CONTROL, vcount_stop); + REG_WRITE(OTG_V_COUNT_STOP_CONTROL2, vcount_stop_timer); + } + } +} + static struct timing_generator_funcs dcn35_tg_funcs = { .validate_timing = optc1_validate_timing, .program_timing = optc1_program_timing, @@ -245,7 +407,7 @@ static struct timing_generator_funcs dcn35_tg_funcs = { .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable, .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable, .enable_optc_clock = optc1_enable_optc_clock, - .set_drr = optc31_set_drr, + .set_drr = optc35_set_drr, .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal, .set_vtotal_min_max = optc1_set_vtotal_min_max, .set_static_screen_control = optc1_set_static_screen_control, @@ -275,6 +437,7 @@ static struct timing_generator_funcs dcn35_tg_funcs = { .setup_manual_trigger = optc2_setup_manual_trigger, .get_hw_timing = optc1_get_hw_timing, .init_odm = optc3_init_odm, + .set_long_vtotal = optc35_set_long_vtotal, }; void dcn35_timing_generator_init(struct optc *optc1) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h index 1f422e4c468f..d077e2392379 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.h @@ -65,10 +65,14 @@ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG_CRC1_WINDOWB_X_END_READBACK, mask_sh),\ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_START_READBACK, mask_sh),\ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG_CRC1_WINDOWB_Y_END_READBACK, mask_sh),\ - SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh) + SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh),\ + SF(OTG0_OTG_V_COUNT_STOP_CONTROL, OTG_V_COUNT_STOP, mask_sh),\ + SF(OTG0_OTG_V_COUNT_STOP_CONTROL2, OTG_V_COUNT_STOP_TIMER, mask_sh) void dcn35_timing_generator_init(struct optc *optc1); void dcn35_timing_generator_set_fgcg(struct optc *optc1, bool enable); +void optc35_set_drr(struct timing_generator *optc, const struct drr_params *params); + #endif /* __DC_OPTC_DCN35_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile index 184b1f23aa77..db9048974d74 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/Makefile +++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile @@ -102,10 +102,6 @@ AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN21) ############################################################################### -############################################################################### - -############################################################################### - RESOURCE_DCN30 = dcn30_resource.o AMD_DAL_RESOURCE_DCN30 = $(addprefix $(AMDDALPATH)/dc/resource/dcn30/,$(RESOURCE_DCN30)) @@ -202,6 +198,4 @@ AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN351) ############################################################################### -############################################################################### - endif diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c index d1edac46c9a0..88afb2a30eef 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c @@ -864,8 +864,6 @@ static struct clock_source *find_matching_pll( default: return NULL; } - - return NULL; } static enum dc_status build_mapped_resource( diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c index 20662edd0ae4..621825a51f46 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c @@ -1060,7 +1060,7 @@ static bool dce120_resource_construct( struct irq_service_init_data irq_init_data; static const struct resource_create_funcs *res_funcs; bool is_vg20 = ASICREV_IS_VEGA20_P(ctx->asic_id.hw_internal_rev); - uint32_t pipe_fuses; + uint32_t pipe_fuses = 0; ctx->dc_bios->regs = &bios_regs; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c index 35a2cce0c2b8..56ee45e12b46 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c @@ -56,7 +56,6 @@ #include "dce/dce_aux.h" #include "dce/dce_abm.h" #include "dce/dce_i2c.h" -/* TODO remove this include */ #ifndef mmMC_HUB_RDREQ_DMIF_LIMIT #include "gmc/gmc_7_1_d.h" diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c index d08d10969251..563c5eec83ff 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c @@ -513,7 +513,7 @@ static const struct dc_plane_cap plane_cap = { .argb8888 = true, .nv12 = true, .fp16 = true, - .p010 = true + .p010 = false }, .max_upscale_factor = { @@ -569,6 +569,7 @@ static const struct dc_debug_options debug_defaults_diags = { .disable_pplib_clock_request = true, .disable_pplib_wm_range = true, .underflow_assert_delay_us = 0xFFFFFFFF, + .enable_legacy_fast_update = true, }; static void dcn10_dpp_destroy(struct dpp **dpp) @@ -1631,6 +1632,7 @@ static bool dcn10_resource_construct( /* valid pipe num */ pool->base.pipe_count = j; pool->base.timing_generator_count = j; + pool->base.mpcc_count = j; /* within dml lib, it is hard code to 4. If ASIC pipe is fused, * the value may be changed diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c index a2387cea1af9..6406d31ceefe 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c @@ -62,6 +62,9 @@ #include "dcn20/dcn20_vmid.h" #include "dce/dce_panel_cntl.h" +#include "dcn20/dcn20_dwb.h" +#include "dcn20/dcn20_mmhubbub.h" + #include "navi10_ip_offset.h" #include "dcn/dcn_2_0_0_offset.h" @@ -71,9 +74,6 @@ #include "nbio/nbio_2_3_offset.h" -#include "dcn20/dcn20_dwb.h" -#include "dcn20/dcn20_mmhubbub.h" - #include "mmhub/mmhub_2_0_0_offset.h" #include "mmhub/mmhub_2_0_0_sh_mask.h" @@ -83,11 +83,10 @@ #include "dce/dce_aux.h" #include "dce/dce_i2c.h" #include "vm_helper.h" + #include "link_enc_cfg.h" - -#include "amdgpu_socbb.h" - #include "link.h" + #define DC_LOGGER_INIT(logger) #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL @@ -1282,8 +1281,13 @@ void dcn20_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx) static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx) { + struct resource_pool *pool = pipe_ctx->stream->ctx->dc->res_pool; - dcn20_build_pipe_pix_clk_params(pipe_ctx); + if (pool->funcs->build_pipe_pix_clk_params) { + pool->funcs->build_pipe_pix_clk_params(pipe_ctx); + } else { + dcn20_build_pipe_pix_clk_params(pipe_ctx); + } pipe_ctx->stream->clamping.pixel_encoding = pipe_ctx->stream->timing.pixel_encoding; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c index 914b234d7f6b..070a4efb308b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c @@ -55,7 +55,6 @@ #include "dce110/dce110_resource.h" #include "dce/dce_aux.h" #include "dce/dce_i2c.h" -#include "dcn201/dcn201_hubbub.h" #include "dcn10/dcn10_resource.h" #include "cyan_skillfish_ip_offset.h" @@ -182,6 +181,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn201_soc = { .socclk_mhz = 1254.0, .dram_speed_mts = 14000.0, }, + /* state4 is not an actual state, just defines unsupported for dml*/ { .state = 4, .dscclk_mhz = 400.0, @@ -566,6 +566,8 @@ static const struct resource_caps res_cap_dnc201 = { .num_audio = 2, .num_stream_encoder = 2, .num_pll = 2, + .num_dwb = 0, + .num_dsc = 0, .num_ddc = 2, }; @@ -612,7 +614,7 @@ static const struct dc_debug_options debug_defaults_drv = { .scl_reset_length10 = true, .sanity_checks = false, .underflow_assert_delay_us = 0xFFFFFFFF, - .enable_tri_buf = false, + .enable_tri_buf = true, .enable_legacy_fast_update = true, .using_dml2 = false, }; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c index 65d337731f56..8663cbc3d1cf 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c @@ -581,32 +581,6 @@ static const struct resource_caps res_cap_rn = { .num_dsc = 3, }; -#ifdef DIAGS_BUILD -static const struct resource_caps res_cap_rn_FPGA_4pipe = { - .num_timing_generator = 4, - .num_opp = 4, - .num_video_plane = 4, - .num_audio = 7, - .num_stream_encoder = 4, - .num_pll = 4, - .num_dwb = 1, - .num_ddc = 4, - .num_dsc = 0, -}; - -static const struct resource_caps res_cap_rn_FPGA_2pipe_dsc = { - .num_timing_generator = 2, - .num_opp = 2, - .num_video_plane = 2, - .num_audio = 7, - .num_stream_encoder = 2, - .num_pll = 4, - .num_dwb = 1, - .num_ddc = 4, - .num_dsc = 2, -}; -#endif - static const struct dc_plane_cap plane_cap = { .type = DC_PLANE_TYPE_DCN_UNIVERSAL, .per_pixel_alpha = true, @@ -1415,16 +1389,11 @@ static bool dcn21_resource_construct( struct dc_context *ctx = dc->ctx; struct irq_service_init_data init_data; uint32_t pipe_fuses = read_pipe_fuses(ctx); - uint32_t num_pipes; + uint32_t num_pipes = 0; ctx->dc_bios->regs = &bios_regs; pool->base.res_cap = &res_cap_rn; -#ifdef DIAGS_BUILD - if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - //pool->base.res_cap = &res_cap_nv10_FPGA_2pipe_dsc; - pool->base.res_cap = &res_cap_rn_FPGA_4pipe; -#endif pool->base.funcs = &dcn21_res_pool_funcs; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c index ecc477ef8e3b..f35cc307830b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c @@ -1639,7 +1639,7 @@ noinline bool dcn30_internal_validate_bw( int split[MAX_PIPES] = { 0 }; bool merge[MAX_PIPES] = { false }; bool newly_split[MAX_PIPES] = { false }; - int pipe_cnt, i, pipe_idx, vlevel; + int pipe_cnt, i, pipe_idx, vlevel = 0; struct vba_vars_st *vba = &context->bw_ctx.dml.vba; ASSERT(pipes); @@ -2050,6 +2050,9 @@ bool dcn30_validate_bandwidth(struct dc *dc, BW_VAL_TRACE_COUNT(); + if (!pipes) + goto validate_fail; + DC_FP_START(); out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); DC_FP_END(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c index 25cd6236b054..8bc1bcaeaa47 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c @@ -1143,7 +1143,7 @@ static bool dcn303_resource_construct( int i; struct dc_context *ctx = dc->ctx; struct irq_service_init_data init_data; - struct ddc_service_init_data ddc_init_data; + struct ddc_service_init_data ddc_init_data = {0}; ctx->dc_bios->regs = &bios_regs; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c index 04d142f97474..d4c3e2754f51 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c @@ -75,7 +75,6 @@ #include "dcn30/dcn30_dwb.h" #include "dcn30/dcn30_mmhubbub.h" -// TODO: change include headers /amd/include/asic_reg after upstream #include "yellow_carp_offset.h" #include "dcn/dcn_3_1_2_offset.h" #include "dcn/dcn_3_1_2_sh_mask.h" @@ -892,7 +891,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_z10 = true, .enable_legacy_fast_update = true, .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .dml_hostvm_override = DML_HOSTVM_OVERRIDE_FALSE, + .dml_hostvm_override = DML_HOSTVM_NO_OVERRIDE, .using_dml2 = false, }; @@ -1311,6 +1310,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], @@ -1645,7 +1646,7 @@ int dcn31_populate_dml_pipes_from_context( { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; bool upscaled = false; DC_FP_START(); @@ -1767,11 +1768,14 @@ bool dcn31_validate_bandwidth(struct dc *dc, BW_VAL_TRACE_COUNT(); + if (!pipes) + goto validate_fail; + DC_FP_START(); out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate, true); DC_FP_END(); - // Disable fast_validate to set min dcfclk in alculate_wm_and_dlg + // Disable fast_validate to set min dcfclk in calculate_wm_and_dlg if (pipe_cnt == 0) fast_validate = false; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c index c97391edb5ff..ff50f43e4c00 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c @@ -925,27 +925,10 @@ static const struct dc_debug_options debug_defaults_drv = { }, .seamless_boot_odm_combine = true, + .enable_legacy_fast_update = true, .using_dml2 = false, }; -static const struct dc_debug_options debug_defaults_diags = { - .disable_dmcu = true, - .force_abm_enable = false, - .timing_trace = true, - .clock_trace = true, - .disable_dpp_power_gate = true, - .disable_hubp_power_gate = true, - .disable_clock_gate = true, - .disable_pplib_clock_request = true, - .disable_pplib_wm_range = true, - .disable_stutter = false, - .scl_reset_length10 = true, - .dwb_fi_phase = -1, // -1 = disable - .dmub_command_table = true, - .enable_tri_buf = true, - .use_max_lb = true -}; - static const struct dc_panel_config panel_config_defaults = { .psr = { .disable_psr = false, @@ -1384,6 +1367,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], @@ -1744,6 +1729,9 @@ bool dcn314_validate_bandwidth(struct dc *dc, BW_VAL_TRACE_COUNT(); + if (!pipes) + goto validate_fail; + if (filter_modes_for_single_channel_workaround(dc, context)) goto validate_fail; @@ -1938,8 +1926,6 @@ static bool dcn314_resource_construct( if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->debug = debug_defaults_drv; - else - dc->debug = debug_defaults_diags; /* Disable pipe power gating */ dc->debug.disable_dpp_power_gate = true; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c index 515ba435f759..4ce0f4bf1d9b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c @@ -1309,6 +1309,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c index b9753d4606f8..5fd52c5fcee4 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c @@ -125,7 +125,6 @@ #include "link_enc_cfg.h" #define DCN3_16_MAX_DET_SIZE 384 -#define DCN3_16_MIN_COMPBUF_SIZE_KB 128 #define DCN3_16_CRB_SEGMENT_SIZE_KB 64 enum dcn31_clk_src_array_id { @@ -1306,6 +1305,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ hpo_dp_link_encoder31_construct(hpo_dp_enc31, ctx, inst, &hpo_dp_link_enc_regs[inst], @@ -1614,7 +1615,7 @@ static int dcn316_populate_dml_pipes_from_context( { int i, pipe_cnt; struct resource_context *res_ctx = &context->res_ctx; - struct pipe_ctx *pipe; + struct pipe_ctx *pipe = 0; const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB; DC_FP_START(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index ce1754cc1f46..abd76345d1e4 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -1304,6 +1304,8 @@ static struct hpo_dp_link_encoder *dcn32_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ #undef REG_STRUCT #define REG_STRUCT hpo_dp_link_enc_regs @@ -1751,6 +1753,9 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val BW_VAL_TRACE_COUNT(); + if (!pipes) + goto validate_fail; + DC_FP_START(); out = dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate); DC_FP_END(); @@ -1799,7 +1804,9 @@ bool dcn32_validate_bandwidth(struct dc *dc, bool out = false; if (dc->debug.using_dml2) - out = dml2_validate(dc, context, fast_validate); + out = dml2_validate(dc, context, + context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, + fast_validate); else out = dml1_validate(dc, context, fast_validate); return out; @@ -1815,9 +1822,48 @@ int dcn32_populate_dml_pipes_from_context( struct pipe_ctx *pipe = NULL; bool subvp_in_use = false; struct dc_crtc_timing *timing; + int subvp_main_pipe_index = -1; + enum mall_stream_type mall_type; + bool single_display_subvp = false; + struct dc_stream_state *stream = NULL; + int num_subvp_main = 0; + int num_subvp_phantom = 0; + int num_subvp_none = 0; + int odm_slice_count; dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate); + /* For single display subvp, look for subvp main so if we have phantom + * pipe, we can set odm policy to match main pipe + */ + for (i = 0; i < context->stream_count; i++) { + stream = context->streams[i]; + mall_type = dc_state_get_stream_subvp_type(context, stream); + if (mall_type == SUBVP_MAIN) + num_subvp_main++; + else if (mall_type == SUBVP_PHANTOM) + num_subvp_phantom++; + else + num_subvp_none++; + } + if (num_subvp_main == 1 && num_subvp_phantom == 1 && num_subvp_none == 0) + single_display_subvp = true; + + if (single_display_subvp) { + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { + pipe = &res_ctx->pipe_ctx[i]; + if (!res_ctx->pipe_ctx[i].stream) + continue; + + mall_type = dc_state_get_pipe_subvp_type(context, pipe); + if (mall_type == SUBVP_MAIN) { + if (resource_is_pipe_type(pipe, OTG_MASTER)) + subvp_main_pipe_index = i; + } + pipe_cnt++; + } + } + for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) { if (!res_ctx->pipe_ctx[i].stream) @@ -1832,7 +1878,21 @@ int dcn32_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch; if (dc->config.enable_windowed_mpo_odm && dc->debug.enable_single_display_2to1_odm_policy) { - switch (resource_get_odm_slice_count(pipe)) { + /* For single display subvp, if pipe is phantom pipe, + * then copy odm policy from subvp main pipe + */ + mall_type = dc_state_get_pipe_subvp_type(context, pipe); + if (single_display_subvp && (mall_type == SUBVP_PHANTOM)) { + if (subvp_main_pipe_index < 0) { + odm_slice_count = -1; + ASSERT(0); + } else { + odm_slice_count = resource_get_odm_slice_count(&res_ctx->pipe_ctx[subvp_main_pipe_index]); + } + } else { + odm_slice_count = resource_get_odm_slice_count(pipe); + } + switch (odm_slice_count) { case 2: pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_2to1; break; @@ -1845,6 +1905,7 @@ int dcn32_populate_dml_pipes_from_context( } else { pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal; } + pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet pipes[pipe_cnt].pipe.src.unbounded_req_mode = false; pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19; @@ -1912,6 +1973,22 @@ int dcn32_populate_dml_pipes_from_context( return pipe_cnt; } +unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned int total_size_in_mall_bytes) +{ + uint32_t cache_lines_used, lines_per_way, total_cache_lines, num_ways; + + /* add 2 lines for worst case alignment */ + cache_lines_used = total_size_in_mall_bytes / dc->caps.cache_line_size + 2; + + total_cache_lines = dc->caps.max_cab_allocation_bytes / dc->caps.cache_line_size; + lines_per_way = total_cache_lines / dc->caps.cache_num_ways; + num_ways = cache_lines_used / lines_per_way; + if (cache_lines_used % lines_per_way > 0) + num_ways++; + + return num_ways; +} + static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn20_get_dcc_compression_cap, .get_subvp_en = dcn32_subvp_in_use, @@ -1929,10 +2006,20 @@ void dcn32_calculate_wm_and_dlg(struct dc *dc, struct dc_state *context, static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct dml2_configuration_options dml2_opt = dc->dml2_options; + DC_FP_START(); + dcn32_update_bw_bounding_box_fpu(dc, bw_params); + + dml2_opt.use_clock_dc_limits = false; if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2) - dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2); + dml2_reinit(dc, &dml2_opt, &dc->current_state->bw_ctx.dml2); + + dml2_opt.use_clock_dc_limits = true; + if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source) + dml2_reinit(dc, &dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source); + DC_FP_END(); } @@ -1960,6 +2047,7 @@ static struct resource_funcs dcn32_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) @@ -2048,7 +2136,8 @@ static bool dcn32_resource_construct( dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; dc->caps.mall_size_per_mem_channel = 4; - dc->caps.mall_size_total = 0; + /* total size = mall per channel * num channels * 1024 * 1024 */ + dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576; dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; dc->caps.cache_line_size = 64; @@ -2362,30 +2451,10 @@ static bool dcn32_resource_construct( dc->dml2_options.use_native_soc_bb_construction = true; dc->dml2_options.minimize_dispclk_using_odm = true; - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + resource_init_common_dml2_callbacks(dc, &dc->dml2_options); dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; - - dc->dml2_options.svp_pstate.callbacks.dc = dc; - dc->dml2_options.svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.add_phantom_stream = &dc_state_add_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.svp_pstate.callbacks.create_phantom_plane = &dc_state_create_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.remove_phantom_plane = &dc_state_remove_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.remove_phantom_stream = &dc_state_remove_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.create_phantom_stream = &dc_state_create_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.release_phantom_plane = &dc_state_release_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.release_phantom_stream = &dc_state_release_phantom_stream; dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; - dc->dml2_options.svp_pstate.callbacks.get_pipe_subvp_type = &dc_state_get_pipe_subvp_type; - dc->dml2_options.svp_pstate.callbacks.get_stream_subvp_type = &dc_state_get_stream_subvp_type; - dc->dml2_options.svp_pstate.callbacks.get_paired_subvp_stream = &dc_state_get_paired_subvp_stream; + dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes = pool->base.funcs->calculate_mall_ways_from_bytes; dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; @@ -2483,7 +2552,7 @@ struct resource_pool *dcn32_create_resource_pool( * full update which delays the flip for 1 frame. If we use the original pipe * we don't have to toggle its power. So we can flip faster. */ -static int find_optimal_free_pipe_as_secondary_dpp_pipe( +int dcn32_find_optimal_free_pipe_as_secondary_dpp_pipe( const struct resource_context *cur_res_ctx, struct resource_context *new_res_ctx, const struct resource_pool *pool, @@ -2666,7 +2735,7 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( return dcn32_acquire_idle_pipe_for_head_pipe_in_layer( new_ctx, pool, opp_head_pipe->stream, opp_head_pipe); - free_pipe_idx = find_optimal_free_pipe_as_secondary_dpp_pipe( + free_pipe_idx = dcn32_find_optimal_free_pipe_as_secondary_dpp_pipe( &cur_ctx->res_ctx, &new_ctx->res_ctx, pool, opp_head_pipe); if (free_pipe_idx >= 0) { diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h index 2258c5c7212d..fee67fbab8e2 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h @@ -113,10 +113,6 @@ void dcn32_calculate_wm_and_dlg( int pipe_cnt, int vlevel); -uint32_t dcn32_helper_mall_bytes_to_ways( - struct dc *dc, - uint32_t total_size_in_mall_bytes); - uint32_t dcn32_helper_calculate_mall_bytes_for_cursor( struct dc *dc, struct pipe_ctx *pipe_ctx, @@ -141,6 +137,12 @@ bool dcn32_any_surfaces_rotated(struct dc *dc, struct dc_state *context); bool dcn32_is_center_timing(struct pipe_ctx *pipe); bool dcn32_is_psr_capable(struct pipe_ctx *pipe); +int dcn32_find_optimal_free_pipe_as_secondary_dpp_pipe( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool, + const struct pipe_ctx *new_opp_head); + struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_dpp_pipe( const struct dc_state *cur_ctx, struct dc_state *new_ctx, @@ -184,6 +186,8 @@ void dcn32_update_dml_pipes_odm_policy_based_on_context(struct dc *dc, struct dc void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context); +unsigned int dcn32_calculate_mall_ways_from_bytes(const struct dc *dc, unsigned int total_size_in_mall_bytes); + /* definitions for run time init of reg offsets */ /* CLK SRC */ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index 296a0a8e7145..e4b360d89b3b 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1288,6 +1288,8 @@ static struct hpo_dp_link_encoder *dcn321_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ #undef REG_STRUCT #define REG_STRUCT hpo_dp_link_enc_regs @@ -1579,10 +1581,20 @@ static struct dc_cap_funcs cap_funcs = { static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { + struct dml2_configuration_options dml2_opt = dc->dml2_options; + DC_FP_START(); + dcn321_update_bw_bounding_box_fpu(dc, bw_params); + + dml2_opt.use_clock_dc_limits = false; if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2) - dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2); + dml2_reinit(dc, &dml2_opt, &dc->current_state->bw_ctx.dml2); + + dml2_opt.use_clock_dc_limits = true; + if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source) + dml2_reinit(dc, &dml2_opt, &dc->current_state->bw_ctx.dml2_dc_power_source); + DC_FP_END(); } @@ -1610,6 +1622,7 @@ static struct resource_funcs dcn321_res_pool_funcs = { .update_soc_for_wm_a = dcn30_update_soc_for_wm_a, .add_phantom_pipes = dcn32_add_phantom_pipes, .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params, + .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes, }; static uint32_t read_pipe_fuses(struct dc_context *ctx) @@ -1697,7 +1710,9 @@ static bool dcn321_resource_construct( dc->caps.min_horizontal_blanking_period = 80; dc->caps.dmdata_alloc_size = 2048; dc->caps.mall_size_per_mem_channel = 4; - dc->caps.mall_size_total = 0; + /* total size = mall per channel * num channels * 1024 * 1024 */ + dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel * dc->ctx->dc_bios->vram_info.num_chans * 1048576; + dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8; dc->caps.cache_line_size = 64; dc->caps.cache_num_ways = 16; @@ -1998,30 +2013,10 @@ static bool dcn321_resource_construct( dc->dml2_options.use_native_soc_bb_construction = true; dc->dml2_options.minimize_dispclk_using_odm = true; - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + resource_init_common_dml2_callbacks(dc, &dc->dml2_options); dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; - - dc->dml2_options.svp_pstate.callbacks.dc = dc; - dc->dml2_options.svp_pstate.callbacks.add_phantom_plane = &dc_state_add_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.add_phantom_stream = &dc_state_add_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.build_scaling_params = &resource_build_scaling_params; - dc->dml2_options.svp_pstate.callbacks.create_phantom_plane = &dc_state_create_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.remove_phantom_plane = &dc_state_remove_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.remove_phantom_stream = &dc_state_remove_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.create_phantom_stream = &dc_state_create_phantom_stream; - dc->dml2_options.svp_pstate.callbacks.release_phantom_plane = &dc_state_release_phantom_plane; - dc->dml2_options.svp_pstate.callbacks.release_phantom_stream = &dc_state_release_phantom_stream; dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc; - dc->dml2_options.svp_pstate.callbacks.get_pipe_subvp_type = &dc_state_get_pipe_subvp_type; - dc->dml2_options.svp_pstate.callbacks.get_stream_subvp_type = &dc_state_get_stream_subvp_type; - dc->dml2_options.svp_pstate.callbacks.get_paired_subvp_stream = &dc_state_get_paired_subvp_stream; + dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes = pool->base.funcs->calculate_mall_ways_from_bytes; dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us; dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us; diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 5d52853cac96..2df8a742516c 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -721,7 +721,7 @@ static const struct dc_debug_options debug_defaults_drv = { .disable_dpp_power_gate = true, .disable_hubp_power_gate = true, .disable_optc_power_gate = true, /*should the same as above two*/ - .disable_hpo_power_gate = true, /*dmubfw force domain25 on*/ + .disable_hpo_power_gate = false, /*dmubfw force domain25 on*/ .disable_clock_gate = false, .disable_dsc_power_gate = true, .vsr_support = true, @@ -764,12 +764,12 @@ static const struct dc_debug_options debug_defaults_drv = { }, .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT, .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ - .minimum_z8_residency_time = 2100, + .minimum_z8_residency_time = 1, /* Always allow when other conditions are met */ .using_dml2 = true, .support_eDP1_5 = true, .enable_hpo_pg_support = false, .enable_legacy_fast_update = true, - .enable_single_display_2to1_odm_policy = false, + .enable_single_display_2to1_odm_policy = true, .disable_idle_power_optimizations = false, .dmcub_emulation = false, .disable_boot_optimizations = false, @@ -783,7 +783,7 @@ static const struct dc_debug_options debug_defaults_drv = { .psp_disabled_wa = true, .ips2_eval_delay_us = 2000, .ips2_entry_delay_us = 800, - .disable_dmub_reallow_idle = true, + .disable_dmub_reallow_idle = false, .static_screen_wait_frames = 2, }; @@ -1368,6 +1368,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ #undef REG_STRUCT #define REG_STRUCT hpo_dp_link_enc_regs @@ -1734,7 +1736,9 @@ static bool dcn35_validate_bandwidth(struct dc *dc, { bool out = false; - out = dml2_validate(dc, context, fast_validate); + out = dml2_validate(dc, context, + context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, + fast_validate); if (fast_validate) return out; @@ -2138,15 +2142,9 @@ static bool dcn35_resource_construct( dc->dml2_options.minimize_dispclk_using_odm = true; dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + resource_init_common_dml2_callbacks(dc, &dc->dml2_options); dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + dc->dml2_options.max_segments_per_hubp = 24; dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h index a51c4a9eaafe..f97bb4cb3761 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h @@ -240,6 +240,8 @@ struct resource_pool *dcn35_create_resource_pool( SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst),\ SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst),\ SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst),\ + SRI_ARR(OTG_V_COUNT_STOP_CONTROL, OTG, inst),\ + SRI_ARR(OTG_V_COUNT_STOP_CONTROL2, OTG, inst),\ SRI_ARR(OTG_TRIGA_CNTL, OTG, inst),\ SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst),\ SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst),\ diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c index 909e14261f9b..ddf9560ab772 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c @@ -758,7 +758,7 @@ static const struct dc_debug_options debug_defaults_drv = { //must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions .enable_double_buffered_dsc_pg_support = true, .enable_dp_dig_pixel_rate_div_policy = 1, - .disable_z10 = true, + .disable_z10 = false, .ignore_pg = true, .psp_disabled_wa = true, .ips2_eval_delay_us = 2000, @@ -1348,6 +1348,8 @@ static struct hpo_dp_link_encoder *dcn31_hpo_dp_link_encoder_create( /* allocate HPO link encoder */ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL); + if (!hpo_dp_enc31) + return NULL; /* out of memory */ #undef REG_STRUCT #define REG_STRUCT hpo_dp_link_enc_regs @@ -1714,19 +1716,20 @@ static bool dcn351_validate_bandwidth(struct dc *dc, { bool out = false; - out = dml2_validate(dc, context, fast_validate); + out = dml2_validate(dc, context, + context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2, + fast_validate); if (fast_validate) return out; DC_FP_START(); - dcn351_decide_zstate_support(dc, context); + dcn35_decide_zstate_support(dc, context); DC_FP_END(); return out; } - static struct resource_funcs dcn351_res_pool_funcs = { .destroy = dcn351_destroy_resource_pool, .link_enc_create = dcn35_link_encoder_create, @@ -1869,6 +1872,9 @@ static bool dcn351_resource_construct( /* Use pipe context based otg sync logic */ dc->config.use_pipe_ctx_sync_logic = true; + /* Use psp mailbox to enable assr */ + dc->config.use_assr_psp_message = true; + /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { @@ -1888,6 +1894,8 @@ static bool dcn351_resource_construct( if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV) dc->debug = debug_defaults_drv; + /*HW default is to have all the FGCG enabled, SW no need to program them*/ + dc->debug.enable_fine_grain_clock_gating.u32All = 0xFFFF; // Init the vm_helper if (dc->vm_helper) vm_helper_init(dc->vm_helper, 16); @@ -2118,15 +2126,9 @@ static bool dcn351_resource_construct( dc->dml2_options.minimize_dispclk_using_odm = true; dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm; - dc->dml2_options.callbacks.dc = dc; - dc->dml2_options.callbacks.build_scaling_params = &resource_build_scaling_params; + resource_init_common_dml2_callbacks(dc, &dc->dml2_options); dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch = &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch; - dc->dml2_options.callbacks.acquire_secondary_pipe_for_mpc_odm = &dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy; - dc->dml2_options.callbacks.update_pipes_for_stream_with_slice_count = &resource_update_pipes_for_stream_with_slice_count; - dc->dml2_options.callbacks.update_pipes_for_plane_with_slice_count = &resource_update_pipes_for_plane_with_slice_count; - dc->dml2_options.callbacks.get_mpc_slice_index = &resource_get_mpc_slice_index; - dc->dml2_options.callbacks.get_odm_slice_index = &resource_get_odm_slice_index; - dc->dml2_options.callbacks.get_opp_head = &resource_get_opp_head; + dc->dml2_options.max_segments_per_hubp = 24; dc->dml2_options.det_segment_size = DCN3_2_DET_SEG_SIZE;/*todo*/ diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 7785908a6676..2fde1f043d50 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -71,6 +71,8 @@ extern "C" { #endif +#define DMUB_PC_SNAPSHOT_COUNT 10 + /* Forward declarations */ struct dmub_srv; struct dmub_srv_common_regs; @@ -295,10 +297,22 @@ struct dmub_srv_hw_params { bool dpia_hpd_int_enable_supported; bool disable_clock_gate; bool disallow_dispclk_dppclk_ds; + bool ips_sequential_ono; enum dmub_memory_access_type mem_access_type; enum dmub_ips_disable_type disable_ips; }; +/** + * struct dmub_srv_debug - Debug info for dmub_srv + * @timeout_occured: Indicates a timeout occured on any message from driver to dmub + * @timeout_cmd: first cmd sent from driver that timed out - subsequent timeouts are not stored + */ +struct dmub_srv_debug { + bool timeout_occured; + union dmub_rb_cmd timeout_cmd; + unsigned long long timestamp; +}; + /** * struct dmub_diagnostic_data - Diagnostic data retrieved from DMCUB for * debugging purposes, including logging, crash analysis, etc. @@ -306,7 +320,7 @@ struct dmub_srv_hw_params { struct dmub_diagnostic_data { uint32_t dmcub_version; uint32_t scratch[17]; - uint32_t pc; + uint32_t pc[DMUB_PC_SNAPSHOT_COUNT]; uint32_t undefined_address_fault_addr; uint32_t inst_fetch_fault_addr; uint32_t data_write_fault_addr; @@ -317,6 +331,7 @@ struct dmub_diagnostic_data { uint32_t inbox0_wptr; uint32_t inbox0_size; uint32_t gpint_datain0; + struct dmub_srv_debug timeout_info; uint8_t is_dmcub_enabled : 1; uint8_t is_dmcub_soft_reset : 1; uint8_t is_dmcub_secure_reset : 1; @@ -506,6 +521,7 @@ struct dmub_srv { struct dmub_visual_confirm_color visual_confirm_color; enum dmub_srv_power_state_type power_state; + struct dmub_srv_debug debug; }; /** diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index af3fe8bb0728..e85fd3ac52c7 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -97,6 +97,9 @@ /* Maximum number of planes on any ASIC. */ #define DMUB_MAX_PLANES 6 +/* Maximum number of phantom planes on any ASIC */ +#define DMUB_MAX_PHANTOM_PLANES ((DMUB_MAX_PLANES) / 2) + /* Trace buffer offset for entry */ #define TRACE_BUFFER_ENTRY_OFFSET 16 @@ -194,6 +197,11 @@ union abm_flags { * of user backlight level. */ unsigned int abm_gradual_bl_change : 1; + + /** + * @abm_new_frame: Indicates if a new frame update needed for ABM to ramp up into steady + */ + unsigned int abm_new_frame : 1; } bitfields; unsigned int u32All; @@ -461,7 +469,7 @@ struct dmub_feature_caps { * Max PSR version supported by FW. */ uint8_t psr; - uint8_t fw_assisted_mclk_switch; + uint8_t fw_assisted_mclk_switch_ver; uint8_t reserved[4]; uint8_t subvp_psr_support; uint8_t gecc_enable; @@ -619,6 +627,7 @@ enum dmub_ips_disable_type { DMUB_IPS_DISABLE_IPS2 = 3, DMUB_IPS_DISABLE_IPS2_Z10 = 4, DMUB_IPS_DISABLE_DYNAMIC = 5, + DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF = 6, }; #define DMUB_IPS1_ALLOW_MASK 0x00000001 @@ -653,6 +662,7 @@ union dmub_fw_boot_options { uint32_t disable_timeout_recovery : 1; /* 1 if timeout recovery should be disabled */ uint32_t ips_pg_disable: 1; /* 1 to disable ONO domains power gating*/ uint32_t ips_disable: 3; /* options to disable ips support*/ + uint32_t ips_sequential_ono: 1; /**< 1 to enable sequential ONO IPS sequence */ uint32_t reserved : 9; /**< reserved */ } bits; /**< boot bits */ uint32_t all; /**< 32-bit access to bits */ @@ -695,7 +705,8 @@ union dmub_shared_state_ips_fw_signals { struct { uint32_t ips1_commit : 1; /**< 1 if in IPS1 */ uint32_t ips2_commit : 1; /**< 1 if in IPS2 */ - uint32_t reserved_bits : 30; /**< Reversed */ + uint32_t in_idle : 1; /**< 1 if DMCUB is in idle */ + uint32_t reserved_bits : 29; /**< Reversed */ } bits; uint32_t all; }; @@ -724,7 +735,13 @@ union dmub_shared_state_ips_driver_signals { */ struct dmub_shared_state_ips_fw { union dmub_shared_state_ips_fw_signals signals; /**< 4 bytes, IPS signal bits */ - uint32_t reserved[61]; /**< Reversed, to be updated when adding new fields. */ + uint32_t rcg_entry_count; /**< Entry counter for RCG */ + uint32_t rcg_exit_count; /**< Exit counter for RCG */ + uint32_t ips1_entry_count; /**< Entry counter for IPS1 */ + uint32_t ips1_exit_count; /**< Exit counter for IPS1 */ + uint32_t ips2_entry_count; /**< Entry counter for IPS2 */ + uint32_t ips2_exit_count; /**< Exit counter for IPS2 */ + uint32_t reserved[55]; /**< Reversed, to be updated when adding new fields. */ }; /* 248-bytes, fixed */ /** @@ -811,6 +828,10 @@ enum dmub_cmd_vbios_type { * Query DP alt status on a transmitter. */ DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT = 26, + /** + * Control PHY FSM + */ + DMUB_CMD__VBIOS_TRANSMITTER_SET_PHY_FSM = 29, /** * Controls domain power gating */ @@ -1186,6 +1207,11 @@ enum dmub_cmd_type { */ DMUB_CMD__DPIA_HPD_INT_ENABLE = 86, + /** + * Command type used for all PSP commands. + */ + DMUB_CMD__PSP = 88, + DMUB_CMD__VBIOS = 128, }; @@ -1588,7 +1614,7 @@ struct dmub_rb_cmd_idle_opt_dcn_restore { */ struct dmub_dcn_notify_idle_cntl_data { uint8_t driver_idle; - uint8_t pad[1]; + uint8_t reserved[59]; }; /** @@ -2309,6 +2335,11 @@ enum phy_link_rate { * UHBR10 - 20.0 Gbps/Lane */ PHY_RATE_2000 = 11, + + PHY_RATE_675 = 12, + /** + * Rate 12 - 6.75 Gbps/Lane + */ }; /** @@ -2327,6 +2358,7 @@ enum dmub_phy_fsm_state { DMUB_PHY_FSM_POWER_DOWN, DMUB_PHY_FSM_PLL_EN, DMUB_PHY_FSM_TX_EN, + DMUB_PHY_FSM_TX_EN_TEST_MODE, DMUB_PHY_FSM_FAST_LP, DMUB_PHY_FSM_P2_PLL_OFF_CPM, DMUB_PHY_FSM_P2_PLL_OFF_PG, @@ -2931,18 +2963,49 @@ struct dmub_rb_cmd_psr_set_power_opt { struct dmub_cmd_psr_set_power_opt_data psr_set_power_opt_data; }; +/** + * Definition of Replay Residency GPINT command. + * Bit[0] - Residency mode for Revision 0 + * Bit[1] - Enable/Disable state + * Bit[2-3] - Revision number + * Bit[4-7] - Residency mode for Revision 1 + * Bit[8] - Panel instance + * Bit[9-15] - Reserved + */ + +enum pr_residency_mode { + PR_RESIDENCY_MODE_PHY = 0x0, + PR_RESIDENCY_MODE_ALPM, + PR_RESIDENCY_MODE_IPS2, + PR_RESIDENCY_MODE_FRAME_CNT, + PR_RESIDENCY_MODE_ENABLEMENT_PERIOD, +}; + #define REPLAY_RESIDENCY_MODE_SHIFT (0) #define REPLAY_RESIDENCY_ENABLE_SHIFT (1) +#define REPLAY_RESIDENCY_REVISION_SHIFT (2) +#define REPLAY_RESIDENCY_MODE2_SHIFT (4) #define REPLAY_RESIDENCY_MODE_MASK (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_ALPM (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_IPS 0x10 +# define REPLAY_RESIDENCY_FIELD_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE_ALPM (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) + +#define REPLAY_RESIDENCY_MODE2_MASK (0xF << REPLAY_RESIDENCY_MODE2_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE2_IPS (0x1 << REPLAY_RESIDENCY_MODE2_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE2_FRAME_CNT (0x2 << REPLAY_RESIDENCY_MODE2_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE2_EN_PERIOD (0x3 << REPLAY_RESIDENCY_MODE2_SHIFT) #define REPLAY_RESIDENCY_ENABLE_MASK (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) # define REPLAY_RESIDENCY_DISABLE (0x0 << REPLAY_RESIDENCY_ENABLE_SHIFT) # define REPLAY_RESIDENCY_ENABLE (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) +#define REPLAY_RESIDENCY_REVISION_MASK (0x3 << REPLAY_RESIDENCY_REVISION_SHIFT) +# define REPLAY_RESIDENCY_REVISION_0 (0x0 << REPLAY_RESIDENCY_REVISION_SHIFT) +# define REPLAY_RESIDENCY_REVISION_1 (0x1 << REPLAY_RESIDENCY_REVISION_SHIFT) + +/** + * Definition of a replay_state. + */ enum replay_state { REPLAY_STATE_0 = 0x0, REPLAY_STATE_1 = 0x10, @@ -3004,6 +3067,11 @@ enum dmub_cmd_replay_type { * Set pseudo vtotal */ DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL = 7, + /** + * Set adaptive sync sdp enabled + */ + DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP = 8, + }; /** @@ -3205,6 +3273,20 @@ struct dmub_cmd_replay_set_pseudo_vtotal { */ uint8_t pad; }; +struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data { + /** + * Panel Instance. + * Panel isntance to identify which replay_state to use + * Currently the support is only for 0 or 1 + */ + uint8_t panel_inst; + /** + * enabled: set adaptive sync sdp enabled + */ + uint8_t force_disabled; + + uint8_t pad[2]; +}; /** * Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command. @@ -3308,6 +3390,20 @@ struct dmub_rb_cmd_replay_set_pseudo_vtotal { struct dmub_cmd_replay_set_pseudo_vtotal data; }; +/** + * Definition of a DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP command. + */ +struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp { + /** + * Command header. + */ + struct dmub_cmd_header header; + /** + * Definition of DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP command. + */ + struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data data; +}; + /** * Data passed from driver to FW in DMUB_CMD__REPLAY_SET_RESIDENCY_FRAMEUPDATE_TIMER command. */ @@ -3363,6 +3459,11 @@ union dmub_replay_cmd_set { * Definition of DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command data. */ struct dmub_cmd_replay_set_pseudo_vtotal pseudo_vtotal_data; + /** + * Definition of DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP command data. + */ + struct dmub_cmd_replay_disabled_adaptive_sync_sdp_data disabled_adaptive_sync_sdp_data; + }; /** @@ -3445,7 +3546,7 @@ enum hw_lock_client { /** * Replay is the client of HW Lock Manager. */ - HW_LOCK_CLIENT_REPLAY = 4, + HW_LOCK_CLIENT_REPLAY = 4, /** * Invalid client. */ @@ -4038,6 +4139,10 @@ enum dmub_cmd_panel_cntl_type { * Queries backlight info for the embedded panel. */ DMUB_CMD__PANEL_CNTL_QUERY_BACKLIGHT_INFO = 1, + /** + * Sets the PWM Freq as per user's requirement. + */ + DMUB_CMD__PANEL_DEBUG_PWM_FREQ = 2, }; /** @@ -4139,6 +4244,34 @@ struct dmub_rb_cmd_transmitter_query_dp_alt { struct dmub_rb_cmd_transmitter_query_dp_alt_data data; /**< payload */ }; +struct phy_test_mode { + uint8_t mode; + uint8_t pat0; + uint8_t pad[2]; +}; + +/** + * Data passed in/out in a DMUB_CMD__VBIOS_TRANSMITTER_SET_PHY_FSM command. + */ +struct dmub_rb_cmd_transmitter_set_phy_fsm_data { + uint8_t phy_id; /**< 0=UNIPHYA, 1=UNIPHYB, 2=UNIPHYC, 3=UNIPHYD, 4=UNIPHYE, 5=UNIPHYF */ + uint8_t mode; /**< HDMI/DP/DP2 etc */ + uint8_t lane_num; /**< Number of lanes */ + uint32_t symclk_100Hz; /**< PLL symclock in 100hz */ + struct phy_test_mode test_mode; + enum dmub_phy_fsm_state state; + uint32_t status; + uint8_t pad; +}; + +/** + * Definition of a DMUB_CMD__VBIOS_TRANSMITTER_SET_PHY_FSM command. + */ +struct dmub_rb_cmd_transmitter_set_phy_fsm { + struct dmub_cmd_header header; /**< header */ + struct dmub_rb_cmd_transmitter_set_phy_fsm_data data; /**< payload */ +}; + /** * Maximum number of bytes a chunk sent to DMUB for parsing */ @@ -4260,6 +4393,65 @@ struct dmub_rb_cmd_secure_display { } roi_info; }; +/** + * Command type of a DMUB_CMD__PSP command + */ +enum dmub_cmd_psp_type { + DMUB_CMD__PSP_ASSR_ENABLE = 0 +}; + +/** + * Data passed from driver to FW in a DMUB_CMD__PSP_ASSR_ENABLE command. + */ +struct dmub_cmd_assr_enable_data { + /** + * ASSR enable or disable. + */ + uint8_t enable; + /** + * PHY port type. + * Indicates eDP / non-eDP port type + */ + uint8_t phy_port_type; + /** + * PHY port ID. + */ + uint8_t phy_port_id; + /** + * Link encoder index. + */ + uint8_t link_enc_index; + /** + * HPO mode. + */ + uint8_t hpo_mode; + + /** + * Reserved field. + */ + uint8_t reserved[7]; +}; + +/** + * Definition of a DMUB_CMD__PSP_ASSR_ENABLE command. + */ +struct dmub_rb_cmd_assr_enable { + /** + * Command header. + */ + struct dmub_cmd_header header; + + /** + * Assr data. + */ + struct dmub_cmd_assr_enable_data assr_data; + + /** + * Reserved field. + */ + uint32_t reserved[3]; +}; + /** * union dmub_rb_cmd - DMUB inbox command. */ @@ -4450,6 +4642,10 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT command. */ struct dmub_rb_cmd_transmitter_query_dp_alt query_dp_alt; + /** + * Definition of a DMUB_CMD__VBIOS_TRANSMITTER_SET_PHY_FSM command. + */ + struct dmub_rb_cmd_transmitter_set_phy_fsm set_phy_fsm; /** * Definition of a DMUB_CMD__DPIA_DIG1_CONTROL command. */ @@ -4518,6 +4714,15 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__REPLAY_SET_PSEUDO_VTOTAL command. */ struct dmub_rb_cmd_replay_set_pseudo_vtotal replay_set_pseudo_vtotal; + /** + * Definition of a DMUB_CMD__REPLAY_DISABLED_ADAPTIVE_SYNC_SDP command. + */ + struct dmub_rb_cmd_replay_disabled_adaptive_sync_sdp replay_disabled_adaptive_sync_sdp; + /** + * Definition of a DMUB_CMD__PSP_ASSR_ENABLE command. + */ + struct dmub_rb_cmd_assr_enable assr_enable; + }; /** diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c index cae96fba6349..e500ca9ae09c 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c @@ -472,4 +472,5 @@ void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); diag_data->is_cw6_enabled = is_cw6_enabled; + diag_data->timeout_info = dmub->debug; } diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index 2bcf5fb87dd9..662c34e9495c 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -466,6 +466,7 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); diag_data->is_cw6_enabled = is_cw6_enabled; + diag_data->timeout_info = dmub->debug; } bool dmub_dcn31_should_detect(struct dmub_srv *dmub) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c index 0d521eeda050..e1da270502cc 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c @@ -478,6 +478,8 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti diag_data->is_cw6_enabled = is_cw6_enabled; diag_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + + diag_data->timeout_info = dmub->debug; } void dmub_dcn32_configure_dmub_in_system_memory(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 53f359f3fae2..70e63aeb8f89 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -420,6 +420,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu boot_options.bits.disable_clk_ds = params->disallow_dispclk_dppclk_ds; boot_options.bits.disable_clk_gate = params->disable_clock_gate; boot_options.bits.ips_disable = params->disable_ips; + boot_options.bits.ips_sequential_ono = params->ips_sequential_ono; REG_WRITE(DMCUB_SCRATCH14, boot_options.all); } @@ -516,6 +517,7 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti diag_data->is_cw6_enabled = is_cw6_enabled; diag_data->gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0); + diag_data->timeout_info = dmub->debug; } void dmub_dcn35_configure_dmub_in_system_memory(struct dmub_srv *dmub) { diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 1c6f24cb1d2f..447768dec887 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -27,7 +27,6 @@ #define __DAL_TYPES_H__ #include "signal_types.h" -#include "dc_types.h" struct dal_logger; struct dc_bios; diff --git a/drivers/gpu/drm/amd/display/include/grph_object_id.h b/drivers/gpu/drm/amd/display/include/grph_object_id.h index c6bbd262f1ac..08ee0350b31f 100644 --- a/drivers/gpu/drm/amd/display/include/grph_object_id.h +++ b/drivers/gpu/drm/amd/display/include/grph_object_id.h @@ -226,8 +226,8 @@ enum dp_alt_mode { struct graphics_object_id { uint32_t id:8; - uint32_t enum_id:4; - uint32_t type:4; + enum object_enum_id enum_id; + enum object_type type; uint32_t reserved:16; /* for padding. total size should be u32 */ }; diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 92dbff22a7c6..1867aac57cf2 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -73,7 +73,6 @@ struct link_training_settings { enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; bool should_set_fec_ready; - /* TODO - factor lane_settings out because it changes during LT */ union dc_dp_ffe_preset *ffe_preset; uint16_t cr_pattern_time; diff --git a/drivers/gpu/drm/amd/display/include/logger_types.h b/drivers/gpu/drm/amd/display/include/logger_types.h index f39e2785e618..83479951732a 100644 --- a/drivers/gpu/drm/amd/display/include/logger_types.h +++ b/drivers/gpu/drm/amd/display/include/logger_types.h @@ -64,6 +64,7 @@ #define DC_LOG_DWB(...) drm_dbg((DC_LOGGER)->dev, __VA_ARGS__) #define DC_LOG_DP2(...) drm_dbg_dp((DC_LOGGER)->dev, __VA_ARGS__) #define DC_LOG_AUTO_DPM_TEST(...) pr_debug("[AutoDPMTest]: "__VA_ARGS__) +#define DC_LOG_IPS(...) pr_debug("[IPS]: "__VA_ARGS__) struct dc_log_buffer_ctx { char *buf; diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h index 1b14b17a79c7..a10d6b988aab 100644 --- a/drivers/gpu/drm/amd/display/include/signal_types.h +++ b/drivers/gpu/drm/amd/display/include/signal_types.h @@ -118,6 +118,19 @@ static inline bool dc_is_dvi_signal(enum signal_type signal) } } +static inline bool dc_is_tmds_signal(enum signal_type signal) +{ + switch (signal) { + case SIGNAL_TYPE_DVI_SINGLE_LINK: + case SIGNAL_TYPE_DVI_DUAL_LINK: + case SIGNAL_TYPE_HDMI_TYPE_A: + return true; + break; + default: + return false; + } +} + static inline bool dc_is_dvi_single_link_signal(enum signal_type signal) { return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK); diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index 8b5c27857671..3699e633801d 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c @@ -1059,7 +1059,7 @@ static bool build_freesync_hdr(struct pwl_float_data_ex *rgb_regamma, struct fixed31_32 min_display; struct fixed31_32 max_content; struct fixed31_32 clip = dc_fixpt_one; - struct fixed31_32 output; + struct fixed31_32 output = dc_fixpt_zero; bool use_eetf = false; bool is_clipped = false; struct fixed31_32 sdr_white_level; diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 3955b7e4b2e2..d09627c15b9c 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -158,13 +158,13 @@ static unsigned int calc_v_total_from_duration( if (duration_in_us > vrr->max_duration_in_us) duration_in_us = vrr->max_duration_in_us; - if (dc_is_hdmi_signal(stream->signal)) { + if (dc_is_hdmi_signal(stream->signal)) { // change for HDMI to comply with spec uint32_t h_total_up_scaled; h_total_up_scaled = stream->timing.h_total * 10000; v_total = div_u64((unsigned long long)duration_in_us * stream->timing.pix_clk_100hz + (h_total_up_scaled - 1), - h_total_up_scaled); + h_total_up_scaled); //ceiling for MMax and MMin for MVRR } else { v_total = div64_u64(div64_u64(((unsigned long long)( duration_in_us) * (stream->timing.pix_clk_100hz / 10)), @@ -1057,7 +1057,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, in_out_vrr->fixed_refresh_in_uhz = 0; refresh_range = div_u64(in_out_vrr->max_refresh_in_uhz + 500000, 1000000) - -+ div_u64(in_out_vrr->min_refresh_in_uhz + 500000, 1000000); + div_u64(in_out_vrr->min_refresh_in_uhz + 500000, 1000000); in_out_vrr->supported = true; } @@ -1126,6 +1126,8 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync, in_out_vrr->adjust.v_total_min = stream->timing.v_total; in_out_vrr->adjust.v_total_max = stream->timing.v_total; } + + in_out_vrr->adjust.allow_otg_v_count_halt = (in_config->state == VRR_STATE_ACTIVE_FIXED) ? true : false; } void mod_freesync_handle_preflip(struct mod_freesync *mod_freesync, diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c index 733f22bed021..c996365e84b0 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c @@ -151,7 +151,7 @@ static enum mod_hdcp_status check_pairing_info_available(struct mod_hdcp *hdcp) static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp) { - enum mod_hdcp_status status; + enum mod_hdcp_status status = MOD_HDCP_STATUS_FAILURE; uint8_t size; uint16_t max_wait = 20; // units of ms uint16_t num_polls = 5; diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c index f7b5583ee609..8e9caae7c955 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c @@ -156,6 +156,10 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp, uint32_t cur_size = 0; uint32_t data_offset = 0; + if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID) { + return MOD_HDCP_STATUS_DDC_FAILURE; + } + if (is_dp_hdcp(hdcp)) { while (buf_len > 0) { cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE); @@ -215,6 +219,10 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp, uint32_t cur_size = 0; uint32_t data_offset = 0; + if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID) { + return MOD_HDCP_STATUS_DDC_FAILURE; + } + if (is_dp_hdcp(hdcp)) { while (buf_len > 0) { cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE); diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 84f9b412a4f1..a344e2e49b0e 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -536,8 +536,6 @@ void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream, mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet); break; case FREESYNC_TYPE_PCON_IN_WHITELIST: - mod_build_adaptive_sync_infopacket_v1(info_packet); - break; case ADAPTIVE_SYNC_TYPE_EDP: mod_build_adaptive_sync_infopacket_v1(info_packet); break; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index b0a6256e89f4..7536c173a546 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -24,6 +24,7 @@ #define __AMD_SHARED_H__ #include +#include #define AMD_MAX_USEC_TIMEOUT 1000000 /* 1000 ms */ @@ -321,6 +322,8 @@ struct amd_ip_funcs { int (*set_powergating_state)(void *handle, enum amd_powergating_state state); void (*get_clockgating_state)(void *handle, u64 *flags); + void (*dump_ip_state)(void *handle); + void (*print_ip_state)(void *handle, struct drm_printer *p); }; diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h index f2f8f9b39c6b..fc72c2267060 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h @@ -311,6 +311,10 @@ #define mmPHYESYMCLK_CLOCK_CNTL_BASE_IDX 2 #define mmPHYFSYMCLK_CLOCK_CNTL 0x0057 #define mmPHYFSYMCLK_CLOCK_CNTL_BASE_IDX 2 +#define regHDMICHARCLK0_CLOCK_CNTL 0x004a +#define regHDMICHARCLK0_CLOCK_CNTL_BASE_IDX 2 +#define mmHDMICHARCLK0_CLOCK_CNTL 0x004a +#define mmHDMICHARCLK0_CLOCK_CNTL_BASE_IDX 2 // addressBlock: dce_dc_dccg_dccg_dfs_dispdec @@ -4513,6 +4517,10 @@ #define mmCM0_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM0_CM_3DLUT_OUT_OFFSET_B 0x0e18 #define mmCM0_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_INDEX 0x0e19 +#define mmCM0_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_DATA 0x0e1a +#define mmCM0_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp0_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -5201,6 +5209,10 @@ #define mmCM1_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM1_CM_3DLUT_OUT_OFFSET_B 0x0f83 #define mmCM1_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_INDEX 0x0f84 +#define mmCM1_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_DATA 0x0f85 +#define mmCM1_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp1_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -5888,6 +5900,10 @@ #define mmCM2_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM2_CM_3DLUT_OUT_OFFSET_B 0x10ee #define mmCM2_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM2_CM_TEST_DEBUG_INDEX 0x10ef +#define mmCM2_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM2_CM_TEST_DEBUG_DATA 0x10f0 +#define mmCM2_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp2_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -6576,6 +6592,10 @@ #define mmCM3_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM3_CM_3DLUT_OUT_OFFSET_B 0x1259 #define mmCM3_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM3_CM_TEST_DEBUG_INDEX 0x125a +#define mmCM3_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM3_CM_TEST_DEBUG_DATA 0x125b +#define mmCM3_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp3_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -7264,6 +7284,10 @@ #define mmCM4_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM4_CM_3DLUT_OUT_OFFSET_B 0x13c4 #define mmCM4_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM4_CM_TEST_DEBUG_INDEX 0x13c5 +#define mmCM4_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM4_CM_TEST_DEBUG_DATA 0x13c6 +#define mmCM4_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp4_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -7952,6 +7976,10 @@ #define mmCM5_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM5_CM_3DLUT_OUT_OFFSET_B 0x152f #define mmCM5_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM5_CM_TEST_DEBUG_INDEX 0x1530 +#define mmCM5_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM5_CM_TEST_DEBUG_DATA 0x1531 +#define mmCM5_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp5_dispdec_dpp_dcperfmon_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h index e0a447351623..daf71e82f0ba 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h @@ -1189,6 +1189,11 @@ #define PHYFSYMCLK_CLOCK_CNTL__PHYFSYMCLK_FORCE_SRC_SEL__SHIFT 0x4 #define PHYFSYMCLK_CLOCK_CNTL__PHYFSYMCLK_FORCE_EN_MASK 0x00000001L #define PHYFSYMCLK_CLOCK_CNTL__PHYFSYMCLK_FORCE_SRC_SEL_MASK 0x00000010L +//HDMICHARCLK0_CLOCK_CNTL +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN__SHIFT 0x0 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL__SHIFT 0x4 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN_MASK 0x00000001L +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL_MASK 0x00000070L // addressBlock: dce_dc_dccg_dccg_dfs_dispdec @@ -16739,6 +16744,15 @@ #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_SCALE_B__SHIFT 0x10 #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_OFFSET_B_MASK 0x0000FFFFL #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_SCALE_B_MASK 0xFFFF0000L +//CM0_CM_TEST_DEBUG_INDEX +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN__SHIFT 0x8 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX_MASK 0x000000FFL +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L +//CM0_CM_TEST_DEBUG_DATA +#define CM0_CM_TEST_DEBUG_DATA__CM_TEST_DEBUG_DATA__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_DATA__CM_TEST_DEBUG_DATA_MASK 0xFFFFFFFFL + // addressBlock: dce_dc_dpp0_dispdec_dpp_dcperfmon_dc_perfmon_dispdec //DC_PERFMON12_PERFCOUNTER_CNTL diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_offset.h index b45a35aae241..bf84f97d9162 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_offset.h @@ -4466,6 +4466,10 @@ #define mmCM0_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM0_CM_3DLUT_OUT_OFFSET_B 0x0e18 #define mmCM0_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_INDEX 0x0e19 +#define mmCM0_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_DATA 0x0e1a +#define mmCM0_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp0_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -5154,6 +5158,10 @@ #define mmCM1_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM1_CM_3DLUT_OUT_OFFSET_B 0x0f83 #define mmCM1_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_INDEX 0x0f84 +#define mmCM1_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_DATA 0x0f85 +#define mmCM1_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp1_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -5841,6 +5849,10 @@ #define mmCM2_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM2_CM_3DLUT_OUT_OFFSET_B 0x10ee #define mmCM2_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM2_CM_TEST_DEBUG_INDEX 0x10ef +#define mmCM2_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM2_CM_TEST_DEBUG_DATA 0x10f0 +#define mmCM2_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp2_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -6529,6 +6541,10 @@ #define mmCM3_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM3_CM_3DLUT_OUT_OFFSET_B 0x1259 #define mmCM3_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM3_CM_TEST_DEBUG_INDEX 0x125a +#define mmCM3_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM3_CM_TEST_DEBUG_DATA 0x125b +#define mmCM3_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp3_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -7217,6 +7233,10 @@ #define mmCM4_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM4_CM_3DLUT_OUT_OFFSET_B 0x13c4 #define mmCM4_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM4_CM_TEST_DEBUG_INDEX 0x13c5 +#define mmCM4_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM4_CM_TEST_DEBUG_DATA 0x13c6 +#define mmCM4_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp4_dispdec_dpp_dcperfmon_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_sh_mask.h index 3dae29f9581e..56cdb219874a 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_2_sh_mask.h @@ -15676,6 +15676,14 @@ #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_SCALE_B__SHIFT 0x10 #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_OFFSET_B_MASK 0x0000FFFFL #define CM0_CM_3DLUT_OUT_OFFSET_B__CM_3DLUT_OUT_SCALE_B_MASK 0xFFFF0000L +//CM0_CM_TEST_DEBUG_INDEX +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN__SHIFT 0x8 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX_MASK 0x000000FFL +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L +//CM0_CM_TEST_DEBUG_DATA +#define CM0_CM_TEST_DEBUG_DATA__CM_TEST_DEBUG_DATA__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_DATA__CM_TEST_DEBUG_DATA_MASK 0xFFFFFFFFL // addressBlock: dce_dc_dpp0_dispdec_dpp_dcperfmon_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_offset.h index daa8130636f0..8b0d2638a6b0 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_offset.h @@ -3110,6 +3110,10 @@ #define mmCM0_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM0_CM_3DLUT_OUT_OFFSET_B 0x0e18 #define mmCM0_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_INDEX 0x0e19 +#define mmCM0_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM0_CM_TEST_DEBUG_DATA 0x0e1a +#define mmCM0_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp0_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -3798,6 +3802,10 @@ #define mmCM1_CM_3DLUT_OUT_OFFSET_G_BASE_IDX 2 #define mmCM1_CM_3DLUT_OUT_OFFSET_B 0x0f83 #define mmCM1_CM_3DLUT_OUT_OFFSET_B_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_INDEX 0x0f84 +#define mmCM1_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define mmCM1_CM_TEST_DEBUG_DATA 0x0f85 +#define mmCM1_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp1_dispdec_dpp_dcperfmon_dc_perfmon_dispdec @@ -5687,6 +5695,16 @@ #define mmDSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define mmDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3035 #define mmDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define mmDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE 0x303a +#define mmDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define mmDSCC0_DSCC_TEST_DEBUG_DATA0 0x303b +#define mmDSCC0_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define mmDSCC0_DSCC_TEST_DEBUG_DATA1 0x303c +#define mmDSCC0_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define mmDSCC0_DSCC_TEST_DEBUG_DATA2 0x303d +#define mmDSCC0_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define mmDSCC0_DSCC_TEST_DEBUG_DATA3 0x303e +#define mmDSCC0_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dce_dc_dsc0_dispdec_dsc_dcperfmon_dc_perfmon_dispdec @@ -5817,6 +5835,16 @@ #define mmDSCC1_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define mmDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3091 #define mmDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define mmDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE 0x3096 +#define mmDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA0 0x3097 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA1 0x3098 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA2 0x3099 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define mmDSCC1_DSCC_TEST_DEBUG_DATA3 0x309a +#define mmDSCC1_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dce_dc_dsc1_dispdec_dsc_dcperfmon_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_sh_mask.h index 5c469cf635e5..53f1705f8d99 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_3_sh_mask.h @@ -10701,6 +10701,13 @@ #define CM0_CM_COEF_FORMAT__CM_BIAS_FORMAT_MASK 0x00000001L #define CM0_CM_COEF_FORMAT__CM_POST_CSC_COEF_FORMAT_MASK 0x00000010L #define CM0_CM_COEF_FORMAT__CM_GAMUT_REMAP_COEF_FORMAT_MASK 0x00000100L + +//CM0_CM_TEST_DEBUG_INDEX +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN__SHIFT 0x8 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX_MASK 0x000000FFL +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L + //CM0_CM_SHAPER_CONTROL #define CM0_CM_SHAPER_CONTROL__CM_SHAPER_LUT_MODE__SHIFT 0x0 #define CM0_CM_SHAPER_CONTROL__CM_SHAPER_MODE_CURRENT__SHIFT 0x2 @@ -22258,7 +22265,9 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L //DSC_TOP0_DSC_DEBUG_CONTROL #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL_MASK 0x00000070L // addressBlock: dce_dc_dsc0_dispdec_dsccif_dispdec @@ -22631,6 +22640,15 @@ //DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__SHIFT 0x0 #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_MASK 0x0003FFFFL +//DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE__SHIFT 0x0 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE__SHIFT 0x8 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE__SHIFT 0x10 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE__SHIFT 0x18 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE_MASK 0x0000001FL +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE_MASK 0x00001F00L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE_MASK 0x001F0000L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE_MASK 0x1F000000L // addressBlock: dce_dc_dsc0_dispdec_dsc_dcperfmon_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h index f268d33c4744..7fd906f10803 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_offset.h @@ -424,6 +424,8 @@ #define regDTBCLK_DTO2_MODULO_BASE_IDX 2 #define regDTBCLK_DTO3_MODULO 0x0022 #define regDTBCLK_DTO3_MODULO_BASE_IDX 2 +#define regHDMICHARCLK0_CLOCK_CNTL 0x004a +#define regHDMICHARCLK0_CLOCK_CNTL_BASE_IDX 2 #define regPHYASYMCLK_CLOCK_CNTL 0x0052 #define regPHYASYMCLK_CLOCK_CNTL_BASE_IDX 2 #define regPHYBSYMCLK_CLOCK_CNTL 0x0053 @@ -434,6 +436,8 @@ #define regPHYDSYMCLK_CLOCK_CNTL_BASE_IDX 2 #define regPHYESYMCLK_CLOCK_CNTL 0x0056 #define regPHYESYMCLK_CLOCK_CNTL_BASE_IDX 2 +#define regHDMISTREAMCLK_CNTL 0x0059 +#define regHDMISTREAMCLK_CNTL_BASE_IDX 2 #define regDCCG_GATE_DISABLE_CNTL3 0x005a #define regDCCG_GATE_DISABLE_CNTL3_BASE_IDX 2 #define regHDMISTREAMCLK0_DTO_PARAM 0x005b diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h index cf3398f15666..07fbfafe6056 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_2_sh_mask.h @@ -1372,6 +1372,11 @@ //DTBCLK_DTO3_MODULO #define DTBCLK_DTO3_MODULO__DTBCLK_DTO3_MODULO__SHIFT 0x0 #define DTBCLK_DTO3_MODULO__DTBCLK_DTO3_MODULO_MASK 0xFFFFFFFFL +//HDMICHARCLK0_CLOCK_CNTL +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN__SHIFT 0x0 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL__SHIFT 0x4 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN_MASK 0x00000001L +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL_MASK 0x00000070L //PHYASYMCLK_CLOCK_CNTL #define PHYASYMCLK_CLOCK_CNTL__PHYASYMCLK_FORCE_EN__SHIFT 0x0 #define PHYASYMCLK_CLOCK_CNTL__PHYASYMCLK_FORCE_SRC_SEL__SHIFT 0x4 @@ -1397,6 +1402,13 @@ #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_SRC_SEL__SHIFT 0x4 #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_EN_MASK 0x00000001L #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_SRC_SEL_MASK 0x00000030L +//HDMISTREAMCLK_CNTL +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_SRC_SEL__SHIFT 0x0 +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_EN__SHIFT 0x3 +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_DTO_FORCE_DIS__SHIFT 0x4 +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_SRC_SEL_MASK 0x00000007L +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_EN_MASK 0x00000008L +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_DTO_FORCE_DIS_MASK 0x00000010L //DCCG_GATE_DISABLE_CNTL3 #define DCCG_GATE_DISABLE_CNTL3__HDMISTREAMCLK0_GATE_DISABLE__SHIFT 0x0 #define DCCG_GATE_DISABLE_CNTL3__HDMISTREAMCLK1_GATE_DISABLE__SHIFT 0x1 @@ -46978,6 +46990,13 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L + + +//DSC_TOP0_DSC_DEBUG_CONTROL +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL_MASK 0x00000070L //DSC_TOP0_DSC_DEBUG_CONTROL #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h index 50c34d88c17c..16a69d17bb1e 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_offset.h @@ -213,6 +213,8 @@ #define regDTBCLK_DTO2_MODULO_BASE_IDX 2 #define regDTBCLK_DTO3_MODULO 0x0022 #define regDTBCLK_DTO3_MODULO_BASE_IDX 2 +#define regHDMICHARCLK0_CLOCK_CNTL 0x004a +#define regHDMICHARCLK0_CLOCK_CNTL_BASE_IDX 2 #define regPHYASYMCLK_CLOCK_CNTL 0x0052 #define regPHYASYMCLK_CLOCK_CNTL_BASE_IDX 2 #define regPHYBSYMCLK_CLOCK_CNTL 0x0053 @@ -233,6 +235,8 @@ #define regDCCG_AUDIO_DTBCLK_DTO_MODULO_BASE_IDX 2 #define regDTBCLK_DTO_DBUF_EN 0x0063 #define regDTBCLK_DTO_DBUF_EN_BASE_IDX 2 +#define regHDMISTREAMCLK_CNTL 0x0059 +#define regHDMISTREAMCLK_CNTL_BASE_IDX 2 // addressBlock: dce_dc_dccg_dccg_dcperfmon0_dc_perfmon_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h index 295e0dac9ffa..6473362e39a8 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h @@ -886,6 +886,11 @@ //DTBCLK_DTO3_MODULO #define DTBCLK_DTO3_MODULO__DTBCLK_DTO3_MODULO__SHIFT 0x0 #define DTBCLK_DTO3_MODULO__DTBCLK_DTO3_MODULO_MASK 0xFFFFFFFFL +//HDMICHARCLK0_CLOCK_CNTL +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN__SHIFT 0x0 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL__SHIFT 0x4 +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_EN_MASK 0x00000001L +#define HDMICHARCLK0_CLOCK_CNTL__HDMICHARCLK0_SRC_SEL_MASK 0x00000070L //PHYASYMCLK_CLOCK_CNTL #define PHYASYMCLK_CLOCK_CNTL__PHYASYMCLK_FORCE_EN__SHIFT 0x0 #define PHYASYMCLK_CLOCK_CNTL__PHYASYMCLK_FORCE_SRC_SEL__SHIFT 0x4 @@ -911,6 +916,11 @@ #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_SRC_SEL__SHIFT 0x4 #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_EN_MASK 0x00000001L #define PHYESYMCLK_CLOCK_CNTL__PHYESYMCLK_FORCE_SRC_SEL_MASK 0x00000030L +//HDMISTREAMCLK_CNTL +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_SRC_SEL__SHIFT 0x0 +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_DTO_FORCE_DIS__SHIFT 0x10 +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_SRC_SEL_MASK 0x00000003L +#define HDMISTREAMCLK_CNTL__HDMISTREAMCLK0_DTO_FORCE_DIS_MASK 0x00010000L //DCCG_GATE_DISABLE_CNTL3 #define DCCG_GATE_DISABLE_CNTL3__HDMISTREAMCLK0_GATE_DISABLE__SHIFT 0x0 #define DCCG_GATE_DISABLE_CNTL3__HDMISTREAMCLK1_GATE_DISABLE__SHIFT 0x1 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h index 14c29ce4c7b3..78cb61d5800a 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_offset.h @@ -1719,6 +1719,10 @@ #define regDCHUBBUB_TIMEOUT_INTERRUPT_STATUS_BASE_IDX 2 #define regFMON_CTRL 0x0541 #define regFMON_CTRL_BASE_IDX 2 +#define regDCHUBBUB_TEST_DEBUG_INDEX 0x0542 +#define regDCHUBBUB_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regDCHUBBUB_TEST_DEBUG_DATA 0x0543 +#define regDCHUBBUB_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dcn_dc_dchubbubl_hubbub_sdpif_dispdec @@ -3574,6 +3578,10 @@ #define regCM0_CM_DEALPHA_BASE_IDX 2 #define regCM0_CM_COEF_FORMAT 0x0d8c #define regCM0_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM0_CM_TEST_DEBUG_INDEX 0x0d8d +#define regCM0_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM0_CM_TEST_DEBUG_DATA 0x0d8e +#define regCM0_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dcn_dc_dpp0_dispdec_dpp_top_dispdec @@ -3960,6 +3968,10 @@ #define regCM1_CM_DEALPHA_BASE_IDX 2 #define regCM1_CM_COEF_FORMAT 0x0ef7 #define regCM1_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM1_CM_TEST_DEBUG_INDEX 0x0ef8 +#define regCM1_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM1_CM_TEST_DEBUG_DATA 0x0ef9 +#define regCM1_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dcn_dc_dpp1_dispdec_dpp_top_dispdec @@ -4346,6 +4358,10 @@ #define regCM2_CM_DEALPHA_BASE_IDX 2 #define regCM2_CM_COEF_FORMAT 0x1062 #define regCM2_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM2_CM_TEST_DEBUG_INDEX 0x1063 +#define regCM2_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM2_CM_TEST_DEBUG_DATA 0x1064 +#define regCM2_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dcn_dc_dpp2_dispdec_dpp_top_dispdec @@ -4732,6 +4748,10 @@ #define regCM3_CM_DEALPHA_BASE_IDX 2 #define regCM3_CM_COEF_FORMAT 0x11cd #define regCM3_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM3_CM_TEST_DEBUG_INDEX 0x11ce +#define regCM3_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM3_CM_TEST_DEBUG_DATA 0x11cf +#define regCM3_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dcn_dc_dpp3_dispdec_dpp_top_dispdec @@ -11780,6 +11800,16 @@ #define regDSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3035 #define regDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE 0x303a +#define regDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_DATA0 0x303b +#define regDSCC0_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_DATA1 0x303c +#define regDSCC0_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_DATA2 0x303d +#define regDSCC0_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_DATA3 0x303e +#define regDSCC0_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dcn_dc_dsc0_dispdec_dsccif_dispdec @@ -11888,6 +11918,16 @@ #define regDSCC1_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3091 #define regDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE 0x3096 +#define regDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_DATA0 0x3097 +#define regDSCC1_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_DATA1 0x3098 +#define regDSCC1_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_DATA2 0x3099 +#define regDSCC1_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_DATA3 0x309a +#define regDSCC1_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dcn_dc_dsc1_dispdec_dsccif_dispdec @@ -11996,6 +12036,16 @@ #define regDSCC2_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC2_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x30ed #define regDSCC2_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_BUS_ROTATE 0x30f2 +#define regDSCC2_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_DATA0 0x30f3 +#define regDSCC2_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_DATA1 0x30f4 +#define regDSCC2_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_DATA2 0x30f5 +#define regDSCC2_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_DATA3 0x30f6 +#define regDSCC2_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dcn_dc_dsc2_dispdec_dsccif_dispdec @@ -12104,6 +12154,16 @@ #define regDSCC3_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC3_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3149 #define regDSCC3_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_BUS_ROTATE 0x314e +#define regDSCC3_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_DATA0 0x314f +#define regDSCC3_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_DATA1 0x3150 +#define regDSCC3_DSCC_TEST_DEBUG_DATA1_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_DATA2 0x3151 +#define regDSCC3_DSCC_TEST_DEBUG_DATA2_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_DATA3 0x3152 +#define regDSCC3_DSCC_TEST_DEBUG_DATA3_BASE_IDX 2 // addressBlock: dcn_dc_dsc3_dispdec_dsccif_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h index 0691e328d0f0..1093105ca35b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_0_sh_mask.h @@ -11544,6 +11544,11 @@ #define CM0_CM_COEF_FORMAT__CM_BIAS_FORMAT_MASK 0x00000001L #define CM0_CM_COEF_FORMAT__CM_POST_CSC_COEF_FORMAT_MASK 0x00000010L #define CM0_CM_COEF_FORMAT__CM_GAMUT_REMAP_COEF_FORMAT_MASK 0x00000100L +//CM0_CM_TEST_DEBUG_INDEX +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN__SHIFT 0x8 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX_MASK 0x000000FFL +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L // addressBlock: dcn_dc_dpp0_dispdec_dpp_top_dispdec @@ -42267,6 +42272,18 @@ //DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__SHIFT 0x0 #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_MASK 0x0003FFFFL +//DSCC0_DSCC_TEST_DEBUG_INDEX2 +#define DSCC0_DSCC_TEST_DEBUG_INDEX2__DSCC_TEST_DEBUG_INDEX2__SHIFT 0x0 +#define DSCC0_DSCC_TEST_DEBUG_INDEX2__DSCC_TEST_DEBUG_INDEX2_MASK 0x000000FFL +//DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE__SHIFT 0x0 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE__SHIFT 0x8 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE__SHIFT 0x10 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE__SHIFT 0x18 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE_MASK 0x0000001FL +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE_MASK 0x00001F00L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE_MASK 0x001F0000L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE_MASK 0x1F000000L // addressBlock: dcn_dc_dsc0_dispdec_dsccif_dispdec @@ -42300,6 +42317,16 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L //DSC_TOP0_DSC_DEBUG_CONTROL #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL_MASK 0x00000070L + + +//DSC_TOP0_DSC_DEBUG_CONTROL +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 +//DSC_TOP0_DSC_DEBUG_CONTROL +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h index 3bd8792fd7b3..a04b8c32c564 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_offset.h @@ -1719,6 +1719,10 @@ #define regDCHUBBUB_TIMEOUT_INTERRUPT_STATUS_BASE_IDX 2 #define regFMON_CTRL 0x0541 #define regFMON_CTRL_BASE_IDX 2 +#define regDCHUBBUB_TEST_DEBUG_INDEX 0x0542 +#define regDCHUBBUB_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regDCHUBBUB_TEST_DEBUG_DATA 0x0543 +#define regDCHUBBUB_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dchubbubl_hubbub_sdpif_dispdec @@ -3573,6 +3577,10 @@ #define regCM0_CM_DEALPHA_BASE_IDX 2 #define regCM0_CM_COEF_FORMAT 0x0d8c #define regCM0_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM0_CM_TEST_DEBUG_INDEX 0x0d8d +#define regCM0_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM0_CM_TEST_DEBUG_DATA 0x0d8e +#define regCM0_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp0_dispdec_dpp_top_dispdec @@ -3959,6 +3967,10 @@ #define regCM1_CM_DEALPHA_BASE_IDX 2 #define regCM1_CM_COEF_FORMAT 0x0ef7 #define regCM1_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM1_CM_TEST_DEBUG_INDEX 0x0ef8 +#define regCM1_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM1_CM_TEST_DEBUG_DATA 0x0ef9 +#define regCM1_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp1_dispdec_dpp_top_dispdec @@ -4345,6 +4357,10 @@ #define regCM2_CM_DEALPHA_BASE_IDX 2 #define regCM2_CM_COEF_FORMAT 0x1062 #define regCM2_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM2_CM_TEST_DEBUG_INDEX 0x1063 +#define regCM2_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM2_CM_TEST_DEBUG_DATA 0x1064 +#define regCM2_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp2_dispdec_dpp_top_dispdec @@ -4731,6 +4747,10 @@ #define regCM3_CM_DEALPHA_BASE_IDX 2 #define regCM3_CM_COEF_FORMAT 0x11cd #define regCM3_CM_COEF_FORMAT_BASE_IDX 2 +#define regCM3_CM_TEST_DEBUG_INDEX 0x11ce +#define regCM3_CM_TEST_DEBUG_INDEX_BASE_IDX 2 +#define regCM3_CM_TEST_DEBUG_DATA 0x11cf +#define regCM3_CM_TEST_DEBUG_DATA_BASE_IDX 2 // addressBlock: dce_dc_dpp3_dispdec_dpp_top_dispdec @@ -11789,6 +11809,10 @@ #define regDSCC0_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3035 #define regDSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE 0x303a +#define regDSCC0_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC0_DSCC_TEST_DEBUG_DATA0 0x303b +#define regDSCC0_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 // addressBlock: dce_dc_dsc0_dispdec_dsccif_dispdec @@ -11897,6 +11921,10 @@ #define regDSCC1_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3091 #define regDSCC1_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE 0x3096 +#define regDSCC1_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC1_DSCC_TEST_DEBUG_DATA0 0x3097 +#define regDSCC1_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 // addressBlock: dce_dc_dsc1_dispdec_dsccif_dispdec @@ -12005,7 +12033,10 @@ #define regDSCC2_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC2_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x30ed #define regDSCC2_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 - +#define regDSCC2_DSCC_TEST_DEBUG_BUS_ROTATE 0x30f2 +#define regDSCC2_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC2_DSCC_TEST_DEBUG_DATA0 0x30f3 +#define regDSCC2_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 // addressBlock: dce_dc_dsc2_dispdec_dsccif_dispdec // base address: 0x2e0 @@ -12113,6 +12144,10 @@ #define regDSCC3_DSCC_RATE_CONTROL_BUFFER2_MAX_FULLNESS_LEVEL_BASE_IDX 2 #define regDSCC3_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL 0x3149 #define regDSCC3_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_BUS_ROTATE 0x314e +#define regDSCC3_DSCC_TEST_DEBUG_BUS_ROTATE_BASE_IDX 2 +#define regDSCC3_DSCC_TEST_DEBUG_DATA0 0x314f +#define regDSCC3_DSCC_TEST_DEBUG_DATA0_BASE_IDX 2 // addressBlock: dce_dc_dsc3_dispdec_dsccif_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h index e82dffc2b9b0..ce773fca621f 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_2_1_sh_mask.h @@ -11547,6 +11547,11 @@ #define CM0_CM_COEF_FORMAT__CM_BIAS_FORMAT_MASK 0x00000001L #define CM0_CM_COEF_FORMAT__CM_POST_CSC_COEF_FORMAT_MASK 0x00000010L #define CM0_CM_COEF_FORMAT__CM_GAMUT_REMAP_COEF_FORMAT_MASK 0x00000100L +//CM0_CM_TEST_DEBUG_INDEX +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX__SHIFT 0x0 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN__SHIFT 0x8 +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_INDEX_MASK 0x000000FFL +#define CM0_CM_TEST_DEBUG_INDEX__CM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L // addressBlock: dce_dc_dpp0_dispdec_dpp_top_dispdec @@ -42315,6 +42320,15 @@ //DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__SHIFT 0x0 #define DSCC0_DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL__DSCC_RATE_CONTROL_BUFFER3_MAX_FULLNESS_LEVEL_MASK 0x0003FFFFL +//DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE__SHIFT 0x0 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE__SHIFT 0x8 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE__SHIFT 0x10 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE__SHIFT 0x18 +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS0_ROTATE_MASK 0x0000001FL +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS1_ROTATE_MASK 0x00001F00L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS2_ROTATE_MASK 0x001F0000L +#define DSCC0_DSCC_TEST_DEBUG_BUS_ROTATE__DSCC_TEST_DEBUG_BUS3_ROTATE_MASK 0x1F000000L // addressBlock: dce_dc_dsc0_dispdec_dsccif_dispdec @@ -42348,7 +42362,9 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L //DSC_TOP0_DSC_DEBUG_CONTROL #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL__SHIFT 0x4 #define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_TEST_CLOCK_MUX_SEL_MASK 0x00000070L // addressBlock: dce_dc_dsc1_dispdec_dscc_dispdec diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h index 0bb47e06eee8..081e726afbf0 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_offset.h @@ -24,6 +24,8 @@ #define mmDPCSTX0_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX0_DPCSTX_PLL_UPDATE_DATA 0x292d #define mmDPCSTX0_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX0_DPCSTX_DEBUG_CONFIG 0x292e +#define mmDPCSTX0_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx0_dispdec @@ -50,6 +52,8 @@ #define mmRDPCSTX0_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX0_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x293c #define mmRDPCSTX0_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX0_RDPCSTX_DEBUG_CONFIG 0x293d +#define mmRDPCSTX0_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX0_RDPCSTX_PHY_CNTL0 0x2940 #define mmRDPCSTX0_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX0_RDPCSTX_PHY_CNTL1 0x2941 @@ -120,6 +124,8 @@ #define mmDPCSTX1_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX1_DPCSTX_PLL_UPDATE_DATA 0x2a05 #define mmDPCSTX1_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX1_DPCSTX_DEBUG_CONFIG 0x2a06 +#define mmDPCSTX1_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx1_dispdec @@ -146,6 +152,8 @@ #define mmRDPCSTX1_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX1_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2a14 #define mmRDPCSTX1_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX1_RDPCSTX_DEBUG_CONFIG 0x2a15 +#define mmRDPCSTX1_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX1_RDPCSTX_PHY_CNTL0 0x2a18 #define mmRDPCSTX1_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX1_RDPCSTX_PHY_CNTL1 0x2a19 @@ -216,6 +224,8 @@ #define mmDPCSTX2_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX2_DPCSTX_PLL_UPDATE_DATA 0x2add #define mmDPCSTX2_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX2_DPCSTX_DEBUG_CONFIG 0x2ade +#define mmDPCSTX2_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx2_dispdec @@ -242,6 +252,8 @@ #define mmRDPCSTX2_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX2_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2aec #define mmRDPCSTX2_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX2_RDPCSTX_DEBUG_CONFIG 0x2aed +#define mmRDPCSTX2_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX2_RDPCSTX_PHY_CNTL0 0x2af0 #define mmRDPCSTX2_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX2_RDPCSTX_PHY_CNTL1 0x2af1 @@ -312,6 +324,8 @@ #define mmDPCSTX3_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX3_DPCSTX_PLL_UPDATE_DATA 0x2bb5 #define mmDPCSTX3_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX3_DPCSTX_DEBUG_CONFIG 0x2bb6 +#define mmDPCSTX3_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx3_dispdec @@ -338,6 +352,8 @@ #define mmRDPCSTX3_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX3_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2bc4 #define mmRDPCSTX3_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX3_RDPCSTX_DEBUG_CONFIG 0x2bc5 +#define mmRDPCSTX3_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX3_RDPCSTX_PHY_CNTL0 0x2bc8 #define mmRDPCSTX3_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX3_RDPCSTX_PHY_CNTL1 0x2bc9 @@ -408,6 +424,8 @@ #define mmDPCSTX4_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX4_DPCSTX_PLL_UPDATE_DATA 0x2c8d #define mmDPCSTX4_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX4_DPCSTX_DEBUG_CONFIG 0x2c8e +#define mmDPCSTX4_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx4_dispdec @@ -434,6 +452,8 @@ #define mmRDPCSTX4_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX4_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2c9c #define mmRDPCSTX4_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX4_RDPCSTX_DEBUG_CONFIG 0x2c9d +#define mmRDPCSTX4_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX4_RDPCSTX_PHY_CNTL0 0x2ca0 #define mmRDPCSTX4_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX4_RDPCSTX_PHY_CNTL1 0x2ca1 @@ -504,6 +524,8 @@ #define mmDPCSTX5_DPCSTX_PLL_UPDATE_ADDR_BASE_IDX 2 #define mmDPCSTX5_DPCSTX_PLL_UPDATE_DATA 0x2d65 #define mmDPCSTX5_DPCSTX_PLL_UPDATE_DATA_BASE_IDX 2 +#define mmDPCSTX5_DPCSTX_DEBUG_CONFIG 0x2d66 +#define mmDPCSTX5_DPCSTX_DEBUG_CONFIG_BASE_IDX 2 // addressBlock: dpcssys_dpcs0_rdpcstx5_dispdec @@ -530,6 +552,8 @@ #define mmRDPCSTX5_RDPCSTX_CNTL2_BASE_IDX 2 #define mmRDPCSTX5_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2d74 #define mmRDPCSTX5_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define mmRDPCSTX5_RDPCSTX_DEBUG_CONFIG 0x2d75 +#define mmRDPCSTX5_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define mmRDPCSTX5_RDPCSTX_PHY_CNTL0 0x2d78 #define mmRDPCSTX5_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define mmRDPCSTX5_RDPCSTX_PHY_CNTL1 0x2d79 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h index 23fa1121a967..1f846fa6c1a2 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_0_sh_mask.h @@ -70,7 +70,9 @@ //DPCSTX0_DPCSTX_PLL_UPDATE_DATA #define DPCSTX0_DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA__SHIFT 0x0 #define DPCSTX0_DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA_MASK 0xFFFFFFFFL - +//DPCSTX0_DPCSTX_DEBUG_CONFIG +#define DPCSTX0_DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS__SHIFT 0xe +#define DPCSTX0_DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS_MASK 0x00004000L // addressBlock: dpcssys_dpcs0_rdpcstx0_dispdec //RDPCSTX0_RDPCSTX_CNTL diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h index 55743d06f728..e55ff0e8d74c 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_3_0_3_sh_mask.h @@ -70,7 +70,9 @@ //DPCSTX0_DPCSTX_PLL_UPDATE_DATA #define DPCSTX0_DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA__SHIFT 0x0 #define DPCSTX0_DPCSTX_PLL_UPDATE_DATA__DPCS_PLL_UPDATE_DATA_MASK 0xFFFFFFFFL - +//DPCSTX0_DPCSTX_DEBUG_CONFIG +#define DPCSTX0_DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS__SHIFT 0xe +#define DPCSTX0_DPCSTX_DEBUG_CONFIG__DPCS_DBG_CBUS_DIS_MASK 0x00004000L // addressBlock: dpcssys_dpcs0_rdpcstx0_dispdec //RDPCSTX0_RDPCSTX_CNTL diff --git a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h index 01a56556cde1..5b4fdeda1040 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h @@ -155,6 +155,8 @@ #define regRDPCSTX0_RDPCSTX_CNTL2_BASE_IDX 2 #define regRDPCSTX0_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x293c #define regRDPCSTX0_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define regRDPCSTX0_RDPCSTX_DEBUG_CONFIG 0x293d +#define regRDPCSTX0_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define regRDPCSTX0_RDPCSTX_PHY_CNTL0 0x2940 #define regRDPCSTX0_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define regRDPCSTX0_RDPCSTX_PHY_CNTL1 0x2941 @@ -239,6 +241,8 @@ #define regRDPCSTX1_RDPCSTX_CNTL2_BASE_IDX 2 #define regRDPCSTX1_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2a14 #define regRDPCSTX1_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define regRDPCSTX1_RDPCSTX_DEBUG_CONFIG 0x2a15 +#define regRDPCSTX1_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define regRDPCSTX1_RDPCSTX_PHY_CNTL0 0x2a18 #define regRDPCSTX1_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define regRDPCSTX1_RDPCSTX_PHY_CNTL1 0x2a19 @@ -323,6 +327,8 @@ #define regRDPCSTX2_RDPCSTX_CNTL2_BASE_IDX 2 #define regRDPCSTX2_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2aec #define regRDPCSTX2_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define regRDPCSTX2_RDPCSTX_DEBUG_CONFIG 0x2aed +#define regRDPCSTX2_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define regRDPCSTX2_RDPCSTX_PHY_CNTL0 0x2af0 #define regRDPCSTX2_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define regRDPCSTX2_RDPCSTX_PHY_CNTL1 0x2af1 @@ -407,6 +413,8 @@ #define regRDPCSTX3_RDPCSTX_CNTL2_BASE_IDX 2 #define regRDPCSTX3_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2bc4 #define regRDPCSTX3_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define regRDPCSTX3_RDPCSTX_DEBUG_CONFIG 0x2bc5 +#define regRDPCSTX3_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define regRDPCSTX3_RDPCSTX_PHY_CNTL0 0x2bc8 #define regRDPCSTX3_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define regRDPCSTX3_RDPCSTX_PHY_CNTL1 0x2bc9 @@ -491,6 +499,8 @@ #define regRDPCSTX4_RDPCSTX_CNTL2_BASE_IDX 2 #define regRDPCSTX4_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG 0x2c9c #define regRDPCSTX4_RDPCSTX_DMCU_DPALT_DIS_BLOCK_REG_BASE_IDX 2 +#define regRDPCSTX4_RDPCSTX_DEBUG_CONFIG 0x2c9d +#define regRDPCSTX4_RDPCSTX_DEBUG_CONFIG_BASE_IDX 2 #define regRDPCSTX4_RDPCSTX_PHY_CNTL0 0x2ca0 #define regRDPCSTX4_RDPCSTX_PHY_CNTL0_BASE_IDX 2 #define regRDPCSTX4_RDPCSTX_PHY_CNTL1 0x2ca1 diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h index 4908044f7409..4c8e7fdb6976 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_10_1_0_offset.h @@ -4830,6 +4830,8 @@ #define mmCP_ECC_FIRSTOCCURRENCE_RING2_BASE_IDX 0 #define mmGB_EDC_MODE 0x1e1e #define mmGB_EDC_MODE_BASE_IDX 0 +#define mmCP_DEBUG 0x1e1f +#define mmCP_DEBUG_BASE_IDX 0 #define mmCP_FETCHER_SOURCE 0x1e22 #define mmCP_FETCHER_SOURCE_BASE_IDX 0 #define mmCP_PQ_WPTR_POLL_CNTL 0x1e23 @@ -7778,6 +7780,8 @@ #define mmCP_MES_DOORBELL_CONTROL5_BASE_IDX 1 #define mmCP_MES_DOORBELL_CONTROL6 0x2841 #define mmCP_MES_DOORBELL_CONTROL6_BASE_IDX 1 +#define mmCP_MES_DEBUG_INTERRUPT_INSTR_PNTR 0x2842 +#define mmCP_MES_DEBUG_INTERRUPT_INSTR_PNTR_BASE_IDX 1 #define mmCP_MES_GP0_LO 0x2843 #define mmCP_MES_GP0_LO_BASE_IDX 1 #define mmCP_MES_GP0_HI 0x2844 @@ -9332,10 +9336,16 @@ #define mmRLC_LB_CNTR_INIT_1_BASE_IDX 1 #define mmRLC_LB_CNTR_1 0x4c1c #define mmRLC_LB_CNTR_1_BASE_IDX 1 +#define mmRLC_GPM_DEBUG_INST_ADDR 0x4c1d +#define mmRLC_GPM_DEBUG_INST_ADDR_BASE_IDX 1 #define mmRLC_JUMP_TABLE_RESTORE 0x4c1e #define mmRLC_JUMP_TABLE_RESTORE_BASE_IDX 1 #define mmRLC_PG_DELAY_2 0x4c1f #define mmRLC_PG_DELAY_2_BASE_IDX 1 +#define mmRLC_GPM_DEBUG_INST_A 0x4c22 +#define mmRLC_GPM_DEBUG_INST_A_BASE_IDX 1 +#define mmRLC_GPM_DEBUG_INST_B 0x4c23 +#define mmRLC_GPM_DEBUG_INST_B_BASE_IDX 1 #define mmRLC_GPU_CLOCK_COUNT_LSB 0x4c24 #define mmRLC_GPU_CLOCK_COUNT_LSB_BASE_IDX 1 #define mmRLC_GPU_CLOCK_COUNT_MSB 0x4c25 @@ -9720,6 +9730,8 @@ #define mmRLC_SPM_THREAD_TRACE_CTRL_BASE_IDX 1 #define mmRLC_LB_CNTR_2 0x4de7 #define mmRLC_LB_CNTR_2_BASE_IDX 1 +#define mmRLC_LX6_CORE_PDEBUG_INST 0x4deb +#define mmRLC_LX6_CORE_PDEBUG_INST_BASE_IDX 1 #define mmRLC_CPAXI_DOORBELL_MON_CTRL 0x4df1 #define mmRLC_CPAXI_DOORBELL_MON_CTRL_BASE_IDX 1 #define mmRLC_CPAXI_DOORBELL_MON_STAT 0x4df2 diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_sh_mask.h index efc16ddf274a..2dfa0e5b1aa3 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_sh_mask.h @@ -6822,6 +6822,8 @@ #define VM_L2_PROTECTION_FAULT_STATUS__VMID__SHIFT 0x14 #define VM_L2_PROTECTION_FAULT_STATUS__VF__SHIFT 0x18 #define VM_L2_PROTECTION_FAULT_STATUS__VFID__SHIFT 0x19 +#define VM_L2_PROTECTION_FAULT_STATUS__UCE__SHIFT 0x1d +#define VM_L2_PROTECTION_FAULT_STATUS__FED__SHIFT 0x1e #define VM_L2_PROTECTION_FAULT_STATUS__MORE_FAULTS_MASK 0x00000001L #define VM_L2_PROTECTION_FAULT_STATUS__WALKER_ERROR_MASK 0x0000000EL #define VM_L2_PROTECTION_FAULT_STATUS__PERMISSION_FAULTS_MASK 0x000000F0L @@ -6832,6 +6834,8 @@ #define VM_L2_PROTECTION_FAULT_STATUS__VMID_MASK 0x00F00000L #define VM_L2_PROTECTION_FAULT_STATUS__VF_MASK 0x01000000L #define VM_L2_PROTECTION_FAULT_STATUS__VFID_MASK 0x1E000000L +#define VM_L2_PROTECTION_FAULT_STATUS__UCE_MASK 0x20000000L +#define VM_L2_PROTECTION_FAULT_STATUS__FED_MASK 0x40000000L //VM_L2_PROTECTION_FAULT_ADDR_LO32 #define VM_L2_PROTECTION_FAULT_ADDR_LO32__LOGICAL_PAGE_ADDR_LO32__SHIFT 0x0 #define VM_L2_PROTECTION_FAULT_ADDR_LO32__LOGICAL_PAGE_ADDR_LO32_MASK 0xFFFFFFFFL diff --git a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_offset.h index 8b931bbabe70..969e006b859b 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_offset.h @@ -237,6 +237,10 @@ #define regSEM_REGISTER_LAST_PART2_BASE_IDX 0 #define regIH_CLIENT_CFG 0x0184 #define regIH_CLIENT_CFG_BASE_IDX 0 +#define regIH_RING1_CLIENT_CFG_INDEX 0x0185 +#define regIH_RING1_CLIENT_CFG_INDEX_BASE_IDX 0 +#define regIH_RING1_CLIENT_CFG_DATA 0x0186 +#define regIH_RING1_CLIENT_CFG_DATA_BASE_IDX 0 #define regIH_CLIENT_CFG_INDEX 0x0188 #define regIH_CLIENT_CFG_INDEX_BASE_IDX 0 #define regIH_CLIENT_CFG_DATA 0x0189 diff --git a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_sh_mask.h index f262f44fa68c..a672a91e58f0 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/oss/osssys_6_0_0_sh_mask.h @@ -888,6 +888,16 @@ //IH_CLIENT_CFG #define IH_CLIENT_CFG__TOTAL_CLIENT_NUM__SHIFT 0x0 #define IH_CLIENT_CFG__TOTAL_CLIENT_NUM_MASK 0x0000003FL +//IH_RING1_CLIENT_CFG_INDEX +#define IH_RING1_CLIENT_CFG_INDEX__INDEX__SHIFT 0x0 +#define IH_RING1_CLIENT_CFG_INDEX__INDEX_MASK 0x00000007L +//IH_RING1_CLIENT_CFG_DATA +#define IH_RING1_CLIENT_CFG_DATA__CLIENT_ID__SHIFT 0x0 +#define IH_RING1_CLIENT_CFG_DATA__SOURCE_ID__SHIFT 0x8 +#define IH_RING1_CLIENT_CFG_DATA__SOURCE_ID_MATCH_ENABLE__SHIFT 0x10 +#define IH_RING1_CLIENT_CFG_DATA__CLIENT_ID_MASK 0x000000FFL +#define IH_RING1_CLIENT_CFG_DATA__SOURCE_ID_MASK 0x0000FF00L +#define IH_RING1_CLIENT_CFG_DATA__SOURCE_ID_MATCH_ENABLE_MASK 0x00010000L //IH_CLIENT_CFG_INDEX #define IH_CLIENT_CFG_INDEX__INDEX__SHIFT 0x0 #define IH_CLIENT_CFG_INDEX__INDEX_MASK 0x0000001FL diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_offset.h new file mode 100644 index 000000000000..da7e31fedd58 --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_offset.h @@ -0,0 +1,511 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _smuio_14_0_2_OFFSET_HEADER +#define _smuio_14_0_2_OFFSET_HEADER + + + +// addressBlock: smuio_smuio_tsc_SmuSmuioDec +// base address: 0x5a8a0 +#define regPWROK_REFCLK_GAP_CYCLES 0x0028 +#define regPWROK_REFCLK_GAP_CYCLES_BASE_IDX 1 +#define regGOLDEN_TSC_INCREMENT_UPPER 0x002b +#define regGOLDEN_TSC_INCREMENT_UPPER_BASE_IDX 1 +#define regGOLDEN_TSC_INCREMENT_LOWER 0x002c +#define regGOLDEN_TSC_INCREMENT_LOWER_BASE_IDX 1 +#define regGOLDEN_TSC_COUNT_UPPER 0x002d +#define regGOLDEN_TSC_COUNT_UPPER_BASE_IDX 1 +#define regGOLDEN_TSC_COUNT_LOWER 0x002e +#define regGOLDEN_TSC_COUNT_LOWER_BASE_IDX 1 +#define regSOC_GOLDEN_TSC_SHADOW_UPPER 0x002f +#define regSOC_GOLDEN_TSC_SHADOW_UPPER_BASE_IDX 1 +#define regSOC_GOLDEN_TSC_SHADOW_LOWER 0x0030 +#define regSOC_GOLDEN_TSC_SHADOW_LOWER_BASE_IDX 1 +#define regSOC_GAP_PWROK 0x0031 +#define regSOC_GAP_PWROK_BASE_IDX 1 + + +// addressBlock: smuio_smuio_swtimer_SmuSmuioDec +// base address: 0x5aca8 +#define regPWR_VIRT_RESET_REQ 0x012a +#define regPWR_VIRT_RESET_REQ_BASE_IDX 1 +#define regPWR_DISP_TIMER_CONTROL 0x012b +#define regPWR_DISP_TIMER_CONTROL_BASE_IDX 1 +#define regPWR_DISP_TIMER_DEBUG 0x012c +#define regPWR_DISP_TIMER_DEBUG_BASE_IDX 1 +#define regPWR_DISP_TIMER2_CONTROL 0x012d +#define regPWR_DISP_TIMER2_CONTROL_BASE_IDX 1 +#define regPWR_DISP_TIMER2_DEBUG 0x012e +#define regPWR_DISP_TIMER2_DEBUG_BASE_IDX 1 +#define regPWR_DISP_TIMER_GLOBAL_CONTROL 0x012f +#define regPWR_DISP_TIMER_GLOBAL_CONTROL_BASE_IDX 1 +#define regPWR_IH_CONTROL 0x0130 +#define regPWR_IH_CONTROL_BASE_IDX 1 + + +// addressBlock: smuio_smuio_misc_SmuSmuioDec +// base address: 0x5a000 +#define regSMUIO_MCM_CONFIG 0x0023 +#define regSMUIO_MCM_CONFIG_BASE_IDX 0 +#define regIP_DISCOVERY_VERSION 0x0000 +#define regIP_DISCOVERY_VERSION_BASE_IDX 1 +#define regSCRATCH_REGISTER0 0x01bd +#define regSCRATCH_REGISTER0_BASE_IDX 1 +#define regSCRATCH_REGISTER1 0x01be +#define regSCRATCH_REGISTER1_BASE_IDX 1 +#define regSCRATCH_REGISTER2 0x01bf +#define regSCRATCH_REGISTER2_BASE_IDX 1 +#define regSCRATCH_REGISTER3 0x01c0 +#define regSCRATCH_REGISTER3_BASE_IDX 1 +#define regSCRATCH_REGISTER4 0x01c1 +#define regSCRATCH_REGISTER4_BASE_IDX 1 +#define regSCRATCH_REGISTER5 0x01c2 +#define regSCRATCH_REGISTER5_BASE_IDX 1 +#define regSCRATCH_REGISTER6 0x01c3 +#define regSCRATCH_REGISTER6_BASE_IDX 1 +#define regSCRATCH_REGISTER7 0x01c4 +#define regSCRATCH_REGISTER7_BASE_IDX 1 + + +// addressBlock: smuio_smuio_i2c_SmuSmuioDec +// base address: 0x5a100 +#define regCKSVII2C_IC_CON 0x0040 +#define regCKSVII2C_IC_CON_BASE_IDX 0 +#define regCKSVII2C_IC_TAR 0x0041 +#define regCKSVII2C_IC_TAR_BASE_IDX 0 +#define regCKSVII2C_IC_SAR 0x0042 +#define regCKSVII2C_IC_SAR_BASE_IDX 0 +#define regCKSVII2C_IC_HS_MADDR 0x0043 +#define regCKSVII2C_IC_HS_MADDR_BASE_IDX 0 +#define regCKSVII2C_IC_DATA_CMD 0x0044 +#define regCKSVII2C_IC_DATA_CMD_BASE_IDX 0 +#define regCKSVII2C_IC_SS_SCL_HCNT 0x0045 +#define regCKSVII2C_IC_SS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C_IC_SS_SCL_LCNT 0x0046 +#define regCKSVII2C_IC_SS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C_IC_FS_SCL_HCNT 0x0047 +#define regCKSVII2C_IC_FS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C_IC_FS_SCL_LCNT 0x0048 +#define regCKSVII2C_IC_FS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C_IC_HS_SCL_HCNT 0x0049 +#define regCKSVII2C_IC_HS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C_IC_HS_SCL_LCNT 0x004a +#define regCKSVII2C_IC_HS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C_IC_INTR_STAT 0x004b +#define regCKSVII2C_IC_INTR_STAT_BASE_IDX 0 +#define regCKSVII2C_IC_INTR_MASK 0x004c +#define regCKSVII2C_IC_INTR_MASK_BASE_IDX 0 +#define regCKSVII2C_IC_RAW_INTR_STAT 0x004d +#define regCKSVII2C_IC_RAW_INTR_STAT_BASE_IDX 0 +#define regCKSVII2C_IC_RX_TL 0x004e +#define regCKSVII2C_IC_RX_TL_BASE_IDX 0 +#define regCKSVII2C_IC_TX_TL 0x004f +#define regCKSVII2C_IC_TX_TL_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_INTR 0x0050 +#define regCKSVII2C_IC_CLR_INTR_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_RX_UNDER 0x0051 +#define regCKSVII2C_IC_CLR_RX_UNDER_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_RX_OVER 0x0052 +#define regCKSVII2C_IC_CLR_RX_OVER_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_TX_OVER 0x0053 +#define regCKSVII2C_IC_CLR_TX_OVER_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_RD_REQ 0x0054 +#define regCKSVII2C_IC_CLR_RD_REQ_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_TX_ABRT 0x0055 +#define regCKSVII2C_IC_CLR_TX_ABRT_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_RX_DONE 0x0056 +#define regCKSVII2C_IC_CLR_RX_DONE_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_ACTIVITY 0x0057 +#define regCKSVII2C_IC_CLR_ACTIVITY_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_STOP_DET 0x0058 +#define regCKSVII2C_IC_CLR_STOP_DET_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_START_DET 0x0059 +#define regCKSVII2C_IC_CLR_START_DET_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_GEN_CALL 0x005a +#define regCKSVII2C_IC_CLR_GEN_CALL_BASE_IDX 0 +#define regCKSVII2C_IC_ENABLE 0x005b +#define regCKSVII2C_IC_ENABLE_BASE_IDX 0 +#define regCKSVII2C_IC_STATUS 0x005c +#define regCKSVII2C_IC_STATUS_BASE_IDX 0 +#define regCKSVII2C_IC_TXFLR 0x005d +#define regCKSVII2C_IC_TXFLR_BASE_IDX 0 +#define regCKSVII2C_IC_RXFLR 0x005e +#define regCKSVII2C_IC_RXFLR_BASE_IDX 0 +#define regCKSVII2C_IC_SDA_HOLD 0x005f +#define regCKSVII2C_IC_SDA_HOLD_BASE_IDX 0 +#define regCKSVII2C_IC_TX_ABRT_SOURCE 0x0060 +#define regCKSVII2C_IC_TX_ABRT_SOURCE_BASE_IDX 0 +#define regCKSVII2C_IC_SLV_DATA_NACK_ONLY 0x0061 +#define regCKSVII2C_IC_SLV_DATA_NACK_ONLY_BASE_IDX 0 +#define regCKSVII2C_IC_DMA_CR 0x0062 +#define regCKSVII2C_IC_DMA_CR_BASE_IDX 0 +#define regCKSVII2C_IC_DMA_TDLR 0x0063 +#define regCKSVII2C_IC_DMA_TDLR_BASE_IDX 0 +#define regCKSVII2C_IC_DMA_RDLR 0x0064 +#define regCKSVII2C_IC_DMA_RDLR_BASE_IDX 0 +#define regCKSVII2C_IC_SDA_SETUP 0x0065 +#define regCKSVII2C_IC_SDA_SETUP_BASE_IDX 0 +#define regCKSVII2C_IC_ACK_GENERAL_CALL 0x0066 +#define regCKSVII2C_IC_ACK_GENERAL_CALL_BASE_IDX 0 +#define regCKSVII2C_IC_ENABLE_STATUS 0x0067 +#define regCKSVII2C_IC_ENABLE_STATUS_BASE_IDX 0 +#define regCKSVII2C_IC_FS_SPKLEN 0x0068 +#define regCKSVII2C_IC_FS_SPKLEN_BASE_IDX 0 +#define regCKSVII2C_IC_HS_SPKLEN 0x0069 +#define regCKSVII2C_IC_HS_SPKLEN_BASE_IDX 0 +#define regCKSVII2C_IC_CLR_RESTART_DET 0x006a +#define regCKSVII2C_IC_CLR_RESTART_DET_BASE_IDX 0 +#define regCKSVII2C_IC_COMP_PARAM_1 0x006d +#define regCKSVII2C_IC_COMP_PARAM_1_BASE_IDX 0 +#define regCKSVII2C_IC_COMP_VERSION 0x006e +#define regCKSVII2C_IC_COMP_VERSION_BASE_IDX 0 +#define regCKSVII2C_IC_COMP_TYPE 0x006f +#define regCKSVII2C_IC_COMP_TYPE_BASE_IDX 0 +#define regCKSVII2C1_IC_CON 0x0080 +#define regCKSVII2C1_IC_CON_BASE_IDX 0 +#define regCKSVII2C1_IC_TAR 0x0081 +#define regCKSVII2C1_IC_TAR_BASE_IDX 0 +#define regCKSVII2C1_IC_SAR 0x0082 +#define regCKSVII2C1_IC_SAR_BASE_IDX 0 +#define regCKSVII2C1_IC_HS_MADDR 0x0083 +#define regCKSVII2C1_IC_HS_MADDR_BASE_IDX 0 +#define regCKSVII2C1_IC_DATA_CMD 0x0084 +#define regCKSVII2C1_IC_DATA_CMD_BASE_IDX 0 +#define regCKSVII2C1_IC_SS_SCL_HCNT 0x0085 +#define regCKSVII2C1_IC_SS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_SS_SCL_LCNT 0x0086 +#define regCKSVII2C1_IC_SS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_FS_SCL_HCNT 0x0087 +#define regCKSVII2C1_IC_FS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_FS_SCL_LCNT 0x0088 +#define regCKSVII2C1_IC_FS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_HS_SCL_HCNT 0x0089 +#define regCKSVII2C1_IC_HS_SCL_HCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_HS_SCL_LCNT 0x008a +#define regCKSVII2C1_IC_HS_SCL_LCNT_BASE_IDX 0 +#define regCKSVII2C1_IC_INTR_STAT 0x008b +#define regCKSVII2C1_IC_INTR_STAT_BASE_IDX 0 +#define regCKSVII2C1_IC_INTR_MASK 0x008c +#define regCKSVII2C1_IC_INTR_MASK_BASE_IDX 0 +#define regCKSVII2C1_IC_RAW_INTR_STAT 0x008d +#define regCKSVII2C1_IC_RAW_INTR_STAT_BASE_IDX 0 +#define regCKSVII2C1_IC_RX_TL 0x008e +#define regCKSVII2C1_IC_RX_TL_BASE_IDX 0 +#define regCKSVII2C1_IC_TX_TL 0x008f +#define regCKSVII2C1_IC_TX_TL_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_INTR 0x0090 +#define regCKSVII2C1_IC_CLR_INTR_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_RX_UNDER 0x0091 +#define regCKSVII2C1_IC_CLR_RX_UNDER_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_RX_OVER 0x0092 +#define regCKSVII2C1_IC_CLR_RX_OVER_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_TX_OVER 0x0093 +#define regCKSVII2C1_IC_CLR_TX_OVER_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_RD_REQ 0x0094 +#define regCKSVII2C1_IC_CLR_RD_REQ_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_TX_ABRT 0x0095 +#define regCKSVII2C1_IC_CLR_TX_ABRT_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_RX_DONE 0x0096 +#define regCKSVII2C1_IC_CLR_RX_DONE_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_ACTIVITY 0x0097 +#define regCKSVII2C1_IC_CLR_ACTIVITY_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_STOP_DET 0x0098 +#define regCKSVII2C1_IC_CLR_STOP_DET_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_START_DET 0x0099 +#define regCKSVII2C1_IC_CLR_START_DET_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_GEN_CALL 0x009a +#define regCKSVII2C1_IC_CLR_GEN_CALL_BASE_IDX 0 +#define regCKSVII2C1_IC_ENABLE 0x009b +#define regCKSVII2C1_IC_ENABLE_BASE_IDX 0 +#define regCKSVII2C1_IC_STATUS 0x009c +#define regCKSVII2C1_IC_STATUS_BASE_IDX 0 +#define regCKSVII2C1_IC_TXFLR 0x009d +#define regCKSVII2C1_IC_TXFLR_BASE_IDX 0 +#define regCKSVII2C1_IC_RXFLR 0x009e +#define regCKSVII2C1_IC_RXFLR_BASE_IDX 0 +#define regCKSVII2C1_IC_SDA_HOLD 0x009f +#define regCKSVII2C1_IC_SDA_HOLD_BASE_IDX 0 +#define regCKSVII2C1_IC_TX_ABRT_SOURCE 0x00a0 +#define regCKSVII2C1_IC_TX_ABRT_SOURCE_BASE_IDX 0 +#define regCKSVII2C1_IC_SLV_DATA_NACK_ONLY 0x00a1 +#define regCKSVII2C1_IC_SLV_DATA_NACK_ONLY_BASE_IDX 0 +#define regCKSVII2C1_IC_DMA_CR 0x00a2 +#define regCKSVII2C1_IC_DMA_CR_BASE_IDX 0 +#define regCKSVII2C1_IC_DMA_TDLR 0x00a3 +#define regCKSVII2C1_IC_DMA_TDLR_BASE_IDX 0 +#define regCKSVII2C1_IC_DMA_RDLR 0x00a4 +#define regCKSVII2C1_IC_DMA_RDLR_BASE_IDX 0 +#define regCKSVII2C1_IC_SDA_SETUP 0x00a5 +#define regCKSVII2C1_IC_SDA_SETUP_BASE_IDX 0 +#define regCKSVII2C1_IC_ACK_GENERAL_CALL 0x00a6 +#define regCKSVII2C1_IC_ACK_GENERAL_CALL_BASE_IDX 0 +#define regCKSVII2C1_IC_ENABLE_STATUS 0x00a7 +#define regCKSVII2C1_IC_ENABLE_STATUS_BASE_IDX 0 +#define regCKSVII2C1_IC_FS_SPKLEN 0x00a8 +#define regCKSVII2C1_IC_FS_SPKLEN_BASE_IDX 0 +#define regCKSVII2C1_IC_HS_SPKLEN 0x00a9 +#define regCKSVII2C1_IC_HS_SPKLEN_BASE_IDX 0 +#define regCKSVII2C1_IC_CLR_RESTART_DET 0x00aa +#define regCKSVII2C1_IC_CLR_RESTART_DET_BASE_IDX 0 +#define regCKSVII2C1_IC_COMP_PARAM_1 0x00ad +#define regCKSVII2C1_IC_COMP_PARAM_1_BASE_IDX 0 +#define regCKSVII2C1_IC_COMP_VERSION 0x00ae +#define regCKSVII2C1_IC_COMP_VERSION_BASE_IDX 0 +#define regCKSVII2C1_IC_COMP_TYPE 0x00af +#define regCKSVII2C1_IC_COMP_TYPE_BASE_IDX 0 +#define regSMUIO_PWRMGT 0x018c +#define regSMUIO_PWRMGT_BASE_IDX 0 + + +// addressBlock: smuio_smuio_rom_SmuSmuioDec +// base address: 0x5a380 +#define regROM_CNTL 0x00e0 +#define regROM_CNTL_BASE_IDX 0 +#define regPAGE_MIRROR_CNTL 0x00e1 +#define regPAGE_MIRROR_CNTL_BASE_IDX 0 +#define regROM_STATUS 0x00e2 +#define regROM_STATUS_BASE_IDX 0 +#define regCGTT_ROM_CLK_CTRL0 0x00e3 +#define regCGTT_ROM_CLK_CTRL0_BASE_IDX 0 +#define regROM_INDEX 0x00e4 +#define regROM_INDEX_BASE_IDX 0 +#define regROM_DATA 0x00e5 +#define regROM_DATA_BASE_IDX 0 +#define regROM_START 0x00e6 +#define regROM_START_BASE_IDX 0 +#define regROM_SW_CNTL 0x00e8 +#define regROM_SW_CNTL_BASE_IDX 0 +#define regROM_SW_STATUS 0x00e9 +#define regROM_SW_STATUS_BASE_IDX 0 +#define regROM_SW_COMMAND 0x00ea +#define regROM_SW_COMMAND_BASE_IDX 0 +#define regROM_SW_DATA_1 0x00ec +#define regROM_SW_DATA_1_BASE_IDX 0 +#define regROM_SW_DATA_2 0x00ed +#define regROM_SW_DATA_2_BASE_IDX 0 +#define regROM_SW_DATA_3 0x00ee +#define regROM_SW_DATA_3_BASE_IDX 0 +#define regROM_SW_DATA_4 0x00ef +#define regROM_SW_DATA_4_BASE_IDX 0 +#define regROM_SW_DATA_5 0x00f0 +#define regROM_SW_DATA_5_BASE_IDX 0 +#define regROM_SW_DATA_6 0x00f1 +#define regROM_SW_DATA_6_BASE_IDX 0 +#define regROM_SW_DATA_7 0x00f2 +#define regROM_SW_DATA_7_BASE_IDX 0 +#define regROM_SW_DATA_8 0x00f3 +#define regROM_SW_DATA_8_BASE_IDX 0 +#define regROM_SW_DATA_9 0x00f4 +#define regROM_SW_DATA_9_BASE_IDX 0 +#define regROM_SW_DATA_10 0x00f5 +#define regROM_SW_DATA_10_BASE_IDX 0 +#define regROM_SW_DATA_11 0x00f6 +#define regROM_SW_DATA_11_BASE_IDX 0 +#define regROM_SW_DATA_12 0x00f7 +#define regROM_SW_DATA_12_BASE_IDX 0 +#define regROM_SW_DATA_13 0x00f8 +#define regROM_SW_DATA_13_BASE_IDX 0 +#define regROM_SW_DATA_14 0x00f9 +#define regROM_SW_DATA_14_BASE_IDX 0 +#define regROM_SW_DATA_15 0x00fa +#define regROM_SW_DATA_15_BASE_IDX 0 +#define regROM_SW_DATA_16 0x00fb +#define regROM_SW_DATA_16_BASE_IDX 0 +#define regROM_SW_DATA_17 0x00fc +#define regROM_SW_DATA_17_BASE_IDX 0 +#define regROM_SW_DATA_18 0x00fd +#define regROM_SW_DATA_18_BASE_IDX 0 +#define regROM_SW_DATA_19 0x00fe +#define regROM_SW_DATA_19_BASE_IDX 0 +#define regROM_SW_DATA_20 0x00ff +#define regROM_SW_DATA_20_BASE_IDX 0 +#define regROM_SW_DATA_21 0x0100 +#define regROM_SW_DATA_21_BASE_IDX 0 +#define regROM_SW_DATA_22 0x0101 +#define regROM_SW_DATA_22_BASE_IDX 0 +#define regROM_SW_DATA_23 0x0102 +#define regROM_SW_DATA_23_BASE_IDX 0 +#define regROM_SW_DATA_24 0x0103 +#define regROM_SW_DATA_24_BASE_IDX 0 +#define regROM_SW_DATA_25 0x0104 +#define regROM_SW_DATA_25_BASE_IDX 0 +#define regROM_SW_DATA_26 0x0105 +#define regROM_SW_DATA_26_BASE_IDX 0 +#define regROM_SW_DATA_27 0x0106 +#define regROM_SW_DATA_27_BASE_IDX 0 +#define regROM_SW_DATA_28 0x0107 +#define regROM_SW_DATA_28_BASE_IDX 0 +#define regROM_SW_DATA_29 0x0108 +#define regROM_SW_DATA_29_BASE_IDX 0 +#define regROM_SW_DATA_30 0x0109 +#define regROM_SW_DATA_30_BASE_IDX 0 +#define regROM_SW_DATA_31 0x010a +#define regROM_SW_DATA_31_BASE_IDX 0 +#define regROM_SW_DATA_32 0x010b +#define regROM_SW_DATA_32_BASE_IDX 0 +#define regROM_SW_DATA_33 0x010c +#define regROM_SW_DATA_33_BASE_IDX 0 +#define regROM_SW_DATA_34 0x010d +#define regROM_SW_DATA_34_BASE_IDX 0 +#define regROM_SW_DATA_35 0x010e +#define regROM_SW_DATA_35_BASE_IDX 0 +#define regROM_SW_DATA_36 0x010f +#define regROM_SW_DATA_36_BASE_IDX 0 +#define regROM_SW_DATA_37 0x0110 +#define regROM_SW_DATA_37_BASE_IDX 0 +#define regROM_SW_DATA_38 0x0111 +#define regROM_SW_DATA_38_BASE_IDX 0 +#define regROM_SW_DATA_39 0x0112 +#define regROM_SW_DATA_39_BASE_IDX 0 +#define regROM_SW_DATA_40 0x0113 +#define regROM_SW_DATA_40_BASE_IDX 0 +#define regROM_SW_DATA_41 0x0114 +#define regROM_SW_DATA_41_BASE_IDX 0 +#define regROM_SW_DATA_42 0x0115 +#define regROM_SW_DATA_42_BASE_IDX 0 +#define regROM_SW_DATA_43 0x0116 +#define regROM_SW_DATA_43_BASE_IDX 0 +#define regROM_SW_DATA_44 0x0117 +#define regROM_SW_DATA_44_BASE_IDX 0 +#define regROM_SW_DATA_45 0x0118 +#define regROM_SW_DATA_45_BASE_IDX 0 +#define regROM_SW_DATA_46 0x0119 +#define regROM_SW_DATA_46_BASE_IDX 0 +#define regROM_SW_DATA_47 0x011a +#define regROM_SW_DATA_47_BASE_IDX 0 +#define regROM_SW_DATA_48 0x011b +#define regROM_SW_DATA_48_BASE_IDX 0 +#define regROM_SW_DATA_49 0x011c +#define regROM_SW_DATA_49_BASE_IDX 0 +#define regROM_SW_DATA_50 0x011d +#define regROM_SW_DATA_50_BASE_IDX 0 +#define regROM_SW_DATA_51 0x011e +#define regROM_SW_DATA_51_BASE_IDX 0 +#define regROM_SW_DATA_52 0x011f +#define regROM_SW_DATA_52_BASE_IDX 0 +#define regROM_SW_DATA_53 0x0120 +#define regROM_SW_DATA_53_BASE_IDX 0 +#define regROM_SW_DATA_54 0x0121 +#define regROM_SW_DATA_54_BASE_IDX 0 +#define regROM_SW_DATA_55 0x0122 +#define regROM_SW_DATA_55_BASE_IDX 0 +#define regROM_SW_DATA_56 0x0123 +#define regROM_SW_DATA_56_BASE_IDX 0 +#define regROM_SW_DATA_57 0x0124 +#define regROM_SW_DATA_57_BASE_IDX 0 +#define regROM_SW_DATA_58 0x0125 +#define regROM_SW_DATA_58_BASE_IDX 0 +#define regROM_SW_DATA_59 0x0126 +#define regROM_SW_DATA_59_BASE_IDX 0 +#define regROM_SW_DATA_60 0x0127 +#define regROM_SW_DATA_60_BASE_IDX 0 +#define regROM_SW_DATA_61 0x0128 +#define regROM_SW_DATA_61_BASE_IDX 0 +#define regROM_SW_DATA_62 0x0129 +#define regROM_SW_DATA_62_BASE_IDX 0 +#define regROM_SW_DATA_63 0x012a +#define regROM_SW_DATA_63_BASE_IDX 0 +#define regROM_SW_DATA_64 0x012b +#define regROM_SW_DATA_64_BASE_IDX 0 + + +// addressBlock: smuio_smuio_gpio_SmuSmuioDec +// base address: 0x5a500 +#define regSMU_GPIOPAD_SW_INT_STAT 0x0140 +#define regSMU_GPIOPAD_SW_INT_STAT_BASE_IDX 0 +#define regSMU_GPIOPAD_MASK 0x0141 +#define regSMU_GPIOPAD_MASK_BASE_IDX 0 +#define regSMU_GPIOPAD_A 0x0142 +#define regSMU_GPIOPAD_A_BASE_IDX 0 +#define regSMU_GPIOPAD_TXIMPSEL 0x0143 +#define regSMU_GPIOPAD_TXIMPSEL_BASE_IDX 0 +#define regSMU_GPIOPAD_EN 0x0144 +#define regSMU_GPIOPAD_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_Y 0x0145 +#define regSMU_GPIOPAD_Y_BASE_IDX 0 +#define regSMU_GPIOPAD_RXEN 0x0146 +#define regSMU_GPIOPAD_RXEN_BASE_IDX 0 +#define regSMU_GPIOPAD_RCVR_SEL0 0x0147 +#define regSMU_GPIOPAD_RCVR_SEL0_BASE_IDX 0 +#define regSMU_GPIOPAD_RCVR_SEL1 0x0148 +#define regSMU_GPIOPAD_RCVR_SEL1_BASE_IDX 0 +#define regSMU_GPIOPAD_PU_EN 0x0149 +#define regSMU_GPIOPAD_PU_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_PD_EN 0x014a +#define regSMU_GPIOPAD_PD_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_PINSTRAPS 0x014b +#define regSMU_GPIOPAD_PINSTRAPS_BASE_IDX 0 +#define regDFT_PINSTRAPS 0x014c +#define regDFT_PINSTRAPS_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_STAT_EN 0x014d +#define regSMU_GPIOPAD_INT_STAT_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_STAT 0x014e +#define regSMU_GPIOPAD_INT_STAT_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_STAT_AK 0x014f +#define regSMU_GPIOPAD_INT_STAT_AK_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_EN 0x0150 +#define regSMU_GPIOPAD_INT_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_TYPE 0x0151 +#define regSMU_GPIOPAD_INT_TYPE_BASE_IDX 0 +#define regSMU_GPIOPAD_INT_POLARITY 0x0152 +#define regSMU_GPIOPAD_INT_POLARITY_BASE_IDX 0 +#define regSMUIO_PCC_GPIO_SELECT 0x0155 +#define regSMUIO_PCC_GPIO_SELECT_BASE_IDX 0 +#define regSMU_GPIOPAD_S0 0x0156 +#define regSMU_GPIOPAD_S0_BASE_IDX 0 +#define regSMU_GPIOPAD_S1 0x0157 +#define regSMU_GPIOPAD_S1_BASE_IDX 0 +#define regSMU_GPIOPAD_SCHMEN 0x0158 +#define regSMU_GPIOPAD_SCHMEN_BASE_IDX 0 +#define regSMU_GPIOPAD_SCL_EN 0x0159 +#define regSMU_GPIOPAD_SCL_EN_BASE_IDX 0 +#define regSMU_GPIOPAD_SDA_EN 0x015a +#define regSMU_GPIOPAD_SDA_EN_BASE_IDX 0 +#define regSMUIO_GPIO_INT0_SELECT 0x015b +#define regSMUIO_GPIO_INT0_SELECT_BASE_IDX 0 +#define regSMUIO_GPIO_INT1_SELECT 0x015c +#define regSMUIO_GPIO_INT1_SELECT_BASE_IDX 0 +#define regSMUIO_GPIO_INT2_SELECT 0x015d +#define regSMUIO_GPIO_INT2_SELECT_BASE_IDX 0 +#define regSMUIO_GPIO_INT3_SELECT 0x015e +#define regSMUIO_GPIO_INT3_SELECT_BASE_IDX 0 +#define regSMU_GPIOPAD_MP_INT0_STAT 0x015f +#define regSMU_GPIOPAD_MP_INT0_STAT_BASE_IDX 0 +#define regSMU_GPIOPAD_MP_INT1_STAT 0x0160 +#define regSMU_GPIOPAD_MP_INT1_STAT_BASE_IDX 0 +#define regSMU_GPIOPAD_MP_INT2_STAT 0x0161 +#define regSMU_GPIOPAD_MP_INT2_STAT_BASE_IDX 0 +#define regSMU_GPIOPAD_MP_INT3_STAT 0x0162 +#define regSMU_GPIOPAD_MP_INT3_STAT_BASE_IDX 0 +#define regSMIO_INDEX 0x0163 +#define regSMIO_INDEX_BASE_IDX 0 +#define regS0_VID_SMIO_CNTL 0x0164 +#define regS0_VID_SMIO_CNTL_BASE_IDX 0 +#define regS1_VID_SMIO_CNTL 0x0165 +#define regS1_VID_SMIO_CNTL_BASE_IDX 0 +#define regOPEN_DRAIN_SELECT 0x0166 +#define regOPEN_DRAIN_SELECT_BASE_IDX 0 +#define regSMIO_ENABLE 0x0167 +#define regSMIO_ENABLE_BASE_IDX 0 + +#endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_sh_mask.h new file mode 100644 index 000000000000..6204505e553b --- /dev/null +++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_14_0_2_sh_mask.h @@ -0,0 +1,1106 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _smuio_14_0_2_SH_MASK_HEADER +#define _smuio_14_0_2_SH_MASK_HEADER + + +// addressBlock: smuio_smuio_tsc_SmuSmuioDec +//PWROK_REFCLK_GAP_CYCLES +#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PreAssertion_clkgap_cycles__SHIFT 0x0 +#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PostAssertion_clkgap_cycles__SHIFT 0x8 +#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PreAssertion_clkgap_cycles_MASK 0x000000FFL +#define PWROK_REFCLK_GAP_CYCLES__Pwrok_PostAssertion_clkgap_cycles_MASK 0x0000FF00L +//GOLDEN_TSC_INCREMENT_UPPER +#define GOLDEN_TSC_INCREMENT_UPPER__GoldenTscIncrementUpper__SHIFT 0x0 +#define GOLDEN_TSC_INCREMENT_UPPER__GoldenTscIncrementUpper_MASK 0x00FFFFFFL +//GOLDEN_TSC_INCREMENT_LOWER +#define GOLDEN_TSC_INCREMENT_LOWER__GoldenTscIncrementLower__SHIFT 0x0 +#define GOLDEN_TSC_INCREMENT_LOWER__GoldenTscIncrementLower_MASK 0xFFFFFFFFL +//GOLDEN_TSC_COUNT_UPPER +#define GOLDEN_TSC_COUNT_UPPER__GoldenTscCountUpper__SHIFT 0x0 +#define GOLDEN_TSC_COUNT_UPPER__GoldenTscCountUpper_MASK 0x00FFFFFFL +//GOLDEN_TSC_COUNT_LOWER +#define GOLDEN_TSC_COUNT_LOWER__GoldenTscCountLower__SHIFT 0x0 +#define GOLDEN_TSC_COUNT_LOWER__GoldenTscCountLower_MASK 0xFFFFFFFFL +//SOC_GOLDEN_TSC_SHADOW_UPPER +#define SOC_GOLDEN_TSC_SHADOW_UPPER__SocGoldenTscShadowUpper__SHIFT 0x0 +#define SOC_GOLDEN_TSC_SHADOW_UPPER__SocGoldenTscShadowUpper_MASK 0x00FFFFFFL +//SOC_GOLDEN_TSC_SHADOW_LOWER +#define SOC_GOLDEN_TSC_SHADOW_LOWER__SocGoldenTscShadowLower__SHIFT 0x0 +#define SOC_GOLDEN_TSC_SHADOW_LOWER__SocGoldenTscShadowLower_MASK 0xFFFFFFFFL +//SOC_GAP_PWROK +#define SOC_GAP_PWROK__soc_gap_pwrok__SHIFT 0x0 +#define SOC_GAP_PWROK__soc_gap_pwrok_MASK 0x00000001L + + +// addressBlock: smuio_smuio_swtimer_SmuSmuioDec +//PWR_VIRT_RESET_REQ +#define PWR_VIRT_RESET_REQ__VF_FLR__SHIFT 0x0 +#define PWR_VIRT_RESET_REQ__PF_FLR__SHIFT 0x1f +#define PWR_VIRT_RESET_REQ__VF_FLR_MASK 0x7FFFFFFFL +#define PWR_VIRT_RESET_REQ__PF_FLR_MASK 0x80000000L +//PWR_DISP_TIMER_CONTROL +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x0 +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x19 +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_DISABLE__SHIFT 0x1a +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK__SHIFT 0x1b +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x1c +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_TYPE__SHIFT 0x1d +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MODE__SHIFT 0x1e +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01FFFFFFL +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_DISABLE_MASK 0x04000000L +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK_MASK 0x08000000L +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x10000000L +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_TYPE_MASK 0x20000000L +#define PWR_DISP_TIMER_CONTROL__DISP_TIMER_INT_MODE_MASK 0x40000000L +//PWR_DISP_TIMER_DEBUG +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_RUNNING__SHIFT 0x0 +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_STAT__SHIFT 0x1 +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT__SHIFT 0x2 +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_RUN_VAL__SHIFT 0x7 +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_RUNNING_MASK 0x00000001L +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_STAT_MASK 0x00000002L +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_INT_MASK 0x00000004L +#define PWR_DISP_TIMER_DEBUG__DISP_TIMER_RUN_VAL_MASK 0xFFFFFF80L +//PWR_DISP_TIMER2_CONTROL +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x0 +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x19 +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_DISABLE__SHIFT 0x1a +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MASK__SHIFT 0x1b +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x1c +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_TYPE__SHIFT 0x1d +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MODE__SHIFT 0x1e +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01FFFFFFL +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_DISABLE_MASK 0x04000000L +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MASK_MASK 0x08000000L +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x10000000L +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_TYPE_MASK 0x20000000L +#define PWR_DISP_TIMER2_CONTROL__DISP_TIMER_INT_MODE_MASK 0x40000000L +//PWR_DISP_TIMER2_DEBUG +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_RUNNING__SHIFT 0x0 +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_STAT__SHIFT 0x1 +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT__SHIFT 0x2 +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_RUN_VAL__SHIFT 0x7 +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_RUNNING_MASK 0x00000001L +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_STAT_MASK 0x00000002L +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_INT_MASK 0x00000004L +#define PWR_DISP_TIMER2_DEBUG__DISP_TIMER_RUN_VAL_MASK 0xFFFFFF80L +//PWR_DISP_TIMER_GLOBAL_CONTROL +#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_WIDTH__SHIFT 0x0 +#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_EN__SHIFT 0xa +#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_WIDTH_MASK 0x000003FFL +#define PWR_DISP_TIMER_GLOBAL_CONTROL__DISP_TIMER_PULSE_EN_MASK 0x00000400L +//PWR_IH_CONTROL +#define PWR_IH_CONTROL__MAX_CREDIT__SHIFT 0x0 +#define PWR_IH_CONTROL__DISP_TIMER_TRIGGER_MASK__SHIFT 0x5 +#define PWR_IH_CONTROL__DISP_TIMER2_TRIGGER_MASK__SHIFT 0x6 +#define PWR_IH_CONTROL__PWR_IH_CLK_GATE_EN__SHIFT 0x1f +#define PWR_IH_CONTROL__MAX_CREDIT_MASK 0x0000001FL +#define PWR_IH_CONTROL__DISP_TIMER_TRIGGER_MASK_MASK 0x00000020L +#define PWR_IH_CONTROL__DISP_TIMER2_TRIGGER_MASK_MASK 0x00000040L +#define PWR_IH_CONTROL__PWR_IH_CLK_GATE_EN_MASK 0x80000000L + + +// addressBlock: smuio_smuio_misc_SmuSmuioDec +//SMUIO_MCM_CONFIG +#define SMUIO_MCM_CONFIG__DIE_ID__SHIFT 0x0 +#define SMUIO_MCM_CONFIG__PKG_TYPE__SHIFT 0x2 +#define SMUIO_MCM_CONFIG__SOCKET_ID__SHIFT 0x8 +#define SMUIO_MCM_CONFIG__PKG_SUBTYPE__SHIFT 0xc +#define SMUIO_MCM_CONFIG__DIE_CONFIG__SHIFT 0xd +#define SMUIO_MCM_CONFIG__CONSOLE_K__SHIFT 0x10 +#define SMUIO_MCM_CONFIG__CONSOLE_A__SHIFT 0x11 +#define SMUIO_MCM_CONFIG__DIE_ID_MASK 0x00000003L +#define SMUIO_MCM_CONFIG__PKG_TYPE_MASK 0x0000001CL +#define SMUIO_MCM_CONFIG__SOCKET_ID_MASK 0x00000300L +#define SMUIO_MCM_CONFIG__PKG_SUBTYPE_MASK 0x00001000L +#define SMUIO_MCM_CONFIG__CONSOLE_K_MASK 0x00010000L +#define SMUIO_MCM_CONFIG__CONSOLE_A_MASK 0x00020000L +//IP_DISCOVERY_VERSION +#define IP_DISCOVERY_VERSION__IP_DISCOVERY_VERSION__SHIFT 0x0 +#define IP_DISCOVERY_VERSION__IP_DISCOVERY_VERSION_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER0 +#define SCRATCH_REGISTER0__ScratchPad0__SHIFT 0x0 +#define SCRATCH_REGISTER0__ScratchPad0_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER1 +#define SCRATCH_REGISTER1__ScratchPad1__SHIFT 0x0 +#define SCRATCH_REGISTER1__ScratchPad1_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER2 +#define SCRATCH_REGISTER2__ScratchPad2__SHIFT 0x0 +#define SCRATCH_REGISTER2__ScratchPad2_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER3 +#define SCRATCH_REGISTER3__ScratchPad3__SHIFT 0x0 +#define SCRATCH_REGISTER3__ScratchPad3_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER4 +#define SCRATCH_REGISTER4__ScratchPad4__SHIFT 0x0 +#define SCRATCH_REGISTER4__ScratchPad4_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER5 +#define SCRATCH_REGISTER5__ScratchPad5__SHIFT 0x0 +#define SCRATCH_REGISTER5__ScratchPad5_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER6 +#define SCRATCH_REGISTER6__ScratchPad6__SHIFT 0x0 +#define SCRATCH_REGISTER6__ScratchPad6_MASK 0xFFFFFFFFL +//SCRATCH_REGISTER7 +#define SCRATCH_REGISTER7__ScratchPad7__SHIFT 0x0 +#define SCRATCH_REGISTER7__ScratchPad7_MASK 0xFFFFFFFFL + + +// addressBlock: smuio_smuio_i2c_SmuSmuioDec +//CKSVII2C_IC_CON +#define CKSVII2C_IC_CON__IC_MASTER_MODE__SHIFT 0x0 +#define CKSVII2C_IC_CON__IC_MAX_SPEED_MODE__SHIFT 0x1 +#define CKSVII2C_IC_CON__IC_10BITADDR_SLAVE__SHIFT 0x3 +#define CKSVII2C_IC_CON__IC_10BITADDR_MASTER__SHIFT 0x4 +#define CKSVII2C_IC_CON__IC_RESTART_EN__SHIFT 0x5 +#define CKSVII2C_IC_CON__IC_SLAVE_DISABLE__SHIFT 0x6 +#define CKSVII2C_IC_CON__STOP_DET_IFADDRESSED__SHIFT 0x7 +#define CKSVII2C_IC_CON__TX_EMPTY_CTRL__SHIFT 0x8 +#define CKSVII2C_IC_CON__RX_FIFO_FULL_HLD_CTRL__SHIFT 0x9 +#define CKSVII2C_IC_CON__BUS_CLEAR_FEATURE_CTRL__SHIFT 0xb +#define CKSVII2C_IC_CON__IC_MASTER_MODE_MASK 0x00000001L +#define CKSVII2C_IC_CON__IC_MAX_SPEED_MODE_MASK 0x00000006L +#define CKSVII2C_IC_CON__IC_10BITADDR_SLAVE_MASK 0x00000008L +#define CKSVII2C_IC_CON__IC_10BITADDR_MASTER_MASK 0x00000010L +#define CKSVII2C_IC_CON__IC_RESTART_EN_MASK 0x00000020L +#define CKSVII2C_IC_CON__IC_SLAVE_DISABLE_MASK 0x00000040L +#define CKSVII2C_IC_CON__STOP_DET_IFADDRESSED_MASK 0x00000080L +#define CKSVII2C_IC_CON__TX_EMPTY_CTRL_MASK 0x00000100L +#define CKSVII2C_IC_CON__RX_FIFO_FULL_HLD_CTRL_MASK 0x00000200L +//CKSVII2C_IC_TAR +#define CKSVII2C_IC_TAR__IC_TAR__SHIFT 0x0 +#define CKSVII2C_IC_TAR__GC_OR_START__SHIFT 0xa +#define CKSVII2C_IC_TAR__SPECIAL__SHIFT 0xb +#define CKSVII2C_IC_TAR__IC_10BITADDR_MASTER__SHIFT 0xc +#define CKSVII2C_IC_TAR__IC_TAR_MASK 0x000003FFL +#define CKSVII2C_IC_TAR__GC_OR_START_MASK 0x00000400L +#define CKSVII2C_IC_TAR__SPECIAL_MASK 0x00000800L +#define CKSVII2C_IC_TAR__IC_10BITADDR_MASTER_MASK 0x00001000L +//CKSVII2C_IC_SAR +#define CKSVII2C_IC_SAR__IC_SAR__SHIFT 0x0 +#define CKSVII2C_IC_SAR__IC_SAR_MASK 0x000003FFL +//CKSVII2C_IC_HS_MADDR +#define CKSVII2C_IC_HS_MADDR__IC_HS_MADDR__SHIFT 0x0 +#define CKSVII2C_IC_HS_MADDR__IC_HS_MADDR_MASK 0x00000007L +//CKSVII2C_IC_DATA_CMD +#define CKSVII2C_IC_DATA_CMD__DAT__SHIFT 0x0 +#define CKSVII2C_IC_DATA_CMD__CMD__SHIFT 0x8 +#define CKSVII2C_IC_DATA_CMD__STOP__SHIFT 0x9 +#define CKSVII2C_IC_DATA_CMD__RESTART__SHIFT 0xa +#define CKSVII2C_IC_DATA_CMD__FIRST_DATA_BYTE__SHIFT 0xb +#define CKSVII2C_IC_DATA_CMD__DAT_MASK 0x000000FFL +#define CKSVII2C_IC_DATA_CMD__CMD_MASK 0x00000100L +#define CKSVII2C_IC_DATA_CMD__STOP_MASK 0x00000200L +#define CKSVII2C_IC_DATA_CMD__RESTART_MASK 0x00000400L +//CKSVII2C_IC_SS_SCL_HCNT +#define CKSVII2C_IC_SS_SCL_HCNT__IC_SS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C_IC_SS_SCL_HCNT__IC_SS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_SS_SCL_LCNT +#define CKSVII2C_IC_SS_SCL_LCNT__IC_SS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C_IC_SS_SCL_LCNT__IC_SS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_FS_SCL_HCNT +#define CKSVII2C_IC_FS_SCL_HCNT__IC_FS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C_IC_FS_SCL_HCNT__IC_FS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_FS_SCL_LCNT +#define CKSVII2C_IC_FS_SCL_LCNT__IC_FS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C_IC_FS_SCL_LCNT__IC_FS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_HS_SCL_HCNT +#define CKSVII2C_IC_HS_SCL_HCNT__IC_HS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C_IC_HS_SCL_HCNT__IC_HS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_HS_SCL_LCNT +#define CKSVII2C_IC_HS_SCL_LCNT__IC_HS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C_IC_HS_SCL_LCNT__IC_HS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C_IC_INTR_STAT +#define CKSVII2C_IC_INTR_STAT__R_RX_UNDER__SHIFT 0x0 +#define CKSVII2C_IC_INTR_STAT__R_RX_OVER__SHIFT 0x1 +#define CKSVII2C_IC_INTR_STAT__R_RX_FULL__SHIFT 0x2 +#define CKSVII2C_IC_INTR_STAT__R_TX_OVER__SHIFT 0x3 +#define CKSVII2C_IC_INTR_STAT__R_TX_EMPTY__SHIFT 0x4 +#define CKSVII2C_IC_INTR_STAT__R_RD_REQ__SHIFT 0x5 +#define CKSVII2C_IC_INTR_STAT__R_TX_ABRT__SHIFT 0x6 +#define CKSVII2C_IC_INTR_STAT__R_RX_DONE__SHIFT 0x7 +#define CKSVII2C_IC_INTR_STAT__R_ACTIVITY__SHIFT 0x8 +#define CKSVII2C_IC_INTR_STAT__R_STOP_DET__SHIFT 0x9 +#define CKSVII2C_IC_INTR_STAT__R_START_DET__SHIFT 0xa +#define CKSVII2C_IC_INTR_STAT__R_GEN_CALL__SHIFT 0xb +#define CKSVII2C_IC_INTR_STAT__R_RESTART_DET__SHIFT 0xc +#define CKSVII2C_IC_INTR_STAT__R_MST_ON_HOLD__SHIFT 0xd +#define CKSVII2C_IC_INTR_STAT__R_SCL_STUCK_AT_LOW__SHIFT 0xe +#define CKSVII2C_IC_INTR_STAT__R_RX_UNDER_MASK 0x00000001L +#define CKSVII2C_IC_INTR_STAT__R_RX_OVER_MASK 0x00000002L +#define CKSVII2C_IC_INTR_STAT__R_RX_FULL_MASK 0x00000004L +#define CKSVII2C_IC_INTR_STAT__R_TX_OVER_MASK 0x00000008L +#define CKSVII2C_IC_INTR_STAT__R_TX_EMPTY_MASK 0x00000010L +#define CKSVII2C_IC_INTR_STAT__R_RD_REQ_MASK 0x00000020L +#define CKSVII2C_IC_INTR_STAT__R_TX_ABRT_MASK 0x00000040L +#define CKSVII2C_IC_INTR_STAT__R_RX_DONE_MASK 0x00000080L +#define CKSVII2C_IC_INTR_STAT__R_ACTIVITY_MASK 0x00000100L +#define CKSVII2C_IC_INTR_STAT__R_STOP_DET_MASK 0x00000200L +#define CKSVII2C_IC_INTR_STAT__R_START_DET_MASK 0x00000400L +#define CKSVII2C_IC_INTR_STAT__R_GEN_CALL_MASK 0x00000800L +#define CKSVII2C_IC_INTR_STAT__R_RESTART_DET_MASK 0x00001000L +#define CKSVII2C_IC_INTR_STAT__R_MST_ON_HOLD_MASK 0x00002000L +//CKSVII2C_IC_INTR_MASK +#define CKSVII2C_IC_INTR_MASK__M_RX_UNDER__SHIFT 0x0 +#define CKSVII2C_IC_INTR_MASK__M_RX_OVER__SHIFT 0x1 +#define CKSVII2C_IC_INTR_MASK__M_RX_FULL__SHIFT 0x2 +#define CKSVII2C_IC_INTR_MASK__M_TX_OVER__SHIFT 0x3 +#define CKSVII2C_IC_INTR_MASK__M_TX_EMPTY__SHIFT 0x4 +#define CKSVII2C_IC_INTR_MASK__M_RD_REQ__SHIFT 0x5 +#define CKSVII2C_IC_INTR_MASK__M_TX_ABRT__SHIFT 0x6 +#define CKSVII2C_IC_INTR_MASK__M_RX_DONE__SHIFT 0x7 +#define CKSVII2C_IC_INTR_MASK__M_ACTIVITY__SHIFT 0x8 +#define CKSVII2C_IC_INTR_MASK__M_STOP_DET__SHIFT 0x9 +#define CKSVII2C_IC_INTR_MASK__M_START_DET__SHIFT 0xa +#define CKSVII2C_IC_INTR_MASK__M_GEN_CALL__SHIFT 0xb +#define CKSVII2C_IC_INTR_MASK__M_RESTART_DET__SHIFT 0xc +#define CKSVII2C_IC_INTR_MASK__M_MST_ON_HOLD__SHIFT 0xd +#define CKSVII2C_IC_INTR_MASK__M_SCL_STUCK_AT_LOW__SHIFT 0xe +#define CKSVII2C_IC_INTR_MASK__M_RX_UNDER_MASK 0x00000001L +#define CKSVII2C_IC_INTR_MASK__M_RX_OVER_MASK 0x00000002L +#define CKSVII2C_IC_INTR_MASK__M_RX_FULL_MASK 0x00000004L +#define CKSVII2C_IC_INTR_MASK__M_TX_OVER_MASK 0x00000008L +#define CKSVII2C_IC_INTR_MASK__M_TX_EMPTY_MASK 0x00000010L +#define CKSVII2C_IC_INTR_MASK__M_RD_REQ_MASK 0x00000020L +#define CKSVII2C_IC_INTR_MASK__M_TX_ABRT_MASK 0x00000040L +#define CKSVII2C_IC_INTR_MASK__M_RX_DONE_MASK 0x00000080L +#define CKSVII2C_IC_INTR_MASK__M_ACTIVITY_MASK 0x00000100L +#define CKSVII2C_IC_INTR_MASK__M_STOP_DET_MASK 0x00000200L +#define CKSVII2C_IC_INTR_MASK__M_START_DET_MASK 0x00000400L +#define CKSVII2C_IC_INTR_MASK__M_GEN_CALL_MASK 0x00000800L +#define CKSVII2C_IC_INTR_MASK__M_RESTART_DET_MASK 0x00001000L +#define CKSVII2C_IC_INTR_MASK__M_MST_ON_HOLD_MASK 0x00002000L +//CKSVII2C_IC_RAW_INTR_STAT +//CKSVII2C_IC_RX_TL +#define CKSVII2C_IC_RX_TL__RX_TL__SHIFT 0x0 +//CKSVII2C_IC_TX_TL +#define CKSVII2C_IC_TX_TL__TX_TL__SHIFT 0x0 +//CKSVII2C_IC_CLR_INTR +//CKSVII2C_IC_CLR_RX_UNDER +//CKSVII2C_IC_CLR_RX_OVER +//CKSVII2C_IC_CLR_TX_OVER +//CKSVII2C_IC_CLR_RD_REQ +//CKSVII2C_IC_CLR_TX_ABRT +//CKSVII2C_IC_CLR_RX_DONE +//CKSVII2C_IC_CLR_ACTIVITY +//CKSVII2C_IC_CLR_STOP_DET +//CKSVII2C_IC_CLR_START_DET +//CKSVII2C_IC_CLR_GEN_CALL +//CKSVII2C_IC_ENABLE +#define CKSVII2C_IC_ENABLE__ENABLE__SHIFT 0x0 +#define CKSVII2C_IC_ENABLE__ABORT__SHIFT 0x1 +#define CKSVII2C_IC_ENABLE__TX_CMD_BLOCK__SHIFT 0x2 +#define CKSVII2C_IC_ENABLE__SDA_STUCK_RECOVERY_ENABLE__SHIFT 0x3 +#define CKSVII2C_IC_ENABLE__ENABLE_MASK 0x00000001L +#define CKSVII2C_IC_ENABLE__ABORT_MASK 0x00000002L +//CKSVII2C_IC_STATUS +#define CKSVII2C_IC_STATUS__ACTIVITY__SHIFT 0x0 +#define CKSVII2C_IC_STATUS__TFNF__SHIFT 0x1 +#define CKSVII2C_IC_STATUS__TFE__SHIFT 0x2 +#define CKSVII2C_IC_STATUS__RFNE__SHIFT 0x3 +#define CKSVII2C_IC_STATUS__RFF__SHIFT 0x4 +#define CKSVII2C_IC_STATUS__MST_ACTIVITY__SHIFT 0x5 +#define CKSVII2C_IC_STATUS__SLV_ACTIVITY__SHIFT 0x6 +#define CKSVII2C_IC_STATUS__MST_HOLD_TX_FIFO_EMPTY__SHIFT 0x7 +#define CKSVII2C_IC_STATUS__MST_HOLD_RX_FIFO_FULL__SHIFT 0x8 +#define CKSVII2C_IC_STATUS__SLV_HOLD_TX_FIFO_EMPTY__SHIFT 0x9 +#define CKSVII2C_IC_STATUS__SLV_HOLD_RX_FIFO_FULL__SHIFT 0xa +#define CKSVII2C_IC_STATUS__SDA_STUCK_NOT_RECOVERED__SHIFT 0xb +#define CKSVII2C_IC_STATUS__ACTIVITY_MASK 0x00000001L +#define CKSVII2C_IC_STATUS__TFNF_MASK 0x00000002L +#define CKSVII2C_IC_STATUS__TFE_MASK 0x00000004L +#define CKSVII2C_IC_STATUS__RFNE_MASK 0x00000008L +#define CKSVII2C_IC_STATUS__RFF_MASK 0x00000010L +#define CKSVII2C_IC_STATUS__MST_ACTIVITY_MASK 0x00000020L +#define CKSVII2C_IC_STATUS__SLV_ACTIVITY_MASK 0x00000040L +//CKSVII2C_IC_TXFLR +#define CKSVII2C_IC_TXFLR__TXFLR__SHIFT 0x0 +//CKSVII2C_IC_RXFLR +#define CKSVII2C_IC_RXFLR__RXFLR__SHIFT 0x0 +//CKSVII2C_IC_SDA_HOLD +#define CKSVII2C_IC_SDA_HOLD__IC_SDA_TX_HOLD__SHIFT 0x0 +#define CKSVII2C_IC_SDA_HOLD__IC_SDA_RX_HOLD__SHIFT 0x10 +//CKSVII2C_IC_TX_ABRT_SOURCE +//CKSVII2C_IC_SLV_DATA_NACK_ONLY +//CKSVII2C_IC_DMA_CR +//CKSVII2C_IC_DMA_TDLR +//CKSVII2C_IC_DMA_RDLR +//CKSVII2C_IC_SDA_SETUP +#define CKSVII2C_IC_SDA_SETUP__SDA_SETUP__SHIFT 0x0 +#define CKSVII2C_IC_SDA_SETUP__SDA_SETUP_MASK 0x000000FFL +//CKSVII2C_IC_ACK_GENERAL_CALL +#define CKSVII2C_IC_ACK_GENERAL_CALL__ACK_GENERAL_CALL__SHIFT 0x0 +#define CKSVII2C_IC_ACK_GENERAL_CALL__ACK_GENERAL_CALL_MASK 0x00000001L +//CKSVII2C_IC_ENABLE_STATUS +#define CKSVII2C_IC_ENABLE_STATUS__IC_EN__SHIFT 0x0 +#define CKSVII2C_IC_ENABLE_STATUS__SLV_DISABLED_WHILE_BUSY__SHIFT 0x1 +#define CKSVII2C_IC_ENABLE_STATUS__SLV_RX_DATA_LOST__SHIFT 0x2 +#define CKSVII2C_IC_ENABLE_STATUS__IC_EN_MASK 0x00000001L +//CKSVII2C_IC_FS_SPKLEN +#define CKSVII2C_IC_FS_SPKLEN__FS_SPKLEN__SHIFT 0x0 +#define CKSVII2C_IC_FS_SPKLEN__FS_SPKLEN_MASK 0x000000FFL +//CKSVII2C_IC_HS_SPKLEN +#define CKSVII2C_IC_HS_SPKLEN__HS_SPKLEN__SHIFT 0x0 +#define CKSVII2C_IC_HS_SPKLEN__HS_SPKLEN_MASK 0x000000FFL +//CKSVII2C_IC_CLR_RESTART_DET +//CKSVII2C_IC_COMP_PARAM_1 +#define CKSVII2C_IC_COMP_PARAM_1__APB_DATA_WIDTH__SHIFT 0x0 +#define CKSVII2C_IC_COMP_PARAM_1__MAX_SPEED_MODE__SHIFT 0x2 +#define CKSVII2C_IC_COMP_PARAM_1__HC_COUNT_VALUES__SHIFT 0x4 +#define CKSVII2C_IC_COMP_PARAM_1__INTR_IO__SHIFT 0x5 +#define CKSVII2C_IC_COMP_PARAM_1__HAS_DMA__SHIFT 0x6 +#define CKSVII2C_IC_COMP_PARAM_1__ADD_ENCODED_PARAMS__SHIFT 0x7 +#define CKSVII2C_IC_COMP_PARAM_1__RX_BUFFER_DEPTH__SHIFT 0x8 +#define CKSVII2C_IC_COMP_PARAM_1__TX_BUFFER_DEPTH__SHIFT 0x10 +//CKSVII2C_IC_COMP_VERSION +#define CKSVII2C_IC_COMP_VERSION__COMP_VERSION__SHIFT 0x0 +#define CKSVII2C_IC_COMP_VERSION__COMP_VERSION_MASK 0xFFFFFFFFL +//CKSVII2C_IC_COMP_TYPE +#define CKSVII2C_IC_COMP_TYPE__COMP_TYPE__SHIFT 0x0 +#define CKSVII2C_IC_COMP_TYPE__COMP_TYPE_MASK 0xFFFFFFFFL +//CKSVII2C1_IC_CON +#define CKSVII2C1_IC_CON__IC1_MASTER_MODE__SHIFT 0x0 +#define CKSVII2C1_IC_CON__IC1_MAX_SPEED_MODE__SHIFT 0x1 +#define CKSVII2C1_IC_CON__IC1_10BITADDR_SLAVE__SHIFT 0x3 +#define CKSVII2C1_IC_CON__IC1_10BITADDR_MASTER__SHIFT 0x4 +#define CKSVII2C1_IC_CON__IC1_RESTART_EN__SHIFT 0x5 +#define CKSVII2C1_IC_CON__IC1_SLAVE_DISABLE__SHIFT 0x6 +#define CKSVII2C1_IC_CON__STOP1_DET_IFADDRESSED__SHIFT 0x7 +#define CKSVII2C1_IC_CON__TX1_EMPTY_CTRL__SHIFT 0x8 +#define CKSVII2C1_IC_CON__RX1_FIFO_FULL_HLD_CTRL__SHIFT 0x9 +#define CKSVII2C1_IC_CON__BUS_CLEAR_FEATURE_CTRL1__SHIFT 0xb +#define CKSVII2C1_IC_CON__IC1_MASTER_MODE_MASK 0x00000001L +#define CKSVII2C1_IC_CON__IC1_MAX_SPEED_MODE_MASK 0x00000006L +#define CKSVII2C1_IC_CON__IC1_10BITADDR_SLAVE_MASK 0x00000008L +#define CKSVII2C1_IC_CON__IC1_10BITADDR_MASTER_MASK 0x00000010L +#define CKSVII2C1_IC_CON__IC1_RESTART_EN_MASK 0x00000020L +#define CKSVII2C1_IC_CON__IC1_SLAVE_DISABLE_MASK 0x00000040L +#define CKSVII2C1_IC_CON__STOP1_DET_IFADDRESSED_MASK 0x00000080L +#define CKSVII2C1_IC_CON__TX1_EMPTY_CTRL_MASK 0x00000100L +#define CKSVII2C1_IC_CON__RX1_FIFO_FULL_HLD_CTRL_MASK 0x00000200L +//CKSVII2C1_IC_TAR +#define CKSVII2C1_IC_TAR__IC1_TAR__SHIFT 0x0 +#define CKSVII2C1_IC_TAR__GC1_OR_START__SHIFT 0xa +#define CKSVII2C1_IC_TAR__SPECIAL1__SHIFT 0xb +#define CKSVII2C1_IC_TAR__IC1_10BITADDR_MASTER__SHIFT 0xc +#define CKSVII2C1_IC_TAR__IC1_TAR_MASK 0x000003FFL +#define CKSVII2C1_IC_TAR__GC1_OR_START_MASK 0x00000400L +#define CKSVII2C1_IC_TAR__SPECIAL1_MASK 0x00000800L +#define CKSVII2C1_IC_TAR__IC1_10BITADDR_MASTER_MASK 0x00001000L +//CKSVII2C1_IC_SAR +#define CKSVII2C1_IC_SAR__IC1_SAR__SHIFT 0x0 +#define CKSVII2C1_IC_SAR__IC1_SAR_MASK 0x000003FFL +//CKSVII2C1_IC_HS_MADDR +#define CKSVII2C1_IC_HS_MADDR__IC1_HS_MADDR__SHIFT 0x0 +#define CKSVII2C1_IC_HS_MADDR__IC1_HS_MADDR_MASK 0x00000007L +//CKSVII2C1_IC_DATA_CMD +#define CKSVII2C1_IC_DATA_CMD__DAT1__SHIFT 0x0 +#define CKSVII2C1_IC_DATA_CMD__CMD1__SHIFT 0x8 +#define CKSVII2C1_IC_DATA_CMD__STOP1__SHIFT 0x9 +#define CKSVII2C1_IC_DATA_CMD__RESTART1__SHIFT 0xa +#define CKSVII2C1_IC_DATA_CMD__FIRST1_DATA_BYTE__SHIFT 0xb +#define CKSVII2C1_IC_DATA_CMD__DAT1_MASK 0x000000FFL +#define CKSVII2C1_IC_DATA_CMD__CMD1_MASK 0x00000100L +#define CKSVII2C1_IC_DATA_CMD__STOP1_MASK 0x00000200L +#define CKSVII2C1_IC_DATA_CMD__RESTART1_MASK 0x00000400L +//CKSVII2C1_IC_SS_SCL_HCNT +#define CKSVII2C1_IC_SS_SCL_HCNT__IC1_SS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C1_IC_SS_SCL_HCNT__IC1_SS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_SS_SCL_LCNT +#define CKSVII2C1_IC_SS_SCL_LCNT__IC1_SS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C1_IC_SS_SCL_LCNT__IC1_SS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_FS_SCL_HCNT +#define CKSVII2C1_IC_FS_SCL_HCNT__IC1_FS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C1_IC_FS_SCL_HCNT__IC1_FS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_FS_SCL_LCNT +#define CKSVII2C1_IC_FS_SCL_LCNT__IC1_FS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C1_IC_FS_SCL_LCNT__IC1_FS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_HS_SCL_HCNT +#define CKSVII2C1_IC_HS_SCL_HCNT__IC1_HS_SCL_HCNT__SHIFT 0x0 +#define CKSVII2C1_IC_HS_SCL_HCNT__IC1_HS_SCL_HCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_HS_SCL_LCNT +#define CKSVII2C1_IC_HS_SCL_LCNT__IC1_HS_SCL_LCNT__SHIFT 0x0 +#define CKSVII2C1_IC_HS_SCL_LCNT__IC1_HS_SCL_LCNT_MASK 0x0000FFFFL +//CKSVII2C1_IC_INTR_STAT +#define CKSVII2C1_IC_INTR_STAT__R1_RX_UNDER__SHIFT 0x0 +#define CKSVII2C1_IC_INTR_STAT__R1_RX_OVER__SHIFT 0x1 +#define CKSVII2C1_IC_INTR_STAT__R1_RX_FULL__SHIFT 0x2 +#define CKSVII2C1_IC_INTR_STAT__R1_TX_OVER__SHIFT 0x3 +#define CKSVII2C1_IC_INTR_STAT__R1_TX_EMPTY__SHIFT 0x4 +#define CKSVII2C1_IC_INTR_STAT__R1_RD_REQ__SHIFT 0x5 +#define CKSVII2C1_IC_INTR_STAT__R1_TX_ABRT__SHIFT 0x6 +#define CKSVII2C1_IC_INTR_STAT__R1_RX_DONE__SHIFT 0x7 +#define CKSVII2C1_IC_INTR_STAT__R1_ACTIVITY__SHIFT 0x8 +#define CKSVII2C1_IC_INTR_STAT__R1_STOP_DET__SHIFT 0x9 +#define CKSVII2C1_IC_INTR_STAT__R1_START_DET__SHIFT 0xa +#define CKSVII2C1_IC_INTR_STAT__R1_GEN_CALL__SHIFT 0xb +#define CKSVII2C1_IC_INTR_STAT__R1_RESTART_DET__SHIFT 0xc +#define CKSVII2C1_IC_INTR_STAT__R1_MST_ON_HOLD__SHIFT 0xd +#define CKSVII2C1_IC_INTR_STAT__R1_SCL_STUCK_AT_LOW__SHIFT 0xe +#define CKSVII2C1_IC_INTR_STAT__R1_RX_UNDER_MASK 0x00000001L +#define CKSVII2C1_IC_INTR_STAT__R1_RX_OVER_MASK 0x00000002L +#define CKSVII2C1_IC_INTR_STAT__R1_RX_FULL_MASK 0x00000004L +#define CKSVII2C1_IC_INTR_STAT__R1_TX_OVER_MASK 0x00000008L +#define CKSVII2C1_IC_INTR_STAT__R1_TX_EMPTY_MASK 0x00000010L +#define CKSVII2C1_IC_INTR_STAT__R1_RD_REQ_MASK 0x00000020L +#define CKSVII2C1_IC_INTR_STAT__R1_TX_ABRT_MASK 0x00000040L +#define CKSVII2C1_IC_INTR_STAT__R1_RX_DONE_MASK 0x00000080L +#define CKSVII2C1_IC_INTR_STAT__R1_ACTIVITY_MASK 0x00000100L +#define CKSVII2C1_IC_INTR_STAT__R1_STOP_DET_MASK 0x00000200L +#define CKSVII2C1_IC_INTR_STAT__R1_START_DET_MASK 0x00000400L +#define CKSVII2C1_IC_INTR_STAT__R1_GEN_CALL_MASK 0x00000800L +#define CKSVII2C1_IC_INTR_STAT__R1_RESTART_DET_MASK 0x00001000L +#define CKSVII2C1_IC_INTR_STAT__R1_MST_ON_HOLD_MASK 0x00002000L +//CKSVII2C1_IC_INTR_MASK +#define CKSVII2C1_IC_INTR_MASK__M1_RX_UNDER__SHIFT 0x0 +#define CKSVII2C1_IC_INTR_MASK__M1_RX_OVER__SHIFT 0x1 +#define CKSVII2C1_IC_INTR_MASK__M1_RX_FULL__SHIFT 0x2 +#define CKSVII2C1_IC_INTR_MASK__M1_TX_OVER__SHIFT 0x3 +#define CKSVII2C1_IC_INTR_MASK__M1_TX_EMPTY__SHIFT 0x4 +#define CKSVII2C1_IC_INTR_MASK__M1_RD_REQ__SHIFT 0x5 +#define CKSVII2C1_IC_INTR_MASK__M1_TX_ABRT__SHIFT 0x6 +#define CKSVII2C1_IC_INTR_MASK__M1_RX_DONE__SHIFT 0x7 +#define CKSVII2C1_IC_INTR_MASK__M1_ACTIVITY__SHIFT 0x8 +#define CKSVII2C1_IC_INTR_MASK__M1_STOP_DET__SHIFT 0x9 +#define CKSVII2C1_IC_INTR_MASK__M1_START_DET__SHIFT 0xa +#define CKSVII2C1_IC_INTR_MASK__M1_GEN_CALL__SHIFT 0xb +#define CKSVII2C1_IC_INTR_MASK__M1_RESTART_DET__SHIFT 0xc +#define CKSVII2C1_IC_INTR_MASK__M1_MST_ON_HOLD__SHIFT 0xd +#define CKSVII2C1_IC_INTR_MASK__M1_SCL_STUCK_AT_LOW__SHIFT 0xe +#define CKSVII2C1_IC_INTR_MASK__M1_RX_UNDER_MASK 0x00000001L +#define CKSVII2C1_IC_INTR_MASK__M1_RX_OVER_MASK 0x00000002L +#define CKSVII2C1_IC_INTR_MASK__M1_RX_FULL_MASK 0x00000004L +#define CKSVII2C1_IC_INTR_MASK__M1_TX_OVER_MASK 0x00000008L +#define CKSVII2C1_IC_INTR_MASK__M1_TX_EMPTY_MASK 0x00000010L +#define CKSVII2C1_IC_INTR_MASK__M1_RD_REQ_MASK 0x00000020L +#define CKSVII2C1_IC_INTR_MASK__M1_TX_ABRT_MASK 0x00000040L +#define CKSVII2C1_IC_INTR_MASK__M1_RX_DONE_MASK 0x00000080L +#define CKSVII2C1_IC_INTR_MASK__M1_ACTIVITY_MASK 0x00000100L +#define CKSVII2C1_IC_INTR_MASK__M1_STOP_DET_MASK 0x00000200L +#define CKSVII2C1_IC_INTR_MASK__M1_START_DET_MASK 0x00000400L +#define CKSVII2C1_IC_INTR_MASK__M1_GEN_CALL_MASK 0x00000800L +#define CKSVII2C1_IC_INTR_MASK__M1_RESTART_DET_MASK 0x00001000L +#define CKSVII2C1_IC_INTR_MASK__M1_MST_ON_HOLD_MASK 0x00002000L +//CKSVII2C1_IC_RAW_INTR_STAT +//CKSVII2C1_IC_RX_TL +#define CKSVII2C1_IC_RX_TL__RX1_TL__SHIFT 0x0 +//CKSVII2C1_IC_TX_TL +#define CKSVII2C1_IC_TX_TL__TX1_TL__SHIFT 0x0 +//CKSVII2C1_IC_CLR_INTR +//CKSVII2C1_IC_CLR_RX_UNDER +//CKSVII2C1_IC_CLR_RX_OVER +//CKSVII2C1_IC_CLR_TX_OVER +//CKSVII2C1_IC_CLR_RD_REQ +//CKSVII2C1_IC_CLR_TX_ABRT +//CKSVII2C1_IC_CLR_RX_DONE +//CKSVII2C1_IC_CLR_ACTIVITY +//CKSVII2C1_IC_CLR_STOP_DET +//CKSVII2C1_IC_CLR_START_DET +//CKSVII2C1_IC_CLR_GEN_CALL +//CKSVII2C1_IC_ENABLE +#define CKSVII2C1_IC_ENABLE__ENABLE1__SHIFT 0x0 +#define CKSVII2C1_IC_ENABLE__ABORT1__SHIFT 0x1 +#define CKSVII2C1_IC_ENABLE__TX1_CMD_BLOCK__SHIFT 0x2 +#define CKSVII2C1_IC_ENABLE__SDA1_STUCK_RECOVERY_ENABLE__SHIFT 0x3 +#define CKSVII2C1_IC_ENABLE__ENABLE1_MASK 0x00000001L +#define CKSVII2C1_IC_ENABLE__ABORT1_MASK 0x00000002L +//CKSVII2C1_IC_STATUS +#define CKSVII2C1_IC_STATUS__ACTIVITY1__SHIFT 0x0 +#define CKSVII2C1_IC_STATUS__TFNF1__SHIFT 0x1 +#define CKSVII2C1_IC_STATUS__TFE1__SHIFT 0x2 +#define CKSVII2C1_IC_STATUS__RFNE1__SHIFT 0x3 +#define CKSVII2C1_IC_STATUS__RFF1__SHIFT 0x4 +#define CKSVII2C1_IC_STATUS__MST1_ACTIVITY__SHIFT 0x5 +#define CKSVII2C1_IC_STATUS__SLV1_ACTIVITY__SHIFT 0x6 +#define CKSVII2C1_IC_STATUS__MST1_HOLD_TX_FIFO_EMPTY__SHIFT 0x7 +#define CKSVII2C1_IC_STATUS__MST1_HOLD_RX_FIFO_FULL__SHIFT 0x8 +#define CKSVII2C1_IC_STATUS__SLV1_HOLD_TX_FIFO_EMPTY__SHIFT 0x9 +#define CKSVII2C1_IC_STATUS__SLV1_HOLD_RX_FIFO_FULL__SHIFT 0xa +#define CKSVII2C1_IC_STATUS__SDA1_STUCK_NOT_RECOVERED__SHIFT 0xb +#define CKSVII2C1_IC_STATUS__ACTIVITY1_MASK 0x00000001L +#define CKSVII2C1_IC_STATUS__TFNF1_MASK 0x00000002L +#define CKSVII2C1_IC_STATUS__TFE1_MASK 0x00000004L +#define CKSVII2C1_IC_STATUS__RFNE1_MASK 0x00000008L +#define CKSVII2C1_IC_STATUS__RFF1_MASK 0x00000010L +#define CKSVII2C1_IC_STATUS__MST1_ACTIVITY_MASK 0x00000020L +#define CKSVII2C1_IC_STATUS__SLV1_ACTIVITY_MASK 0x00000040L +//CKSVII2C1_IC_TXFLR +#define CKSVII2C1_IC_TXFLR__TXFLR1__SHIFT 0x0 +//CKSVII2C1_IC_RXFLR +#define CKSVII2C1_IC_RXFLR__RXFLR1__SHIFT 0x0 +//CKSVII2C1_IC_SDA_HOLD +#define CKSVII2C1_IC_SDA_HOLD__IC1_SDA_TX_HOLD__SHIFT 0x0 +#define CKSVII2C1_IC_SDA_HOLD__IC1_SDA_RX_HOLD__SHIFT 0x10 +//CKSVII2C1_IC_TX_ABRT_SOURCE +//CKSVII2C1_IC_SLV_DATA_NACK_ONLY +//CKSVII2C1_IC_DMA_CR +//CKSVII2C1_IC_DMA_TDLR +//CKSVII2C1_IC_DMA_RDLR +//CKSVII2C1_IC_SDA_SETUP +#define CKSVII2C1_IC_SDA_SETUP__SDA1_SETUP__SHIFT 0x0 +#define CKSVII2C1_IC_SDA_SETUP__SDA1_SETUP_MASK 0x000000FFL +//CKSVII2C1_IC_ACK_GENERAL_CALL +#define CKSVII2C1_IC_ACK_GENERAL_CALL__ACK1_GENERAL_CALL__SHIFT 0x0 +#define CKSVII2C1_IC_ACK_GENERAL_CALL__ACK1_GENERAL_CALL_MASK 0x00000001L +//CKSVII2C1_IC_ENABLE_STATUS +#define CKSVII2C1_IC_ENABLE_STATUS__IC1_EN__SHIFT 0x0 +#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_DISABLED_WHILE_BUSY__SHIFT 0x1 +#define CKSVII2C1_IC_ENABLE_STATUS__SLV1_RX_DATA_LOST__SHIFT 0x2 +#define CKSVII2C1_IC_ENABLE_STATUS__IC1_EN_MASK 0x00000001L +//CKSVII2C1_IC_FS_SPKLEN +#define CKSVII2C1_IC_FS_SPKLEN__FS1_SPKLEN__SHIFT 0x0 +//CKSVII2C1_IC_HS_SPKLEN +#define CKSVII2C1_IC_HS_SPKLEN__HS1_SPKLEN__SHIFT 0x0 +//CKSVII2C1_IC_CLR_RESTART_DET +//CKSVII2C1_IC_COMP_PARAM_1 +#define CKSVII2C1_IC_COMP_PARAM_1__APB1_DATA_WIDTH__SHIFT 0x0 +#define CKSVII2C1_IC_COMP_PARAM_1__MAX1_SPEED_MODE__SHIFT 0x2 +#define CKSVII2C1_IC_COMP_PARAM_1__HC1_COUNT_VALUES__SHIFT 0x4 +#define CKSVII2C1_IC_COMP_PARAM_1__INTR1_IO__SHIFT 0x5 +#define CKSVII2C1_IC_COMP_PARAM_1__HAS1_DMA__SHIFT 0x6 +#define CKSVII2C1_IC_COMP_PARAM_1__ADD1_ENCODED_PARAMS__SHIFT 0x7 +#define CKSVII2C1_IC_COMP_PARAM_1__RX1_BUFFER_DEPTH__SHIFT 0x8 +#define CKSVII2C1_IC_COMP_PARAM_1__TX1_BUFFER_DEPTH__SHIFT 0x10 +//CKSVII2C1_IC_COMP_VERSION +#define CKSVII2C1_IC_COMP_VERSION__COMP1_VERSION__SHIFT 0x0 +//CKSVII2C1_IC_COMP_TYPE +#define CKSVII2C1_IC_COMP_TYPE__COMP1_TYPE__SHIFT 0x0 +//SMUIO_PWRMGT +#define SMUIO_PWRMGT__i2c_clk_gate_en__SHIFT 0x0 +#define SMUIO_PWRMGT__i2c1_clk_gate_en__SHIFT 0x4 +#define SMUIO_PWRMGT__i2c_clk_gate_en_MASK 0x00000001L +#define SMUIO_PWRMGT__i2c1_clk_gate_en_MASK 0x00000010L + + +// addressBlock: smuio_smuio_rom_SmuSmuioDec +//ROM_CNTL +#define ROM_CNTL__CLOCK_GATING_EN__SHIFT 0x0 +#define ROM_CNTL__READ_MODE__SHIFT 0x1 +#define ROM_CNTL__READ_MODE_OVERRIDE__SHIFT 0x3 +#define ROM_CNTL__SPI_TIMING_RELAX_SCK__SHIFT 0x4 +#define ROM_CNTL__SPI_TIMING_RELAX_SCK_OVERRIDE__SHIFT 0x5 +#define ROM_CNTL__FOUR_BYTE_ADDRESS_MODE__SHIFT 0x6 +#define ROM_CNTL__DUMMY_CYCLE_NUM__SHIFT 0x8 +#define ROM_CNTL__SPI_TIMING_RELAX__SHIFT 0x13 +#define ROM_CNTL__SPI_TIMING_RELAX_OVERRIDE__SHIFT 0x14 +#define ROM_CNTL__SPI_FAST_MODE__SHIFT 0x15 +#define ROM_CNTL__SPI_FAST_MODE_OVERRIDE__SHIFT 0x16 +#define ROM_CNTL__SCK_PRESCALE_REFCLK__SHIFT 0x17 +#define ROM_CNTL__SCK_PRESCALE_REFCLK_OVERRIDE__SHIFT 0x1c +#define ROM_CNTL__ROM_INDEX_ADDRESS_AUTO_INCREASE__SHIFT 0x1d +#define ROM_CNTL__PAD_SAMPLE_MODE__SHIFT 0x1e +#define ROM_CNTL__PAD_SAMPLE_MODE_OVERRIDE__SHIFT 0x1f +#define ROM_CNTL__CLOCK_GATING_EN_MASK 0x00000001L +#define ROM_CNTL__SPI_TIMING_RELAX_MASK 0x00080000L +#define ROM_CNTL__SPI_TIMING_RELAX_OVERRIDE_MASK 0x00100000L +#define ROM_CNTL__SPI_FAST_MODE_MASK 0x00200000L +#define ROM_CNTL__SPI_FAST_MODE_OVERRIDE_MASK 0x00400000L +#define ROM_CNTL__SCK_PRESCALE_REFCLK_MASK 0x0F800000L +#define ROM_CNTL__SCK_PRESCALE_REFCLK_OVERRIDE_MASK 0x10000000L +//PAGE_MIRROR_CNTL +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_BASE_ADDR__SHIFT 0x0 +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_ENABLE__SHIFT 0x19 +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_USAGE__SHIFT 0x1a +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_INVALIDATE__SHIFT 0x1c +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_BASE_ADDR_MASK 0x01FFFFFFL +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_ENABLE_MASK 0x02000000L +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_USAGE_MASK 0x0C000000L +#define PAGE_MIRROR_CNTL__PAGE_MIRROR_INVALIDATE_MASK 0x10000000L +//ROM_STATUS +#define ROM_STATUS__ROM_BUSY__SHIFT 0x0 +#define ROM_STATUS__ROM_BUSY_MASK 0x00000001L +//CGTT_ROM_CLK_CTRL0 +#define CGTT_ROM_CLK_CTRL0__ON_DELAY__SHIFT 0x0 +#define CGTT_ROM_CLK_CTRL0__OFF_HYSTERESIS__SHIFT 0x4 +#define CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1__SHIFT 0x1e +#define CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0__SHIFT 0x1f +#define CGTT_ROM_CLK_CTRL0__ON_DELAY_MASK 0x0000000FL +#define CGTT_ROM_CLK_CTRL0__OFF_HYSTERESIS_MASK 0x00000FF0L +#define CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK 0x40000000L +#define CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK 0x80000000L +//ROM_INDEX +#define ROM_INDEX__ROM_INDEX__SHIFT 0x0 +#define ROM_INDEX__ROM_INDEX_MASK 0x01FFFFFFL +//ROM_DATA +#define ROM_DATA__ROM_DATA__SHIFT 0x0 +#define ROM_DATA__ROM_DATA_MASK 0xFFFFFFFFL +//ROM_START +#define ROM_START__ROM_START__SHIFT 0x0 +#define ROM_START__ROM_START_MASK 0x01FFFFFFL +//ROM_SW_CNTL +#define ROM_SW_CNTL__DATA_SIZE__SHIFT 0x0 +#define ROM_SW_CNTL__COMMAND_SIZE__SHIFT 0x10 +#define ROM_SW_CNTL__ROM_SW_RETURN_DATA_ENABLE__SHIFT 0x13 +#define ROM_SW_CNTL__DATA_SIZE_MASK 0x0000FFFFL +#define ROM_SW_CNTL__COMMAND_SIZE_MASK 0x00070000L +#define ROM_SW_CNTL__ROM_SW_RETURN_DATA_ENABLE_MASK 0x00080000L +//ROM_SW_STATUS +#define ROM_SW_STATUS__ROM_SW_DONE__SHIFT 0x0 +#define ROM_SW_STATUS__ROM_SW_DONE_MASK 0x00000001L +//ROM_SW_COMMAND +#define ROM_SW_COMMAND__ROM_SW_INSTRUCTION__SHIFT 0x0 +#define ROM_SW_COMMAND__ROM_SW_ADDRESS__SHIFT 0x8 +#define ROM_SW_COMMAND__ROM_SW_INSTRUCTION_MASK 0x000000FFL +#define ROM_SW_COMMAND__ROM_SW_ADDRESS_MASK 0xFFFFFF00L +//ROM_SW_DATA_1 +#define ROM_SW_DATA_1__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_1__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_2 +#define ROM_SW_DATA_2__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_2__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_3 +#define ROM_SW_DATA_3__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_3__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_4 +#define ROM_SW_DATA_4__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_4__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_5 +#define ROM_SW_DATA_5__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_5__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_6 +#define ROM_SW_DATA_6__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_6__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_7 +#define ROM_SW_DATA_7__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_7__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_8 +#define ROM_SW_DATA_8__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_8__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_9 +#define ROM_SW_DATA_9__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_9__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_10 +#define ROM_SW_DATA_10__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_10__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_11 +#define ROM_SW_DATA_11__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_11__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_12 +#define ROM_SW_DATA_12__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_12__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_13 +#define ROM_SW_DATA_13__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_13__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_14 +#define ROM_SW_DATA_14__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_14__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_15 +#define ROM_SW_DATA_15__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_15__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_16 +#define ROM_SW_DATA_16__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_16__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_17 +#define ROM_SW_DATA_17__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_17__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_18 +#define ROM_SW_DATA_18__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_18__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_19 +#define ROM_SW_DATA_19__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_19__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_20 +#define ROM_SW_DATA_20__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_20__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_21 +#define ROM_SW_DATA_21__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_21__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_22 +#define ROM_SW_DATA_22__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_22__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_23 +#define ROM_SW_DATA_23__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_23__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_24 +#define ROM_SW_DATA_24__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_24__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_25 +#define ROM_SW_DATA_25__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_25__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_26 +#define ROM_SW_DATA_26__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_26__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_27 +#define ROM_SW_DATA_27__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_27__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_28 +#define ROM_SW_DATA_28__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_28__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_29 +#define ROM_SW_DATA_29__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_29__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_30 +#define ROM_SW_DATA_30__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_30__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_31 +#define ROM_SW_DATA_31__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_31__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_32 +#define ROM_SW_DATA_32__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_32__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_33 +#define ROM_SW_DATA_33__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_33__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_34 +#define ROM_SW_DATA_34__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_34__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_35 +#define ROM_SW_DATA_35__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_35__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_36 +#define ROM_SW_DATA_36__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_36__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_37 +#define ROM_SW_DATA_37__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_37__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_38 +#define ROM_SW_DATA_38__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_38__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_39 +#define ROM_SW_DATA_39__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_39__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_40 +#define ROM_SW_DATA_40__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_40__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_41 +#define ROM_SW_DATA_41__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_41__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_42 +#define ROM_SW_DATA_42__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_42__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_43 +#define ROM_SW_DATA_43__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_43__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_44 +#define ROM_SW_DATA_44__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_44__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_45 +#define ROM_SW_DATA_45__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_45__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_46 +#define ROM_SW_DATA_46__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_46__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_47 +#define ROM_SW_DATA_47__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_47__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_48 +#define ROM_SW_DATA_48__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_48__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_49 +#define ROM_SW_DATA_49__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_49__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_50 +#define ROM_SW_DATA_50__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_50__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_51 +#define ROM_SW_DATA_51__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_51__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_52 +#define ROM_SW_DATA_52__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_52__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_53 +#define ROM_SW_DATA_53__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_53__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_54 +#define ROM_SW_DATA_54__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_54__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_55 +#define ROM_SW_DATA_55__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_55__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_56 +#define ROM_SW_DATA_56__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_56__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_57 +#define ROM_SW_DATA_57__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_57__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_58 +#define ROM_SW_DATA_58__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_58__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_59 +#define ROM_SW_DATA_59__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_59__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_60 +#define ROM_SW_DATA_60__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_60__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_61 +#define ROM_SW_DATA_61__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_61__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_62 +#define ROM_SW_DATA_62__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_62__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_63 +#define ROM_SW_DATA_63__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_63__ROM_SW_DATA_MASK 0xFFFFFFFFL +//ROM_SW_DATA_64 +#define ROM_SW_DATA_64__ROM_SW_DATA__SHIFT 0x0 +#define ROM_SW_DATA_64__ROM_SW_DATA_MASK 0xFFFFFFFFL + + +// addressBlock: smuio_smuio_gpio_SmuSmuioDec +//SMU_GPIOPAD_SW_INT_STAT +#define SMU_GPIOPAD_SW_INT_STAT__SW_INT_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_SW_INT_STAT__SW_INT_STAT_MASK 0x00000001L +//SMU_GPIOPAD_MASK +#define SMU_GPIOPAD_MASK__GPIO_MASK__SHIFT 0x0 +#define SMU_GPIOPAD_MASK__GPIO_MASK_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_A +#define SMU_GPIOPAD_A__GPIO_A__SHIFT 0x0 +#define SMU_GPIOPAD_A__GPIO_A_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_TXIMPSEL +#define SMU_GPIOPAD_TXIMPSEL__GPIO_TXIMPSEL__SHIFT 0x0 +#define SMU_GPIOPAD_TXIMPSEL__GPIO_TXIMPSEL_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_EN +#define SMU_GPIOPAD_EN__GPIO_EN__SHIFT 0x0 +#define SMU_GPIOPAD_EN__GPIO_EN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_Y +#define SMU_GPIOPAD_Y__GPIO_Y__SHIFT 0x0 +#define SMU_GPIOPAD_Y__GPIO_Y_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_RXEN +#define SMU_GPIOPAD_RXEN__GPIO_RXEN__SHIFT 0x0 +#define SMU_GPIOPAD_RXEN__GPIO_RXEN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_RCVR_SEL0 +#define SMU_GPIOPAD_RCVR_SEL0__GPIO_RCVR_SEL0__SHIFT 0x0 +#define SMU_GPIOPAD_RCVR_SEL0__GPIO_RCVR_SEL0_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_RCVR_SEL1 +#define SMU_GPIOPAD_RCVR_SEL1__GPIO_RCVR_SEL1__SHIFT 0x0 +#define SMU_GPIOPAD_RCVR_SEL1__GPIO_RCVR_SEL1_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_PU_EN +#define SMU_GPIOPAD_PU_EN__GPIO_PU_EN__SHIFT 0x0 +#define SMU_GPIOPAD_PU_EN__GPIO_PU_EN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_PD_EN +#define SMU_GPIOPAD_PD_EN__GPIO_PD_EN__SHIFT 0x0 +#define SMU_GPIOPAD_PD_EN__GPIO_PD_EN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_PINSTRAPS +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0__SHIFT 0x0 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1__SHIFT 0x1 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2__SHIFT 0x2 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3__SHIFT 0x3 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4__SHIFT 0x4 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5__SHIFT 0x5 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6__SHIFT 0x6 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7__SHIFT 0x7 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8__SHIFT 0x8 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9__SHIFT 0x9 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10__SHIFT 0xa +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11__SHIFT 0xb +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12__SHIFT 0xc +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13__SHIFT 0xd +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14__SHIFT 0xe +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15__SHIFT 0xf +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16__SHIFT 0x10 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17__SHIFT 0x11 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18__SHIFT 0x12 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19__SHIFT 0x13 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20__SHIFT 0x14 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21__SHIFT 0x15 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22__SHIFT 0x16 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23__SHIFT 0x17 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24__SHIFT 0x18 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25__SHIFT 0x19 +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26__SHIFT 0x1a +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27__SHIFT 0x1b +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28__SHIFT 0x1c +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29__SHIFT 0x1d +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30__SHIFT 0x1e +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0_MASK 0x00000001L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1_MASK 0x00000002L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2_MASK 0x00000004L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3_MASK 0x00000008L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4_MASK 0x00000010L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5_MASK 0x00000020L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6_MASK 0x00000040L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7_MASK 0x00000080L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8_MASK 0x00000100L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9_MASK 0x00000200L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10_MASK 0x00000400L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11_MASK 0x00000800L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12_MASK 0x00001000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13_MASK 0x00002000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14_MASK 0x00004000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15_MASK 0x00008000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16_MASK 0x00010000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17_MASK 0x00020000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18_MASK 0x00040000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19_MASK 0x00080000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20_MASK 0x00100000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21_MASK 0x00200000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22_MASK 0x00400000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23_MASK 0x00800000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24_MASK 0x01000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25_MASK 0x02000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26_MASK 0x04000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27_MASK 0x08000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28_MASK 0x10000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29_MASK 0x20000000L +#define SMU_GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30_MASK 0x40000000L +//DFT_PINSTRAPS +#define DFT_PINSTRAPS__DFT_PINSTRAPS__SHIFT 0x0 +#define DFT_PINSTRAPS__DFT_PINSTRAPS_MASK 0x000000FFL +//SMU_GPIOPAD_INT_STAT_EN +#define SMU_GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN__SHIFT 0x0 +#define SMU_GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN__SHIFT 0x1f +#define SMU_GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN_MASK 0x1FFFFFFFL +#define SMU_GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN_MASK 0x80000000L +//SMU_GPIOPAD_INT_STAT +#define SMU_GPIOPAD_INT_STAT__GPIO_INT_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT__SHIFT 0x1f +#define SMU_GPIOPAD_INT_STAT__GPIO_INT_STAT_MASK 0x1FFFFFFFL +#define SMU_GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT_MASK 0x80000000L +//SMU_GPIOPAD_INT_STAT_AK +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0__SHIFT 0x0 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1__SHIFT 0x1 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2__SHIFT 0x2 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3__SHIFT 0x3 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4__SHIFT 0x4 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5__SHIFT 0x5 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6__SHIFT 0x6 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7__SHIFT 0x7 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8__SHIFT 0x8 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9__SHIFT 0x9 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10__SHIFT 0xa +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11__SHIFT 0xb +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12__SHIFT 0xc +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13__SHIFT 0xd +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14__SHIFT 0xe +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15__SHIFT 0xf +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16__SHIFT 0x10 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17__SHIFT 0x11 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18__SHIFT 0x12 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19__SHIFT 0x13 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20__SHIFT 0x14 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21__SHIFT 0x15 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22__SHIFT 0x16 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23__SHIFT 0x17 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24__SHIFT 0x18 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25__SHIFT 0x19 +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26__SHIFT 0x1a +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27__SHIFT 0x1b +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28__SHIFT 0x1c +#define SMU_GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK__SHIFT 0x1f +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0_MASK 0x00000001L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1_MASK 0x00000002L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2_MASK 0x00000004L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3_MASK 0x00000008L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4_MASK 0x00000010L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5_MASK 0x00000020L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6_MASK 0x00000040L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7_MASK 0x00000080L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8_MASK 0x00000100L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9_MASK 0x00000200L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10_MASK 0x00000400L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11_MASK 0x00000800L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12_MASK 0x00001000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13_MASK 0x00002000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14_MASK 0x00004000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15_MASK 0x00008000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16_MASK 0x00010000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17_MASK 0x00020000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18_MASK 0x00040000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19_MASK 0x00080000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20_MASK 0x00100000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21_MASK 0x00200000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22_MASK 0x00400000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23_MASK 0x00800000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24_MASK 0x01000000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25_MASK 0x02000000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26_MASK 0x04000000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27_MASK 0x08000000L +#define SMU_GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28_MASK 0x10000000L +#define SMU_GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK_MASK 0x80000000L +//SMU_GPIOPAD_INT_EN +#define SMU_GPIOPAD_INT_EN__GPIO_INT_EN__SHIFT 0x0 +#define SMU_GPIOPAD_INT_EN__SW_INITIATED_INT_EN__SHIFT 0x1f +#define SMU_GPIOPAD_INT_EN__GPIO_INT_EN_MASK 0x1FFFFFFFL +#define SMU_GPIOPAD_INT_EN__SW_INITIATED_INT_EN_MASK 0x80000000L +//SMU_GPIOPAD_INT_TYPE +#define SMU_GPIOPAD_INT_TYPE__GPIO_INT_TYPE__SHIFT 0x0 +#define SMU_GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE__SHIFT 0x1f +#define SMU_GPIOPAD_INT_TYPE__GPIO_INT_TYPE_MASK 0x1FFFFFFFL +#define SMU_GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE_MASK 0x80000000L +//SMU_GPIOPAD_INT_POLARITY +#define SMU_GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY__SHIFT 0x0 +#define SMU_GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY__SHIFT 0x1f +#define SMU_GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY_MASK 0x1FFFFFFFL +#define SMU_GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY_MASK 0x80000000L +//SMUIO_PCC_GPIO_SELECT +#define SMUIO_PCC_GPIO_SELECT__GPIO__SHIFT 0x0 +#define SMUIO_PCC_GPIO_SELECT__GPIO_MASK 0xFFFFFFFFL +//SMU_GPIOPAD_S0 +#define SMU_GPIOPAD_S0__GPIO_S0__SHIFT 0x0 +#define SMU_GPIOPAD_S0__GPIO_S0_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_S1 +#define SMU_GPIOPAD_S1__GPIO_S1__SHIFT 0x0 +#define SMU_GPIOPAD_S1__GPIO_S1_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_SCHMEN +#define SMU_GPIOPAD_SCHMEN__GPIO_SCHMEN__SHIFT 0x0 +#define SMU_GPIOPAD_SCHMEN__GPIO_SCHMEN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_SCL_EN +#define SMU_GPIOPAD_SCL_EN__GPIO_SCL_EN__SHIFT 0x0 +#define SMU_GPIOPAD_SCL_EN__GPIO_SCL_EN_MASK 0x7FFFFFFFL +//SMU_GPIOPAD_SDA_EN +#define SMU_GPIOPAD_SDA_EN__GPIO_SDA_EN__SHIFT 0x0 +#define SMU_GPIOPAD_SDA_EN__GPIO_SDA_EN_MASK 0x7FFFFFFFL +//SMUIO_GPIO_INT0_SELECT +#define SMUIO_GPIO_INT0_SELECT__GPIO_INT0_SELECT__SHIFT 0x0 +#define SMUIO_GPIO_INT0_SELECT__GPIO_INT0_SELECT_MASK 0xFFFFFFFFL +//SMUIO_GPIO_INT1_SELECT +#define SMUIO_GPIO_INT1_SELECT__GPIO_INT1_SELECT__SHIFT 0x0 +#define SMUIO_GPIO_INT1_SELECT__GPIO_INT1_SELECT_MASK 0xFFFFFFFFL +//SMUIO_GPIO_INT2_SELECT +#define SMUIO_GPIO_INT2_SELECT__GPIO_INT2_SELECT__SHIFT 0x0 +#define SMUIO_GPIO_INT2_SELECT__GPIO_INT2_SELECT_MASK 0xFFFFFFFFL +//SMUIO_GPIO_INT3_SELECT +#define SMUIO_GPIO_INT3_SELECT__GPIO_INT3_SELECT__SHIFT 0x0 +#define SMUIO_GPIO_INT3_SELECT__GPIO_INT3_SELECT_MASK 0xFFFFFFFFL +//SMU_GPIOPAD_MP_INT0_STAT +#define SMU_GPIOPAD_MP_INT0_STAT__GPIO_MP_INT0_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_MP_INT0_STAT__GPIO_MP_INT0_STAT_MASK 0x1FFFFFFFL +//SMU_GPIOPAD_MP_INT1_STAT +#define SMU_GPIOPAD_MP_INT1_STAT__GPIO_MP_INT1_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_MP_INT1_STAT__GPIO_MP_INT1_STAT_MASK 0x1FFFFFFFL +//SMU_GPIOPAD_MP_INT2_STAT +#define SMU_GPIOPAD_MP_INT2_STAT__GPIO_MP_INT2_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_MP_INT2_STAT__GPIO_MP_INT2_STAT_MASK 0x1FFFFFFFL +//SMU_GPIOPAD_MP_INT3_STAT +#define SMU_GPIOPAD_MP_INT3_STAT__GPIO_MP_INT3_STAT__SHIFT 0x0 +#define SMU_GPIOPAD_MP_INT3_STAT__GPIO_MP_INT3_STAT_MASK 0x1FFFFFFFL +//SMIO_INDEX +#define SMIO_INDEX__SW_SMIO_INDEX__SHIFT 0x0 +#define SMIO_INDEX__SW_SMIO_INDEX_MASK 0x00000001L +//S0_VID_SMIO_CNTL +#define S0_VID_SMIO_CNTL__S0_SMIO_VALUES__SHIFT 0x0 +#define S0_VID_SMIO_CNTL__S0_SMIO_VALUES_MASK 0xFFFFFFFFL +//S1_VID_SMIO_CNTL +#define S1_VID_SMIO_CNTL__S1_SMIO_VALUES__SHIFT 0x0 +#define S1_VID_SMIO_CNTL__S1_SMIO_VALUES_MASK 0xFFFFFFFFL +//OPEN_DRAIN_SELECT +#define OPEN_DRAIN_SELECT__OPEN_DRAIN_SELECT__SHIFT 0x0 +#define OPEN_DRAIN_SELECT__RESERVED__SHIFT 0x1f +#define OPEN_DRAIN_SELECT__OPEN_DRAIN_SELECT_MASK 0x7FFFFFFFL +#define OPEN_DRAIN_SELECT__RESERVED_MASK 0x80000000L +//SMIO_ENABLE +#define SMIO_ENABLE__SMIO_ENABLE__SHIFT 0x0 +#define SMIO_ENABLE__SMIO_ENABLE_MASK 0xFFFFFFFFL + +#endif diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 32054ecf0b87..805c9d37a2b4 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -150,6 +150,7 @@ enum amd_pp_sensors { AMDGPU_PP_SENSOR_VCN_POWER_STATE, AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK, AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK, + AMDGPU_PP_SENSOR_VCN_LOAD, }; enum amd_pp_task { @@ -420,7 +421,7 @@ struct amd_pm_funcs { int (*set_hard_min_dcefclk_by_freq)(void *handle, uint32_t clock); int (*set_hard_min_fclk_by_freq)(void *handle, uint32_t clock); int (*set_min_deep_sleep_dcefclk)(void *handle, uint32_t clock); - bool (*get_asic_baco_capability)(void *handle); + int (*get_asic_baco_capability)(void *handle); int (*get_asic_baco_state)(void *handle, int *state); int (*set_asic_baco_state)(void *handle, int state); int (*get_ppfeature_status)(void *handle, char *buf); diff --git a/drivers/gpu/drm/amd/include/mes_v11_api_def.h b/drivers/gpu/drm/amd/include/mes_v11_api_def.h index ec5b9ab67c5e..b72d5d362251 100644 --- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h +++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h @@ -61,6 +61,7 @@ enum MES_SCH_API_OPCODE { MES_SCH_API_MISC = 14, MES_SCH_API_UPDATE_ROOT_PAGE_TABLE = 15, MES_SCH_API_AMD_LOG = 16, + MES_SCH_API_SET_HW_RSRC_1 = 19, MES_SCH_API_MAX = 0xFF }; @@ -238,6 +239,26 @@ union MESAPI_SET_HW_RESOURCES { uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS]; }; +union MESAPI_SET_HW_RESOURCES_1 { + struct { + union MES_API_HEADER header; + struct MES_API_STATUS api_status; + uint64_t timestamp; + union { + struct { + uint32_t enable_mes_info_ctx : 1; + uint32_t reserved : 31; + }; + uint32_t uint32_all; + }; + uint64_t mes_info_ctx_mc_addr; + uint32_t mes_info_ctx_size; + uint32_t mes_kiq_unmap_timeout; // unit is 100ms + }; + + uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS]; +}; + union MESAPI__ADD_QUEUE { struct { union MES_API_HEADER header; @@ -278,10 +299,21 @@ union MESAPI__ADD_QUEUE { uint32_t skip_process_ctx_clear : 1; uint32_t map_legacy_kq : 1; uint32_t exclusively_scheduled : 1; - uint32_t reserved : 17; + uint32_t is_long_running : 1; + uint32_t is_dwm_queue : 1; + uint32_t is_video_blit_queue : 1; + uint32_t reserved : 14; }; - struct MES_API_STATUS api_status; - uint64_t tma_addr; + struct MES_API_STATUS api_status; + uint64_t tma_addr; + uint32_t sch_id; + uint64_t timestamp; + uint32_t process_context_array_index; + uint32_t gang_context_array_index; + uint32_t pipe_id; + uint32_t queue_id; + uint32_t alignment_mode_setting; + uint64_t unmap_flag_addr; }; uint32_t max_dwords_in_api[API_FRAME_SIZE_IN_DWORDS]; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index f84bfed50681..eee919577b44 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -199,14 +199,14 @@ int amdgpu_dpm_notify_rlc_state(struct amdgpu_device *adev, bool en) return ret; } -bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) +int amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) { const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; void *pp_handle = adev->powerplay.pp_handle; - bool ret; + int ret; if (!pp_funcs || !pp_funcs->get_asic_baco_capability) - return false; + return 0; /* Don't use baco for reset in S3. * This is a workaround for some platforms * where entering BACO during suspend @@ -217,7 +217,7 @@ bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) * devices. Needs more investigation. */ if (adev->in_s3) - return false; + return 0; mutex_lock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index f09b9d49297e..c11952a4389b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -38,6 +38,8 @@ #define MAX_NUM_OF_FEATURES_PER_SUBSET 8 #define MAX_NUM_OF_SUBSETS 8 +#define DEVICE_ATTR_IS(_name) (attr_id == device_attr_id__##_name) + struct od_attribute { struct kobj_attribute attribute; struct list_head entry; @@ -1581,6 +1583,30 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, return sysfs_emit(buf, "%d\n", value); } +/** + * DOC: vcn_busy_percent + * + * The amdgpu driver provides a sysfs API for reading how busy the VCN + * is as a percentage. The file vcn_busy_percent is used for this. + * The SMU firmware computes a percentage of load based on the + * aggregate activity level in the IP cores. + */ +static ssize_t amdgpu_get_vcn_busy_percent(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = drm_to_adev(ddev); + unsigned int value; + int r; + + r = amdgpu_hwmon_get_sensor_generic(adev, AMDGPU_PP_SENSOR_VCN_LOAD, &value); + if (r) + return r; + + return sysfs_emit(buf, "%d\n", value); +} + /** * DOC: pcie_bw * @@ -2091,6 +2117,99 @@ static int pp_dpm_dcefclk_attr_update(struct amdgpu_device *adev, struct amdgpu_ return 0; } +static int pp_dpm_clk_default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, + uint32_t mask, enum amdgpu_device_attr_states *states) +{ + struct device_attribute *dev_attr = &attr->dev_attr; + enum amdgpu_device_attr_id attr_id = attr->attr_id; + uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0); + uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0); + + *states = ATTR_STATE_SUPPORTED; + + if (!(attr->flags & mask)) { + *states = ATTR_STATE_UNSUPPORTED; + return 0; + } + + if (DEVICE_ATTR_IS(pp_dpm_socclk)) { + if (gc_ver < IP_VERSION(9, 0, 0)) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { + if (mp1_ver < IP_VERSION(10, 0, 0)) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 3) || + gc_ver == IP_VERSION(10, 3, 6) || + gc_ver == IP_VERSION(10, 3, 7) || + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(10, 1, 2) || + gc_ver == IP_VERSION(11, 0, 0) || + gc_ver == IP_VERSION(11, 0, 1) || + gc_ver == IP_VERSION(11, 0, 4) || + gc_ver == IP_VERSION(11, 5, 0) || + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3) || + gc_ver == IP_VERSION(9, 4, 3))) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_vclk1)) { + if (!((gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 3) || + gc_ver == IP_VERSION(10, 3, 6) || + gc_ver == IP_VERSION(10, 3, 7) || + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(10, 1, 2) || + gc_ver == IP_VERSION(11, 0, 0) || + gc_ver == IP_VERSION(11, 0, 1) || + gc_ver == IP_VERSION(11, 0, 4) || + gc_ver == IP_VERSION(11, 5, 0) || + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3) || + gc_ver == IP_VERSION(9, 4, 3))) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_dclk1)) { + if (!((gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0) || + gc_ver == IP_VERSION(11, 0, 2) || + gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_pcie)) { + if (gc_ver == IP_VERSION(9, 4, 2) || + gc_ver == IP_VERSION(9, 4, 3)) + *states = ATTR_STATE_UNSUPPORTED; + } + + switch (gc_ver) { + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): + /* the Mi series card does not support standalone mclk/socclk/fclk level setting */ + if (DEVICE_ATTR_IS(pp_dpm_mclk) || + DEVICE_ATTR_IS(pp_dpm_socclk) || + DEVICE_ATTR_IS(pp_dpm_fclk)) { + dev_attr->attr.mode &= ~S_IWUGO; + dev_attr->store = NULL; + } + break; + default: + break; + } + + /* setting should not be allowed from VF if not in one VF mode */ + if (amdgpu_sriov_vf(adev) && amdgpu_sriov_is_pp_one_vf(adev)) { + dev_attr->attr.mode &= ~S_IWUGO; + dev_attr->store = NULL; + } + + return 0; +} + /* Following items will be read out to indicate current plpd policy: * - -1: none * - 0: disallow @@ -2162,17 +2281,26 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RO(pp_cur_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_force_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(pp_table, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_sclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_socclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk1, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk1, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_sclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_socclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_vclk1, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_dclk1, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, .attr_update = pp_dpm_dcefclk_attr_update), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, + .attr_update = pp_dpm_clk_default_attr_update), AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_mclk_od, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_power_profile_mode, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), @@ -2180,6 +2308,7 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { .attr_update = pp_od_clk_voltage_attr_update), AMDGPU_DEVICE_ATTR_RO(gpu_busy_percent, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RO(mem_busy_percent, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RO(vcn_busy_percent, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RO(pcie_bw, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), @@ -2201,28 +2330,28 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ uint32_t mask, enum amdgpu_device_attr_states *states) { struct device_attribute *dev_attr = &attr->dev_attr; - uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0); + enum amdgpu_device_attr_id attr_id = attr->attr_id; uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0); - const char *attr_name = dev_attr->attr.name; if (!(attr->flags & mask)) { *states = ATTR_STATE_UNSUPPORTED; return 0; } -#define DEVICE_ATTR_IS(_name) (!strcmp(attr_name, #_name)) - - if (DEVICE_ATTR_IS(pp_dpm_socclk)) { - if (gc_ver < IP_VERSION(9, 0, 0)) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { - if (mp1_ver < IP_VERSION(10, 0, 0)) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(mem_busy_percent)) { + if (DEVICE_ATTR_IS(mem_busy_percent)) { if ((adev->flags & AMD_IS_APU && gc_ver != IP_VERSION(9, 4, 3)) || gc_ver == IP_VERSION(9, 0, 1)) *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(vcn_busy_percent)) { + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 3) || + gc_ver == IP_VERSION(10, 3, 6) || + gc_ver == IP_VERSION(10, 3, 7) || + gc_ver == IP_VERSION(11, 0, 1) || + gc_ver == IP_VERSION(11, 0, 4) || + gc_ver == IP_VERSION(11, 5, 0))) + *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pcie_bw)) { /* PCIe Perf counters won't work on APU nodes */ if (adev->flags & AMD_IS_APU || @@ -2253,36 +2382,6 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(gpu_metrics)) { if (gc_ver < IP_VERSION(9, 1, 0)) *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { - if (!(gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(10, 1, 2) || - gc_ver == IP_VERSION(11, 0, 0) || - gc_ver == IP_VERSION(11, 0, 2) || - gc_ver == IP_VERSION(11, 0, 3) || - gc_ver == IP_VERSION(9, 4, 3))) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_vclk1)) { - if (!((gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(11, 0, 2) || - gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { - if (!(gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(10, 1, 2) || - gc_ver == IP_VERSION(11, 0, 0) || - gc_ver == IP_VERSION(11, 0, 2) || - gc_ver == IP_VERSION(11, 0, 3) || - gc_ver == IP_VERSION(9, 4, 3))) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_dclk1)) { - if (!((gc_ver == IP_VERSION(10, 3, 1) || - gc_ver == IP_VERSION(10, 3, 0) || - gc_ver == IP_VERSION(11, 0, 2) || - gc_ver == IP_VERSION(11, 0, 3)) && adev->vcn.num_vcn_inst >= 2)) - *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; @@ -2304,23 +2403,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (amdgpu_dpm_get_apu_thermal_limit(adev, &limit) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_pcie)) { - if (gc_ver == IP_VERSION(9, 4, 2) || - gc_ver == IP_VERSION(9, 4, 3)) - *states = ATTR_STATE_UNSUPPORTED; } switch (gc_ver) { - case IP_VERSION(9, 4, 1): - case IP_VERSION(9, 4, 2): - /* the Mi series card does not support standalone mclk/socclk/fclk level setting */ - if (DEVICE_ATTR_IS(pp_dpm_mclk) || - DEVICE_ATTR_IS(pp_dpm_socclk) || - DEVICE_ATTR_IS(pp_dpm_fclk)) { - dev_attr->attr.mode &= ~S_IWUGO; - dev_attr->store = NULL; - } - break; case IP_VERSION(10, 3, 0): if (DEVICE_ATTR_IS(power_dpm_force_performance_level) && amdgpu_sriov_vf(adev)) { @@ -2332,14 +2417,6 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ break; } - /* setting should not be allowed from VF if not in one VF mode */ - if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { - dev_attr->attr.mode &= ~S_IWUGO; - dev_attr->store = NULL; - } - -#undef DEVICE_ATTR_IS - return 0; } @@ -4261,6 +4338,13 @@ static int amdgpu_od_set_init(struct amdgpu_device *adev) } } + /* + * If gpu_od is the only member in the list, that means gpu_od is an + * empty directory, so remove it. + */ + if (list_is_singular(&adev->pm.od_kobj_list)) + goto err_out; + return 0; err_out: @@ -4322,6 +4406,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) ret = amdgpu_od_set_init(adev); if (ret) goto err_out1; + } else if (adev->pm.pp_feature & PP_OVERDRIVE_MASK) { + dev_info(adev->dev, "overdrive feature is not supported\n"); } adev->pm.sysfs_initialized = true; @@ -4429,6 +4515,9 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a /* MEM Load */ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size)) seq_printf(m, "MEM Load: %u %%\n", value); + /* VCN Load */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_LOAD, (void *)&value, &size)) + seq_printf(m, "VCN Load: %u %%\n", value); seq_printf(m, "\n"); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index 621200e0823f..501f8c726e8d 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -50,8 +50,12 @@ enum amdgpu_runpm_mode { AMDGPU_RUNPM_PX, AMDGPU_RUNPM_BOCO, AMDGPU_RUNPM_BACO, + AMDGPU_RUNPM_BAMACO, }; +#define BACO_SUPPORT (1<<0) +#define MACO_SUPPORT (1<<1) + struct amdgpu_ps { u32 caps; /* vbios flags */ u32 class; /* vbios flags */ @@ -407,7 +411,7 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev); int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev); int amdgpu_dpm_enable_gfx_features(struct amdgpu_device *adev); -bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev); +int amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev); bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev); int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h index eec816f0cbf9..448ba3a14584 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h @@ -43,8 +43,48 @@ enum amdgpu_device_attr_states { ATTR_STATE_SUPPORTED, }; +enum amdgpu_device_attr_id { + device_attr_id__unknown = -1, + device_attr_id__power_dpm_state = 0, + device_attr_id__power_dpm_force_performance_level, + device_attr_id__pp_num_states, + device_attr_id__pp_cur_state, + device_attr_id__pp_force_state, + device_attr_id__pp_table, + device_attr_id__pp_dpm_sclk, + device_attr_id__pp_dpm_mclk, + device_attr_id__pp_dpm_socclk, + device_attr_id__pp_dpm_fclk, + device_attr_id__pp_dpm_vclk, + device_attr_id__pp_dpm_vclk1, + device_attr_id__pp_dpm_dclk, + device_attr_id__pp_dpm_dclk1, + device_attr_id__pp_dpm_dcefclk, + device_attr_id__pp_dpm_pcie, + device_attr_id__pp_sclk_od, + device_attr_id__pp_mclk_od, + device_attr_id__pp_power_profile_mode, + device_attr_id__pp_od_clk_voltage, + device_attr_id__gpu_busy_percent, + device_attr_id__mem_busy_percent, + device_attr_id__vcn_busy_percent, + device_attr_id__pcie_bw, + device_attr_id__pp_features, + device_attr_id__unique_id, + device_attr_id__thermal_throttling_logging, + device_attr_id__apu_thermal_cap, + device_attr_id__gpu_metrics, + device_attr_id__smartshift_apu_power, + device_attr_id__smartshift_dgpu_power, + device_attr_id__smartshift_bias, + device_attr_id__xgmi_plpd_policy, + device_attr_id__pm_metrics, + device_attr_id__count, +}; + struct amdgpu_device_attr { struct device_attribute dev_attr; + enum amdgpu_device_attr_id attr_id; enum amdgpu_device_attr_flags flags; int (*attr_update)(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, uint32_t mask, enum amdgpu_device_attr_states *states); @@ -61,6 +101,7 @@ struct amdgpu_device_attr_entry { #define __AMDGPU_DEVICE_ATTR(_name, _mode, _show, _store, _flags, ...) \ { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .attr_id = device_attr_id__##_name, \ .flags = _flags, \ ##__VA_ARGS__, } diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c index 5cb4725c773f..6bb42d04b247 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/kv_dpm.c @@ -3316,6 +3316,8 @@ static const struct amd_ip_funcs kv_dpm_ip_funcs = { .soft_reset = kv_dpm_soft_reset, .set_clockgating_state = kv_dpm_set_clockgating_state, .set_powergating_state = kv_dpm_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version kv_smu_ip_block = { diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index eb4da3666e05..f245fc0bc6d3 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -8060,6 +8060,8 @@ static const struct amd_ip_funcs si_dpm_ip_funcs = { .soft_reset = si_dpm_soft_reset, .set_clockgating_state = si_dpm_set_clockgating_state, .set_powergating_state = si_dpm_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version si_smu_ip_block = diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index aed0e2cefbf9..5fb21a0508cd 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -302,6 +302,8 @@ static const struct amd_ip_funcs pp_ip_funcs = { .soft_reset = pp_sw_reset, .set_clockgating_state = pp_set_clockgating_state, .set_powergating_state = pp_set_powergating_state, + .dump_ip_state = NULL, + .print_ip_state = NULL, }; const struct amdgpu_ip_block_version pp_smu_ip_block = @@ -1371,7 +1373,7 @@ static int pp_set_active_display_count(void *handle, uint32_t count) return phm_set_active_display_count(hwmgr, count); } -static bool pp_get_asic_baco_capability(void *handle) +static int pp_get_asic_baco_capability(void *handle) { struct pp_hwmgr *hwmgr = handle; @@ -1379,10 +1381,10 @@ static bool pp_get_asic_baco_capability(void *handle) return false; if (!(hwmgr->not_vf && amdgpu_dpm) || - !hwmgr->hwmgr_func->get_asic_baco_capability) + !hwmgr->hwmgr_func->get_bamaco_support) return false; - return hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr); + return hwmgr->hwmgr_func->get_bamaco_support(hwmgr); } static int pp_get_asic_baco_state(void *handle, int *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c index e8a9471c1898..ad60918aaae1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c @@ -33,7 +33,7 @@ #include "smu/smu_7_1_2_d.h" #include "smu/smu_7_1_2_sh_mask.h" -bool smu7_baco_get_capability(struct pp_hwmgr *hwmgr) +int smu7_get_bamaco_support(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg; @@ -44,9 +44,9 @@ bool smu7_baco_get_capability(struct pp_hwmgr *hwmgr) reg = RREG32(mmCC_BIF_BX_FUSESTRAP0); if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK) - return true; + return BACO_SUPPORT; - return false; + return 0; } int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h index 73a773f4ce2e..750082ea74d8 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern bool smu7_baco_get_capability(struct pp_hwmgr *hwmgr); +extern int smu7_get_bamaco_support(struct pp_hwmgr *hwmgr); extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index aa91730e4eaf..1fcd4451001f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -5791,7 +5791,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .get_power_profile_mode = smu7_get_power_profile_mode, .set_power_profile_mode = smu7_set_power_profile_mode, .get_performance_level = smu7_get_performance_level, - .get_asic_baco_capability = smu7_baco_get_capability, + .get_bamaco_support = smu7_get_bamaco_support, .get_asic_baco_state = smu7_baco_get_state, .set_asic_baco_state = smu7_baco_set_state, .power_off_asic = smu7_power_off_asic, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c index c66ef9741535..c1ce1d7cae48 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c @@ -28,13 +28,13 @@ #include "vega10_inc.h" #include "smu9_baco.h" -bool smu9_baco_get_capability(struct pp_hwmgr *hwmgr) +int smu9_get_bamaco_support(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg, data; if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return false; + return 0; WREG32(0x12074, 0xFFF0003B); data = RREG32(0x12075); @@ -43,10 +43,10 @@ bool smu9_baco_get_capability(struct pp_hwmgr *hwmgr) reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - return true; + return BACO_SUPPORT; } - return false; + return 0; } int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h index 9ff7c2ea1b58..2c100482084c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern bool smu9_baco_get_capability(struct pp_hwmgr *hwmgr); +extern int smu9_get_bamaco_support(struct pp_hwmgr *hwmgr); extern int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); #endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index 6d6bc6a380b3..9f5bd998c6bf 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -5756,7 +5756,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .set_power_limit = vega10_set_power_limit, .odn_edit_dpm_table = vega10_odn_edit_dpm_table, .get_performance_level = vega10_get_performance_level, - .get_asic_baco_capability = smu9_baco_get_capability, + .get_bamaco_support = smu9_get_bamaco_support, .get_asic_baco_state = smu9_baco_get_state, .set_asic_baco_state = vega10_baco_set_state, .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c index 460067933de2..c223e3a6bfca 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c @@ -2966,7 +2966,7 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = { .start_thermal_controller = vega12_start_thermal_controller, .powergate_gfx = vega12_gfx_off_control, .get_performance_level = vega12_get_performance_level, - .get_asic_baco_capability = smu9_baco_get_capability, + .get_bamaco_support = smu9_get_bamaco_support, .get_asic_baco_state = smu9_baco_get_state, .set_asic_baco_state = vega12_baco_set_state, .get_ppfeature_status = vega12_get_ppfeature_status, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c index dad4c80aee58..424e4ec9e389 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c @@ -36,22 +36,22 @@ static const struct soc15_baco_cmd_entry clean_baco_tbl[] = { {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, }; -bool vega20_baco_get_capability(struct pp_hwmgr *hwmgr) +int vega20_get_bamaco_support(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); uint32_t reg; if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return false; + return 0; if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) { reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - return true; + return BACO_SUPPORT; } - return false; + return 0; } int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h index bdad9c915631..0f2dd8c008ba 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h @@ -25,7 +25,7 @@ #include "hwmgr.h" #include "common_baco.h" -extern bool vega20_baco_get_capability(struct pp_hwmgr *hwmgr); +extern int vega20_get_bamaco_support(struct pp_hwmgr *hwmgr); extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); extern int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c index 3b33af30eb0f..f9efb0bad807 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c @@ -4422,7 +4422,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { .notify_cac_buffer_info = vega20_notify_cac_buffer_info, .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost, /* BACO related */ - .get_asic_baco_capability = vega20_baco_get_capability, + .get_bamaco_support = vega20_get_bamaco_support, .get_asic_baco_state = vega20_baco_get_state, .set_asic_baco_state = vega20_baco_set_state, .set_mp1_state = vega20_set_mp1_state, diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index 6f536159df4d..69928a4a074b 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -351,7 +351,7 @@ struct pp_hwmgr_func { int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_hard_min_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_soft_max_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); - bool (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr); + int (*get_bamaco_support)(struct pp_hwmgr *hwmgr); int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 246b211b1e85..7789b313285c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -45,6 +45,7 @@ #include "smu_v13_0_6_ppt.h" #include "smu_v13_0_7_ppt.h" #include "smu_v14_0_0_ppt.h" +#include "smu_v14_0_2_ppt.h" #include "amd_pcie.h" /* @@ -715,6 +716,10 @@ static int smu_set_funcs(struct amdgpu_device *adev) case IP_VERSION(14, 0, 1): smu_v14_0_0_set_ppt_funcs(smu); break; + case IP_VERSION(14, 0, 2): + case IP_VERSION(14, 0, 3): + smu_v14_0_2_set_ppt_funcs(smu); + break; default: return -EINVAL; } @@ -735,8 +740,9 @@ static int smu_early_init(void *handle) smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; smu->is_apu = false; - smu->smu_baco.state = SMU_BACO_STATE_EXIT; + smu->smu_baco.state = SMU_BACO_STATE_NONE; smu->smu_baco.platform_support = false; + smu->smu_baco.maco_support = false; smu->user_dpm_profile.fan_mode = -1; mutex_init(&smu->message_lock); @@ -1966,10 +1972,25 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) return 0; } +static int smu_reset_mp1_state(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if ((!adev->in_runpm) && (!adev->in_suspend) && + (!amdgpu_in_reset(adev)) && amdgpu_ip_version(adev, MP1_HWIP, 0) == + IP_VERSION(13, 0, 10) && + !amdgpu_device_has_display_hardware(adev)) + ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD); + + return ret; +} + static int smu_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct smu_context *smu = adev->powerplay.pp_handle; + int ret; if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1987,7 +2008,15 @@ static int smu_hw_fini(void *handle) adev->pm.dpm_enabled = false; - return smu_smc_hw_cleanup(smu); + ret = smu_smc_hw_cleanup(smu); + if (ret) + return ret; + + ret = smu_reset_mp1_state(smu); + if (ret) + return ret; + + return 0; } static void smu_late_fini(void *handle) @@ -3200,17 +3229,17 @@ static int smu_set_xgmi_pstate(void *handle, return ret; } -static bool smu_get_baco_capability(void *handle) +static int smu_get_baco_capability(void *handle) { struct smu_context *smu = handle; if (!smu->pm_enabled) return false; - if (!smu->ppt_funcs || !smu->ppt_funcs->baco_is_support) + if (!smu->ppt_funcs || !smu->ppt_funcs->get_bamaco_support) return false; - return smu->ppt_funcs->baco_is_support(smu); + return smu->ppt_funcs->get_bamaco_support(smu); } static int smu_baco_set_state(void *handle, int state) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index a870bdd49a4e..0917dec8efe3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -424,6 +424,7 @@ enum smu_reset_mode { enum smu_baco_state { SMU_BACO_STATE_ENTER = 0, SMU_BACO_STATE_EXIT, + SMU_BACO_STATE_NONE, }; struct smu_baco_context { @@ -458,7 +459,7 @@ struct smu_umd_pstate_table { struct cmn2asic_msg_mapping { int valid_mapping; int map_to; - int valid_in_vf; + uint32_t flags; }; struct cmn2asic_mapping { @@ -538,6 +539,7 @@ struct smu_context { uint32_t smc_driver_if_version; uint32_t smc_fw_if_version; uint32_t smc_fw_version; + uint32_t smc_fw_caps; bool uploading_custom_pp_table; bool dc_controlled_by_gpio; @@ -1173,9 +1175,11 @@ struct pptable_funcs { int (*get_max_sustainable_clocks_by_dc)(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); /** - * @baco_is_support: Check if GPU supports BACO (Bus Active, Chip Off). + * @get_bamaco_support: Check if GPU supports BACO/MACO + * BACO: Bus Active, Chip Off + * MACO: Memory Active, Chip Off */ - bool (*baco_is_support)(struct smu_context *smu); + int (*get_bamaco_support)(struct smu_context *smu); /** * @baco_get_state: Get the current BACO state. @@ -1482,8 +1486,8 @@ enum smu_baco_seq { BACO_SEQ_COUNT, }; -#define MSG_MAP(msg, index, valid_in_vf) \ - [SMU_MSG_##msg] = {1, (index), (valid_in_vf)} +#define MSG_MAP(msg, index, flags) \ + [SMU_MSG_##msg] = {1, (index), (flags)} #define CLK_MAP(clk, index) \ [SMU_##clk] = {1, (index)} diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h new file mode 100644 index 000000000000..97a29b80fb13 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0.h @@ -0,0 +1,1836 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU14_DRIVER_IF_V14_0_H +#define SMU14_DRIVER_IF_V14_0_H + +//Increment this version if SkuTable_t or BoardTable_t change +#define PPTABLE_VERSION 0x18 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_DPPCLK_DPM_LEVELS 8 +#define NUM_DPREFCLK_DPM_LEVELS 8 +#define NUM_DCFCLK_DPM_LEVELS 8 +#define NUM_DTBCLK_DPM_LEVELS 8 +#define NUM_UCLK_DPM_LEVELS 6 +#define NUM_LINK_LEVELS 3 +#define NUM_FCLK_DPM_LEVELS 8 +#define NUM_OD_FAN_MAX_POINTS 6 + +// Feature Control Defines +#define FEATURE_FW_DATA_READ_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT 2 +#define FEATURE_DPM_UCLK_BIT 3 +#define FEATURE_DPM_FCLK_BIT 4 +#define FEATURE_DPM_SOCCLK_BIT 5 +#define FEATURE_DPM_LINK_BIT 6 +#define FEATURE_DPM_DCN_BIT 7 +#define FEATURE_VMEMP_SCALING_BIT 8 +#define FEATURE_VDDIO_MEM_SCALING_BIT 9 +#define FEATURE_DS_GFXCLK_BIT 10 +#define FEATURE_DS_SOCCLK_BIT 11 +#define FEATURE_DS_FCLK_BIT 12 +#define FEATURE_DS_LCLK_BIT 13 +#define FEATURE_DS_DCFCLK_BIT 14 +#define FEATURE_DS_UCLK_BIT 15 +#define FEATURE_GFX_ULV_BIT 16 +#define FEATURE_FW_DSTATE_BIT 17 +#define FEATURE_GFXOFF_BIT 18 +#define FEATURE_BACO_BIT 19 +#define FEATURE_MM_DPM_BIT 20 +#define FEATURE_SOC_MPCLK_DS_BIT 21 +#define FEATURE_BACO_MPCLK_DS_BIT 22 +#define FEATURE_THROTTLERS_BIT 23 +#define FEATURE_SMARTSHIFT_BIT 24 +#define FEATURE_GTHR_BIT 25 +#define FEATURE_ACDC_BIT 26 +#define FEATURE_VR0HOT_BIT 27 +#define FEATURE_FW_CTF_BIT 28 +#define FEATURE_FAN_CONTROL_BIT 29 +#define FEATURE_GFX_DCS_BIT 30 +#define FEATURE_GFX_READ_MARGIN_BIT 31 +#define FEATURE_LED_DISPLAY_BIT 32 +#define FEATURE_GFXCLK_SPREAD_SPECTRUM_BIT 33 +#define FEATURE_OUT_OF_BAND_MONITOR_BIT 34 +#define FEATURE_OPTIMIZED_VMIN_BIT 35 +#define FEATURE_GFX_IMU_BIT 36 +#define FEATURE_BOOT_TIME_CAL_BIT 37 +#define FEATURE_GFX_PCC_DFLL_BIT 38 +#define FEATURE_SOC_CG_BIT 39 +#define FEATURE_DF_CSTATE_BIT 40 +#define FEATURE_GFX_EDC_BIT 41 +#define FEATURE_BOOT_POWER_OPT_BIT 42 +#define FEATURE_CLOCK_POWER_DOWN_BYPASS_BIT 43 +#define FEATURE_DS_VCN_BIT 44 +#define FEATURE_BACO_CG_BIT 45 +#define FEATURE_MEM_TEMP_READ_BIT 46 +#define FEATURE_ATHUB_MMHUB_PG_BIT 47 +#define FEATURE_SOC_PCC_BIT 48 +#define FEATURE_EDC_PWRBRK_BIT 49 +#define FEATURE_SOC_EDC_XVMIN_BIT 50 +#define FEATURE_GFX_PSM_DIDT_BIT 51 +#define FEATURE_APT_ALL_ENABLE_BIT 52 +#define FEATURE_APT_SQ_THROTTLE_BIT 53 +#define FEATURE_APT_PF_DCS_BIT 54 +#define FEATURE_GFX_EDC_XVMIN_BIT 55 +#define FEATURE_GFX_DIDT_XVMIN_BIT 56 +#define FEATURE_FAN_ABNORMAL_BIT 57 +#define FEATURE_CLOCK_STRETCH_COMPENSATOR 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 +#define NUM_FEATURES 64 + +#define ALLOWED_FEATURE_CTRL_DEFAULT 0xFFFFFFFFFFFFFFFFULL +#define ALLOWED_FEATURE_CTRL_SCPM (1 << FEATURE_DPM_GFXCLK_BIT) | \ + (1 << FEATURE_DPM_GFX_POWER_OPTIMIZER_BIT) | \ + (1 << FEATURE_DPM_UCLK_BIT) | \ + (1 << FEATURE_DPM_FCLK_BIT) | \ + (1 << FEATURE_DPM_SOCCLK_BIT) | \ + (1 << FEATURE_DPM_LINK_BIT) | \ + (1 << FEATURE_DPM_DCN_BIT) | \ + (1 << FEATURE_DS_GFXCLK_BIT) | \ + (1 << FEATURE_DS_SOCCLK_BIT) | \ + (1 << FEATURE_DS_FCLK_BIT) | \ + (1 << FEATURE_DS_LCLK_BIT) | \ + (1 << FEATURE_DS_DCFCLK_BIT) | \ + (1 << FEATURE_DS_UCLK_BIT) | \ + (1ULL << FEATURE_DS_VCN_BIT) + + +//For use with feature control messages +typedef enum { + FEATURE_PWR_ALL, + FEATURE_PWR_S5, + FEATURE_PWR_BACO, + FEATURE_PWR_SOC, + FEATURE_PWR_GFX, + FEATURE_PWR_DOMAIN_COUNT, +} FEATURE_PWR_DOMAIN_e; + +//For use with feature control + BTC save restore +typedef enum { + FEATURE_BTC_NOP, + FEATURE_BTC_SAVE, + FEATURE_BTC_RESTORE, + FEATURE_BTC_COUNT, +} FEATURE_BTC_e; + +// Debug Overrides Bitmask +#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000001 +#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_DCN_FCLK 0x00000002 +#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_MP0_FCLK 0x00000004 +#define DEBUG_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCFCLK 0x00000008 +#define DEBUG_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00000010 +#define DEBUG_OVERRIDE_DISABLE_VCN_PG 0x00000020 +#define DEBUG_OVERRIDE_DISABLE_FMAX_VMAX 0x00000040 +#define DEBUG_OVERRIDE_DISABLE_IMU_FW_CHECKS 0x00000080 +#define DEBUG_OVERRIDE_DISABLE_D0i2_REENTRY_HSR_TIMER_CHECK 0x00000100 +#define DEBUG_OVERRIDE_DISABLE_DFLL 0x00000200 +#define DEBUG_OVERRIDE_ENABLE_RLC_VF_BRINGUP_MODE 0x00000400 +#define DEBUG_OVERRIDE_DFLL_MASTER_MODE 0x00000800 +#define DEBUG_OVERRIDE_ENABLE_PROFILING_MODE 0x00001000 +#define DEBUG_OVERRIDE_ENABLE_SOC_VF_BRINGUP_MODE 0x00002000 +#define DEBUG_OVERRIDE_ENABLE_PER_WGP_RESIENCY 0x00004000 +#define DEBUG_OVERRIDE_DISABLE_MEMORY_VOLTAGE_SCALING 0x00008000 + +// VR Mapping Bit Defines +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + +// PSI Bit Defines +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + +typedef enum { + SVI_PSI_0, // Full phase count (default) + SVI_PSI_1, // Phase count 1st level + SVI_PSI_2, // Phase count 2nd level + SVI_PSI_3, // Single phase operation + active diode emulation + SVI_PSI_4, // Single phase operation + passive diode emulation *optional* + SVI_PSI_5, // Reserved + SVI_PSI_6, // Power down to 0V (voltage regulation disabled) + SVI_PSI_7, // Automated phase shedding and diode emulation +} SVI_PSI_e; + +// Throttler Control/Status Bits +#define THROTTLER_TEMP_EDGE_BIT 0 +#define THROTTLER_TEMP_HOTSPOT_BIT 1 +#define THROTTLER_TEMP_HOTSPOT_GFX_BIT 2 +#define THROTTLER_TEMP_HOTSPOT_SOC_BIT 3 +#define THROTTLER_TEMP_MEM_BIT 4 +#define THROTTLER_TEMP_VR_GFX_BIT 5 +#define THROTTLER_TEMP_VR_SOC_BIT 6 +#define THROTTLER_TEMP_VR_MEM0_BIT 7 +#define THROTTLER_TEMP_VR_MEM1_BIT 8 +#define THROTTLER_TEMP_LIQUID0_BIT 9 +#define THROTTLER_TEMP_LIQUID1_BIT 10 +#define THROTTLER_TEMP_PLX_BIT 11 +#define THROTTLER_TDC_GFX_BIT 12 +#define THROTTLER_TDC_SOC_BIT 13 +#define THROTTLER_PPT0_BIT 14 +#define THROTTLER_PPT1_BIT 15 +#define THROTTLER_PPT2_BIT 16 +#define THROTTLER_PPT3_BIT 17 +#define THROTTLER_FIT_BIT 18 +#define THROTTLER_GFX_APCC_PLUS_BIT 19 +#define THROTTLER_GFX_DVO_BIT 20 +#define THROTTLER_COUNT 21 + +// FW DState Features Control Bits +#define FW_DSTATE_SOC_ULV_BIT 0 +#define FW_DSTATE_G6_HSR_BIT 1 +#define FW_DSTATE_G6_PHY_VMEMP_OFF_BIT 2 +#define FW_DSTATE_SMN_DS_BIT 3 +#define FW_DSTATE_MP1_WHISPER_MODE_BIT 4 +#define FW_DSTATE_SOC_LIV_MIN_BIT 5 +#define FW_DSTATE_SOC_PLL_PWRDN_BIT 6 +#define FW_DSTATE_MEM_PLL_PWRDN_BIT 7 +#define FW_DSTATE_MALL_ALLOC_BIT 8 +#define FW_DSTATE_MEM_PSI_BIT 9 +#define FW_DSTATE_HSR_NON_STROBE_BIT 10 +#define FW_DSTATE_MP0_ENTER_WFI_BIT 11 +#define FW_DSTATE_MALL_FLUSH_BIT 12 +#define FW_DSTATE_SOC_PSI_BIT 13 +#define FW_DSTATE_MMHUB_INTERLOCK_BIT 14 +#define FW_DSTATE_D0i3_2_QUIET_FW_BIT 15 +#define FW_DSTATE_CLDO_PRG_BIT 16 +#define FW_DSTATE_DF_PLL_PWRDN_BIT 17 + +//LED Display Mask & Control Bits +#define LED_DISPLAY_GFX_DPM_BIT 0 +#define LED_DISPLAY_PCIE_BIT 1 +#define LED_DISPLAY_ERROR_BIT 2 + + +#define MEM_TEMP_READ_OUT_OF_BAND_BIT 0 +#define MEM_TEMP_READ_IN_BAND_REFRESH_BIT 1 +#define MEM_TEMP_READ_IN_BAND_DUMMY_PSTATE_BIT 2 + +typedef enum { + SMARTSHIFT_VERSION_1, + SMARTSHIFT_VERSION_2, + SMARTSHIFT_VERSION_3, +} SMARTSHIFT_VERSION_e; + +typedef enum { + FOPT_CALC_AC_CALC_DC, + FOPT_PPTABLE_AC_CALC_DC, + FOPT_CALC_AC_PPTABLE_DC, + FOPT_PPTABLE_AC_PPTABLE_DC, +} FOPT_CALC_e; + +typedef enum { + DRAM_BIT_WIDTH_DISABLED = 0, + DRAM_BIT_WIDTH_X_8 = 8, + DRAM_BIT_WIDTH_X_16 = 16, + DRAM_BIT_WIDTH_X_32 = 32, + DRAM_BIT_WIDTH_X_64 = 64, + DRAM_BIT_WIDTH_X_128 = 128, + DRAM_BIT_WIDTH_COUNT, +} DRAM_BIT_WIDTH_TYPE_e; + +//I2C Interface +#define NUM_I2C_CONTROLLERS 8 + +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +#define MAX_SW_I2C_COMMANDS 24 + +typedef enum { + I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 + I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 + I2C_CONTROLLER_PORT_COUNT, +} I2cControllerPort_e; + +typedef enum { + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VMEMP, + I2C_CONTROLLER_NAME_VR_VDDIO, + I2C_CONTROLLER_NAME_LIQUID0, + I2C_CONTROLLER_NAME_LIQUID1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_FAN_INTAKE, + I2C_CONTROLLER_NAME_COUNT, +} I2cControllerName_e; + +typedef enum { + I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, + I2C_CONTROLLER_THROTTLER_VR_GFX, + I2C_CONTROLLER_THROTTLER_VR_SOC, + I2C_CONTROLLER_THROTTLER_VR_VMEMP, + I2C_CONTROLLER_THROTTLER_VR_VDDIO, + I2C_CONTROLLER_THROTTLER_LIQUID0, + I2C_CONTROLLER_THROTTLER_LIQUID1, + I2C_CONTROLLER_THROTTLER_PLX, + I2C_CONTROLLER_THROTTLER_FAN_INTAKE, + I2C_CONTROLLER_THROTTLER_INA3221, + I2C_CONTROLLER_THROTTLER_COUNT, +} I2cControllerThrottler_e; + +typedef enum { + I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, + I2C_CONTROLLER_PROTOCOL_VR_IR35217, + I2C_CONTROLLER_PROTOCOL_TMP_MAX31875, + I2C_CONTROLLER_PROTOCOL_INA3221, + I2C_CONTROLLER_PROTOCOL_TMP_MAX6604, + I2C_CONTROLLER_PROTOCOL_COUNT, +} I2cControllerProtocol_e; + +typedef struct { + uint8_t Enabled; + uint8_t Speed; + uint8_t SlaveAddress; + uint8_t ControllerPort; + uint8_t ControllerName; + uint8_t ThermalThrotter; + uint8_t I2cProtocol; + uint8_t PaddingConfig; +} I2cControllerConfig_t; + +typedef enum { + I2C_PORT_SVD_SCL = 0, + I2C_PORT_GPIO, +} I2cPort_e; + +typedef enum { + I2C_SPEED_FAST_50K = 0, //50 Kbits/s + I2C_SPEED_FAST_100K, //100 Kbits/s + I2C_SPEED_FAST_400K, //400 Kbits/s + I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) + I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) + I2C_SPEED_HIGH_2M, //2.3 Mbits/s + I2C_SPEED_COUNT, +} I2cSpeed_e; + +typedef enum { + I2C_CMD_READ = 0, + I2C_CMD_WRITE, + I2C_CMD_COUNT, +} I2cCmdType_e; + +#define CMDCONFIG_STOP_BIT 0 +#define CMDCONFIG_RESTART_BIT 1 +#define CMDCONFIG_READWRITE_BIT 2 //bit should be 0 for read, 1 for write + +#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) +#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) +#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT) + +typedef struct { + uint8_t ReadWriteData; //Return data for read. Data to send for write + uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command, and is a read or write +} SwI2cCmd_t; //SW I2C Command Table + +typedef struct { + uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) + uint8_t I2CSpeed; //Use I2cSpeed_e to indicate speed to select + uint8_t SlaveAddress; //Slave address of device + uint8_t NumCmds; //Number of commands + + SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; +} SwI2cRequest_t; // SW I2C Request Table + +typedef struct { + SwI2cRequest_t SwI2cRequest; + + uint32_t Spare[8]; + uint32_t MmHubPadding[8]; // SMU internal use +} SwI2cRequestExternal_t; + +typedef struct { + uint64_t mca_umc_status; + uint64_t mca_umc_addr; + + uint16_t ce_count_lo_chip; + uint16_t ce_count_hi_chip; + + uint32_t eccPadding; +} EccInfo_t; + +typedef struct { + EccInfo_t EccInfo[24]; +} EccInfoTable_t; + +//D3HOT sequences +typedef enum { + BACO_SEQUENCE, + MSR_SEQUENCE, + BAMACO_SEQUENCE, + ULPS_SEQUENCE, + D3HOT_SEQUENCE_COUNT, +} D3HOTSequence_e; + +//This is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_DYNAMIC_MODE = 0, + PG_STATIC_MODE, +} PowerGatingMode_e; + +//This is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_POWER_DOWN = 0, + PG_POWER_UP, +} PowerGatingSettings_e; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} QuadraticInt_t; + +typedef struct { + uint32_t m; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable +} LinearInt_t; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} DroopInt_t; + +typedef enum { + DCS_ARCH_DISABLED, + DCS_ARCH_FADCS, + DCS_ARCH_ASYNC, +} DCS_ARCH_e; + +//Only Clks that have DPM descriptors are listed here +typedef enum { + PPCLK_GFXCLK = 0, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_FCLK, + PPCLK_DCLK_0, + PPCLK_VCLK_0, + PPCLK_DISPCLK, + PPCLK_DPPCLK, + PPCLK_DPREFCLK, + PPCLK_DCFCLK, + PPCLK_DTBCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef enum { + VOLTAGE_MODE_PPTABLE = 0, + VOLTAGE_MODE_FUSES, + VOLTAGE_MODE_COUNT, +} VOLTAGE_MODE_e; + +typedef enum { + AVFS_VOLTAGE_GFX = 0, + AVFS_VOLTAGE_SOC, + AVFS_VOLTAGE_COUNT, +} AVFS_VOLTAGE_TYPE_e; + +typedef enum { + AVFS_TEMP_COLD = 0, + AVFS_TEMP_HOT, + AVFS_TEMP_COUNT, +} AVFS_TEMP_e; + +typedef enum { + AVFS_D_G, + AVFS_D_COUNT, +} AVFS_D_e; + + +typedef enum { + UCLK_DIV_BY_1 = 0, + UCLK_DIV_BY_2, + UCLK_DIV_BY_4, + UCLK_DIV_BY_8, +} UCLK_DIV_e; + +typedef enum { + GPIO_INT_POLARITY_ACTIVE_LOW = 0, + GPIO_INT_POLARITY_ACTIVE_HIGH, +} GpioIntPolarity_e; + +typedef enum { + PWR_CONFIG_TDP = 0, + PWR_CONFIG_TGP, + PWR_CONFIG_TCP_ESTIMATED, + PWR_CONFIG_TCP_MEASURED, + PWR_CONFIG_TBP_DESKTOP, + PWR_CONFIG_TBP_MOBILE, +} PwrConfig_e; + +typedef struct { + uint8_t Padding; + uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM + uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used + uint8_t CalculateFopt; // Indication whether FW should calculate Fopt or use values below. Reference FOPT_CALC_e + LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) + uint32_t Padding3[3]; + uint16_t Padding4; + uint16_t FoptimalDc; //Foptimal frequency in DC power mode. + uint16_t FoptimalAc; //Foptimal frequency in AC power mode. + uint16_t Padding2; +} DpmDescriptor_t; + +typedef enum { + PPT_THROTTLER_PPT0, + PPT_THROTTLER_PPT1, + PPT_THROTTLER_PPT2, + PPT_THROTTLER_PPT3, + PPT_THROTTLER_COUNT +} PPT_THROTTLER_e; + +typedef enum { + TEMP_EDGE, + TEMP_HOTSPOT, + TEMP_HOTSPOT_GFX, + TEMP_HOTSPOT_SOC, + TEMP_MEM, + TEMP_VR_GFX, + TEMP_VR_SOC, + TEMP_VR_MEM0, + TEMP_VR_MEM1, + TEMP_LIQUID0, + TEMP_LIQUID1, + TEMP_PLX, + TEMP_COUNT, +} TEMP_e; + +typedef enum { + TDC_THROTTLER_GFX, + TDC_THROTTLER_SOC, + TDC_THROTTLER_COUNT +} TDC_THROTTLER_e; + +typedef enum { + SVI_PLANE_VDD_GFX, + SVI_PLANE_VDD_SOC, + SVI_PLANE_VDDCI_MEM, + SVI_PLANE_VDDIO_MEM, + SVI_PLANE_COUNT, +} SVI_PLANE_e; + +typedef enum { + PMFW_VOLT_PLANE_GFX, + PMFW_VOLT_PLANE_SOC, + PMFW_VOLT_PLANE_COUNT +} PMFW_VOLT_PLANE_e; + +typedef enum { + CUSTOMER_VARIANT_ROW, + CUSTOMER_VARIANT_FALCON, + CUSTOMER_VARIANT_COUNT, +} CUSTOMER_VARIANT_e; + +typedef enum { + POWER_SOURCE_AC, + POWER_SOURCE_DC, + POWER_SOURCE_COUNT, +} POWER_SOURCE_e; + +typedef enum { + MEM_VENDOR_PLACEHOLDER0, // 0 + MEM_VENDOR_SAMSUNG, // 1 + MEM_VENDOR_INFINEON, // 2 + MEM_VENDOR_ELPIDA, // 3 + MEM_VENDOR_ETRON, // 4 + MEM_VENDOR_NANYA, // 5 + MEM_VENDOR_HYNIX, // 6 + MEM_VENDOR_MOSEL, // 7 + MEM_VENDOR_WINBOND, // 8 + MEM_VENDOR_ESMT, // 9 + MEM_VENDOR_PLACEHOLDER1, // 10 + MEM_VENDOR_PLACEHOLDER2, // 11 + MEM_VENDOR_PLACEHOLDER3, // 12 + MEM_VENDOR_PLACEHOLDER4, // 13 + MEM_VENDOR_PLACEHOLDER5, // 14 + MEM_VENDOR_MICRON, // 15 + MEM_VENDOR_COUNT, +} MEM_VENDOR_e; + +typedef enum { + PP_GRTAVFS_HW_CPO_CTL_ZONE0, + PP_GRTAVFS_HW_CPO_CTL_ZONE1, + PP_GRTAVFS_HW_CPO_CTL_ZONE2, + PP_GRTAVFS_HW_CPO_CTL_ZONE3, + PP_GRTAVFS_HW_CPO_CTL_ZONE4, + PP_GRTAVFS_HW_CPO_EN_0_31_ZONE0, + PP_GRTAVFS_HW_CPO_EN_32_63_ZONE0, + PP_GRTAVFS_HW_CPO_EN_0_31_ZONE1, + PP_GRTAVFS_HW_CPO_EN_32_63_ZONE1, + PP_GRTAVFS_HW_CPO_EN_0_31_ZONE2, + PP_GRTAVFS_HW_CPO_EN_32_63_ZONE2, + PP_GRTAVFS_HW_CPO_EN_0_31_ZONE3, + PP_GRTAVFS_HW_CPO_EN_32_63_ZONE3, + PP_GRTAVFS_HW_CPO_EN_0_31_ZONE4, + PP_GRTAVFS_HW_CPO_EN_32_63_ZONE4, + PP_GRTAVFS_HW_ZONE0_VF, + PP_GRTAVFS_HW_ZONE1_VF1, + PP_GRTAVFS_HW_ZONE2_VF2, + PP_GRTAVFS_HW_ZONE3_VF3, + PP_GRTAVFS_HW_VOLTAGE_GB, + PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE0, + PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE1, + PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE2, + PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE3, + PP_GRTAVFS_HW_CPOSCALINGCTRL_ZONE4, + PP_GRTAVFS_HW_RESERVED_0, + PP_GRTAVFS_HW_RESERVED_1, + PP_GRTAVFS_HW_RESERVED_2, + PP_GRTAVFS_HW_RESERVED_3, + PP_GRTAVFS_HW_RESERVED_4, + PP_GRTAVFS_HW_RESERVED_5, + PP_GRTAVFS_HW_RESERVED_6, + PP_GRTAVFS_HW_FUSE_COUNT, +} PP_GRTAVFS_HW_FUSE_e; + +typedef enum { + PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_HOT_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z1_COLD_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_HOT_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z2_COLD_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_HOT_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z3_COLD_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_HOT_T0, + PP_GRTAVFS_FW_COMMON_PPVMIN_Z4_COLD_T0, + PP_GRTAVFS_FW_COMMON_SRAM_RM_Z0, + PP_GRTAVFS_FW_COMMON_SRAM_RM_Z1, + PP_GRTAVFS_FW_COMMON_SRAM_RM_Z2, + PP_GRTAVFS_FW_COMMON_SRAM_RM_Z3, + PP_GRTAVFS_FW_COMMON_SRAM_RM_Z4, + PP_GRTAVFS_FW_COMMON_FUSE_COUNT, +} PP_GRTAVFS_FW_COMMON_FUSE_e; + +typedef enum { + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_NEG_1, + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_0, + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_1, + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_2, + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_3, + PP_GRTAVFS_FW_SEP_FUSE_GB1_PWL_VOLTAGE_4, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_NEG_1, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_0, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_1, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_2, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_3, + PP_GRTAVFS_FW_SEP_FUSE_GB2_PWL_VOLTAGE_4, + PP_GRTAVFS_FW_SEP_FUSE_VF_NEG_1_FREQUENCY, + PP_GRTAVFS_FW_SEP_FUSE_VF4_FREQUENCY, + PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_0, + PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_1, + PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_2, + PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_3, + PP_GRTAVFS_FW_SEP_FUSE_FREQUENCY_TO_COUNT_SCALER_4, + PP_GRTAVFS_FW_SEP_FUSE_COUNT, +} PP_GRTAVFS_FW_SEP_FUSE_e; + +#define PP_NUM_RTAVFS_PWL_ZONES 5 + + +// VBIOS or PPLIB configures telemetry slope and offset. Only slope expected to be set for SVI3 +// Slope Q1.7, Offset Q1.2 +typedef struct { + int8_t Offset; // in Amps + uint8_t Padding; + uint16_t MaxCurrent; // in Amps +} SviTelemetryScale_t; + +#define PP_NUM_OD_VF_CURVE_POINTS PP_NUM_RTAVFS_PWL_ZONES + 1 + +#define PP_OD_FEATURE_GFX_VF_CURVE_BIT 0 +#define PP_OD_FEATURE_GFX_VMAX_BIT 1 +#define PP_OD_FEATURE_SOC_VMAX_BIT 2 +#define PP_OD_FEATURE_PPT_BIT 3 +#define PP_OD_FEATURE_FAN_CURVE_BIT 4 +#define PP_OD_FEATURE_FAN_LEGACY_BIT 5 +#define PP_OD_FEATURE_FULL_CTRL_BIT 6 +#define PP_OD_FEATURE_TDC_BIT 7 +#define PP_OD_FEATURE_GFXCLK_BIT 8 +#define PP_OD_FEATURE_UCLK_BIT 9 +#define PP_OD_FEATURE_FCLK_BIT 10 +#define PP_OD_FEATURE_ZERO_FAN_BIT 11 +#define PP_OD_FEATURE_TEMPERATURE_BIT 12 +#define PP_OD_FEATURE_EDC_BIT 13 +#define PP_OD_FEATURE_COUNT 14 + +typedef enum { + PP_OD_POWER_FEATURE_ALWAYS_ENABLED, + PP_OD_POWER_FEATURE_DISABLED_WHILE_GAMING, + PP_OD_POWER_FEATURE_ALWAYS_DISABLED, +} PP_OD_POWER_FEATURE_e; + +typedef enum { + FAN_MODE_AUTO = 0, + FAN_MODE_MANUAL_LINEAR, +} FanMode_e; + +typedef enum { + OD_NO_ERROR, + OD_REQUEST_ADVANCED_NOT_SUPPORTED, + OD_UNSUPPORTED_FEATURE, + OD_INVALID_FEATURE_COMBO_ERROR, + OD_GFXCLK_VF_CURVE_OFFSET_ERROR, + OD_VDD_GFX_VMAX_ERROR, + OD_VDD_SOC_VMAX_ERROR, + OD_PPT_ERROR, + OD_FAN_MIN_PWM_ERROR, + OD_FAN_ACOUSTIC_TARGET_ERROR, + OD_FAN_ACOUSTIC_LIMIT_ERROR, + OD_FAN_TARGET_TEMP_ERROR, + OD_FAN_ZERO_RPM_STOP_TEMP_ERROR, + OD_FAN_CURVE_PWM_ERROR, + OD_FAN_CURVE_TEMP_ERROR, + OD_FULL_CTRL_GFXCLK_ERROR, + OD_FULL_CTRL_UCLK_ERROR, + OD_FULL_CTRL_FCLK_ERROR, + OD_FULL_CTRL_VDD_GFX_ERROR, + OD_FULL_CTRL_VDD_SOC_ERROR, + OD_TDC_ERROR, + OD_GFXCLK_ERROR, + OD_UCLK_ERROR, + OD_FCLK_ERROR, + OD_OP_TEMP_ERROR, + OD_OP_GFX_EDC_ERROR, + OD_OP_GFX_PCC_ERROR, + OD_POWER_FEATURE_CTRL_ERROR, +} OD_FAIL_e; + +typedef struct { + uint32_t FeatureCtrlMask; + + //Voltage control + int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS]; + + uint16_t VddGfxVmax; // in mV + uint16_t VddSocVmax; + + uint8_t IdlePwrSavingFeaturesCtrl; + uint8_t RuntimePwrSavingFeaturesCtrl; + uint16_t Padding; + + //Frequency changes + int16_t GfxclkFmin; // MHz + int16_t GfxclkFmax; // MHz + uint16_t UclkFmin; // MHz + uint16_t UclkFmax; // MHz + uint16_t FclkFmin; + uint16_t FclkFmax; + + //PPT + int16_t Ppt; // % + int16_t Tdc; + + //Fan control + uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; + uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; + uint16_t FanMinimumPwm; + uint16_t AcousticTargetRpmThreshold; + uint16_t AcousticLimitRpmThreshold; + uint16_t FanTargetTemperature; // Degree Celcius + uint8_t FanZeroRpmEnable; + uint8_t FanZeroRpmStopTemp; + uint8_t FanMode; + uint8_t MaxOpTemp; + + uint8_t AdvancedOdModeEnabled; + uint8_t Padding1[3]; + + uint16_t GfxVoltageFullCtrlMode; + uint16_t SocVoltageFullCtrlMode; + uint16_t GfxclkFullCtrlMode; + uint16_t UclkFullCtrlMode; + uint16_t FclkFullCtrlMode; + uint16_t Padding2; + + int16_t GfxEdc; + int16_t GfxPccLimitControl; + + uint32_t Spare[10]; + uint32_t MmHubPadding[8]; // SMU internal use. Adding here instead of external as a workaround +} OverDriveTable_t; + +typedef struct { + OverDriveTable_t OverDriveTable; + +} OverDriveTableExternal_t; + +typedef struct { + uint32_t FeatureCtrlMask; + + //Gfx Vf Curve + int16_t VoltageOffsetPerZoneBoundary[PP_NUM_OD_VF_CURVE_POINTS]; + //gfx Vmax + uint16_t VddGfxVmax; // in mV + //soc Vmax + uint16_t VddSocVmax; + + //gfxclk + int16_t GfxclkFmin; // MHz + int16_t GfxclkFmax; // MHz + //uclk + uint16_t UclkFmin; // MHz + uint16_t UclkFmax; // MHz + //fclk + uint16_t FclkFmin; + uint16_t FclkFmax; + + //PPT + int16_t Ppt; // % + //TDC + int16_t Tdc; + + //Fan Curve + uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; + uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; + //Fan Legacy + uint16_t FanMinimumPwm; + uint16_t AcousticTargetRpmThreshold; + uint16_t AcousticLimitRpmThreshold; + uint16_t FanTargetTemperature; // Degree Celcius + //zero fan + uint8_t FanZeroRpmEnable; + //temperature + uint8_t MaxOpTemp; + uint8_t Padding[2]; + + //Full Ctrl + uint16_t GfxVoltageFullCtrlMode; + uint16_t SocVoltageFullCtrlMode; + uint16_t GfxclkFullCtrlMode; + uint16_t UclkFullCtrlMode; + uint16_t FclkFullCtrlMode; + //EDC + int16_t GfxEdc; + int16_t GfxPccLimitControl; + int16_t Padding1; + + uint32_t Spare[5]; +} OverDriveLimits_t; + +typedef enum { + BOARD_GPIO_SMUIO_0, + BOARD_GPIO_SMUIO_1, + BOARD_GPIO_SMUIO_2, + BOARD_GPIO_SMUIO_3, + BOARD_GPIO_SMUIO_4, + BOARD_GPIO_SMUIO_5, + BOARD_GPIO_SMUIO_6, + BOARD_GPIO_SMUIO_7, + BOARD_GPIO_SMUIO_8, + BOARD_GPIO_SMUIO_9, + BOARD_GPIO_SMUIO_10, + BOARD_GPIO_SMUIO_11, + BOARD_GPIO_SMUIO_12, + BOARD_GPIO_SMUIO_13, + BOARD_GPIO_SMUIO_14, + BOARD_GPIO_SMUIO_15, + BOARD_GPIO_SMUIO_16, + BOARD_GPIO_SMUIO_17, + BOARD_GPIO_SMUIO_18, + BOARD_GPIO_SMUIO_19, + BOARD_GPIO_SMUIO_20, + BOARD_GPIO_SMUIO_21, + BOARD_GPIO_SMUIO_22, + BOARD_GPIO_SMUIO_23, + BOARD_GPIO_SMUIO_24, + BOARD_GPIO_SMUIO_25, + BOARD_GPIO_SMUIO_26, + BOARD_GPIO_SMUIO_27, + BOARD_GPIO_SMUIO_28, + BOARD_GPIO_SMUIO_29, + BOARD_GPIO_SMUIO_30, + BOARD_GPIO_SMUIO_31, + MAX_BOARD_GPIO_SMUIO_NUM, + BOARD_GPIO_DC_GEN_A, + BOARD_GPIO_DC_GEN_B, + BOARD_GPIO_DC_GEN_C, + BOARD_GPIO_DC_GEN_D, + BOARD_GPIO_DC_GEN_E, + BOARD_GPIO_DC_GEN_F, + BOARD_GPIO_DC_GEN_G, + BOARD_GPIO_DC_GENLK_CLK, + BOARD_GPIO_DC_GENLK_VSYNC, + BOARD_GPIO_DC_SWAPLOCK_A, + BOARD_GPIO_DC_SWAPLOCK_B, + MAX_BOARD_DC_GPIO_NUM, + BOARD_GPIO_LV_EN, +} BOARD_GPIO_TYPE_e; + +#define INVALID_BOARD_GPIO 0xFF + + +typedef struct { + //PLL 0 + uint16_t InitImuClk; + uint16_t InitSocclk; + uint16_t InitMpioclk; + uint16_t InitSmnclk; + //PLL 1 + uint16_t InitDispClk; + uint16_t InitDppClk; + uint16_t InitDprefclk; + uint16_t InitDcfclk; + uint16_t InitDtbclk; + uint16_t InitDbguSocClk; + //PLL 2 + uint16_t InitGfxclk_bypass; + uint16_t InitMp1clk; + uint16_t InitLclk; + uint16_t InitDbguBacoClk; + uint16_t InitBaco400clk; + uint16_t InitBaco1200clk_bypass; + uint16_t InitBaco700clk_bypass; + uint16_t InitBaco500clk; + // PLL 3 + uint16_t InitDclk0; + uint16_t InitVclk0; + // PLL 4 + uint16_t InitFclk; + uint16_t Padding1; + // PLL 5 + //UCLK clocks, assumed all UCLK instances will be the same. + uint8_t InitUclkLevel; // =0,1,2,3,4,5 frequency from FreqTableUclk + + uint8_t Padding[3]; + + uint32_t InitVcoFreqPll0; //smu_socclk_t + uint32_t InitVcoFreqPll1; //smu_displayclk_t + uint32_t InitVcoFreqPll2; //smu_nbioclk_t + uint32_t InitVcoFreqPll3; //smu_vcnclk_t + uint32_t InitVcoFreqPll4; //smu_fclk_t + uint32_t InitVcoFreqPll5; //smu_uclk_01_t + uint32_t InitVcoFreqPll6; //smu_uclk_23_t + uint32_t InitVcoFreqPll7; //smu_uclk_45_t + uint32_t InitVcoFreqPll8; //smu_uclk_67_t + + //encoding will be SVI3 + uint16_t InitGfx; // In mV(Q2) , should be 0? + uint16_t InitSoc; // In mV(Q2) + uint16_t InitVddIoMem; // In mV(Q2) MemVdd + uint16_t InitVddCiMem; // In mV(Q2) VMemP + + //uint16_t Padding2; + + uint32_t Spare[8]; +} BootValues_t; + +typedef struct { + uint16_t Power[PPT_THROTTLER_COUNT][POWER_SOURCE_COUNT]; // Watts + uint16_t Tdc[TDC_THROTTLER_COUNT]; // Amps + + uint16_t Temperature[TEMP_COUNT]; // Celsius + + uint8_t PwmLimitMin; + uint8_t PwmLimitMax; + uint8_t FanTargetTemperature; + uint8_t Spare1[1]; + + uint16_t AcousticTargetRpmThresholdMin; + uint16_t AcousticTargetRpmThresholdMax; + + uint16_t AcousticLimitRpmThresholdMin; + uint16_t AcousticLimitRpmThresholdMax; + + uint16_t PccLimitMin; + uint16_t PccLimitMax; + + uint16_t FanStopTempMin; + uint16_t FanStopTempMax; + uint16_t FanStartTempMin; + uint16_t FanStartTempMax; + + uint16_t PowerMinPpt0[POWER_SOURCE_COUNT]; + uint32_t Spare[11]; +} MsgLimits_t; + +typedef struct { + uint16_t BaseClockAc; + uint16_t GameClockAc; + uint16_t BoostClockAc; + uint16_t BaseClockDc; + uint16_t GameClockDc; + uint16_t BoostClockDc; + + uint32_t Reserved[4]; +} DriverReportedClocks_t; + +typedef struct { + uint8_t DcBtcEnabled; + uint8_t Padding[3]; + + uint16_t DcTol; // mV Q2 + uint16_t DcBtcGb; // mV Q2 + + uint16_t DcBtcMin; // mV Q2 + uint16_t DcBtcMax; // mV Q2 + + LinearInt_t DcBtcGbScalar; +} AvfsDcBtcParams_t; + +typedef struct { + uint16_t AvfsTemp[AVFS_TEMP_COUNT]; //in degrees C + uint16_t VftFMin; // in MHz + uint16_t VInversion; // in mV Q2 + QuadraticInt_t qVft[AVFS_TEMP_COUNT]; + QuadraticInt_t qAvfsGb; + QuadraticInt_t qAvfsGb2; +} AvfsFuseOverride_t; + +//all settings maintained by PFE team +typedef struct { + uint8_t Version; + uint8_t Spare8[3]; + // SECTION: Feature Control + uint32_t FeaturesToRun[NUM_FEATURES / 32]; // Features that PMFW will attempt to enable. Use FEATURE_*_BIT as mapping + // SECTION: FW DSTATE Settings + uint32_t FwDStateMask; // See FW_DSTATE_*_BIT for mapping + // SECTION: Advanced Options + uint32_t DebugOverrides; + + uint32_t Spare[2]; +} PFE_Settings_t; + +typedef struct { + // SECTION: Version + uint32_t Version; // should be unique to each SKU(i.e if any value changes in below structure then this value must be different) + + // SECTION: Miscellaneous Configuration + uint8_t TotalPowerConfig; // Determines how PMFW calculates the power. Use defines from PwrConfig_e + uint8_t CustomerVariant; //To specify if this PPTable is intended for a particular customer. Use defines from CUSTOMER_VARIANT_e + uint8_t MemoryTemperatureTypeMask; // Bit mapping indicating which methods of memory temperature reading are enabled. Use defines from MEM_TEMP_*BIT + uint8_t SmartShiftVersion; // Determine what SmartShift feature version is supported Use defines from SMARTSHIFT_VERSION_e + + // SECTION: Infrastructure Limits + uint8_t SocketPowerLimitSpare[10]; + + //if set to 1, SocketPowerLimitAc and SocketPowerLimitDc will be interpreted as legacy programs(i.e absolute power). If 0, all except index 0 will be scalars + //relative index 0 + uint8_t EnableLegacyPptLimit; + uint8_t UseInputTelemetry; //applicable to SVI3 only and only to be set if VRs support + + uint8_t SmartShiftMinReportedPptinDcs; //minimum possible active power consumption for this SKU. Used for SmartShift power reporting + + uint8_t PaddingPpt[7]; + + uint16_t HwCtfTempLimit; // In degrees Celsius. Temperature above which HW will trigger CTF. Consumed by VBIOS only + + uint16_t PaddingInfra; + + // Per year normalized Vmax state failure rates (sum of the two domains divided by life time in years) + uint32_t FitControllerFailureRateLimit; //in IEEE float + //Expected GFX Duty Cycle at Vmax. + uint32_t FitControllerGfxDutyCycle; // in IEEE float + //Expected SOC Duty Cycle at Vmax. + uint32_t FitControllerSocDutyCycle; // in IEEE float + + //This offset will be deducted from the controller output to before it goes through the SOC Vset limiter block. + uint32_t FitControllerSocOffset; //in IEEE float + + uint32_t GfxApccPlusResidencyLimit; // Percentage value. Used by APCC+ controller to control PCC residency to some value + + // SECTION: Throttler settings + uint32_t ThrottlerControlMask; // See THROTTLER_*_BIT for mapping + + + // SECTION: Voltage Control Parameters + uint16_t UlvVoltageOffset[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2). ULV offset used in either GFX_ULV or SOC_ULV(part of FW_DSTATE) + + uint8_t Padding[2]; + uint16_t DeepUlvVoltageOffsetSoc; // In mV(Q2) Long Idle Vmin (deep ULV), for VDD_SOC as part of FW_DSTATE + + // Voltage Limits + uint16_t DefaultMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage without FIT controller enabled + uint16_t BoostMaxVoltage[PMFW_VOLT_PLANE_COUNT]; // In mV(Q2) Maximum voltage with FIT controller enabled + + //Vmin Optimizations + int16_t VminTempHystersis[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature hysteresis for switching between low/high temperature values for Vmin + int16_t VminTempThreshold[PMFW_VOLT_PLANE_COUNT]; // Celsius Temperature threshold for switching between low/high temperature values for Vmin + uint16_t Vmin_Hot_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at hot. + uint16_t Vmin_Cold_T0[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Initial (pre-aging) Vset to be used at cold. + uint16_t Vmin_Hot_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at hot. + uint16_t Vmin_Cold_Eol[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) End-of-life Vset to be used at cold. + uint16_t Vmin_Aging_Offset[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Worst-case aging margin + uint16_t Spare_Vmin_Plat_Offset_Hot[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Hot + uint16_t Spare_Vmin_Plat_Offset_Cold[PMFW_VOLT_PLANE_COUNT]; //In mV(Q2) Platform offset apply to T0 Cold + + //This is a fixed/minimum VMIN aging degradation offset which is applied at T0. This reflects the minimum amount of aging already accounted for. + uint16_t VcBtcFixedVminAgingOffset[PMFW_VOLT_PLANE_COUNT]; + //Linear offset or GB term to account for mis-correlation between PSM and Vmin shift trends across parts. + uint16_t VcBtcVmin2PsmDegrationGb[PMFW_VOLT_PLANE_COUNT]; + //Scalar coefficient of the PSM aging degradation function + uint32_t VcBtcPsmA[PMFW_VOLT_PLANE_COUNT]; // A_PSM + //Exponential coefficient of the PSM aging degradation function + uint32_t VcBtcPsmB[PMFW_VOLT_PLANE_COUNT]; // B_PSM + //Scalar coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold. + uint32_t VcBtcVminA[PMFW_VOLT_PLANE_COUNT]; // A_VMIN + //Exponential coefficient of the VMIN aging degradation function. Specified as worst case between hot and cold. + uint32_t VcBtcVminB[PMFW_VOLT_PLANE_COUNT]; // B_VMIN + + uint8_t PerPartVminEnabled[PMFW_VOLT_PLANE_COUNT]; + uint8_t VcBtcEnabled[PMFW_VOLT_PLANE_COUNT]; + + uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms + uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms + + QuadraticInt_t Gfx_Vmin_droop; + QuadraticInt_t Soc_Vmin_droop; + uint32_t SpareVmin[6]; + + //SECTION: DPM Configuration 1 + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableShadowUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz + uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz + + uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz + + uint16_t GfxclkAibFmax; + uint16_t GfxclkFreqCap; + + //GFX Idle Power Settings + uint16_t GfxclkFgfxoffEntry; // Entry in RLC stage (PLL), in Mhz + uint16_t GfxclkFgfxoffExitImu; // Exit/Entry in IMU stage (BYPASS), in Mhz + uint16_t GfxclkFgfxoffExitRlc; // Exit in RLC stage (PLL), in Mhz + uint16_t GfxclkThrottleClock; //Used primarily in DCS + uint8_t EnableGfxPowerStagesGpio; //Genlk_vsync GPIO flag used to control gfx power stages + uint8_t GfxIdlePadding; + + uint8_t SmsRepairWRCKClkDivEn; + uint8_t SmsRepairWRCKClkDivVal; + uint8_t GfxOffEntryEarlyMGCGEn; + uint8_t GfxOffEntryForceCGCGEn; + uint8_t GfxOffEntryForceCGCGDelayEn; + uint8_t GfxOffEntryForceCGCGDelayVal; // in microseconds + + uint16_t GfxclkFreqGfxUlv; // in MHz + uint8_t GfxIdlePadding2[2]; + uint32_t GfxOffEntryHysteresis; //For RLC to count after it enters CGCG, and before triggers GFXOFF entry + uint32_t GfxoffSpare[15]; + + // DFLL + uint16_t DfllMstrOscConfigA; //Used for voltage sensitivity slope tuning: 0 = (en_leaker << 9) | (en_vint1_reduce << 8) | (gain_code << 6) | (bias_code << 3) | (vint1_code << 1) | en_bias + uint16_t DfllSlvOscConfigA; //Used for voltage sensitivity slope tuning: 0 = (en_leaker << 9) | (en_vint1_reduce << 8) | (gain_code << 6) | (bias_code << 3) | (vint1_code << 1) | en_bias + uint32_t DfllBtcMasterScalerM; + int32_t DfllBtcMasterScalerB; + uint32_t DfllBtcSlaveScalerM; + int32_t DfllBtcSlaveScalerB; + + uint32_t DfllPccAsWaitCtrl; //GDFLL_AS_WAIT_CTRL_PCC register value to be passed to RLC msg + uint32_t DfllPccAsStepCtrl; //GDFLL_AS_STEP_CTRL_PCC register value to be passed to RLC msg + uint32_t GfxDfllSpare[9]; + + // DVO + uint32_t DvoPsmDownThresholdVoltage; //Voltage float + uint32_t DvoPsmUpThresholdVoltage; //Voltage float + uint32_t DvoFmaxLowScaler; //Unitless float + + // GFX DCS + uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase + uint16_t PaddingDcs; + + uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase + uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch. + + uint32_t DcsMinCreditAccum; //Min amount of positive credit accumulation before waking GFX up as part of DCS. + + uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase. + uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin. + + uint32_t DcsPfGfxFopt; //Default to GFX FMIN + uint32_t DcsPfUclkFopt; //Default to UCLK FMIN + + uint8_t FoptEnabled; + uint8_t DcsSpare2[3]; + uint32_t DcsFoptM; //Tuning paramters to shift Fopt calculation, IEEE754 float + uint32_t DcsFoptB; //Tuning paramters to shift Fopt calculation, IEEE754 float + uint32_t DcsSpare[9]; + + // UCLK section + uint8_t UseStrobeModeOptimizations; //Set to indicate that FW should use strobe mode optimizations + uint8_t PaddingMem[3]; + + uint8_t UclkDpmPstates [NUM_UCLK_DPM_LEVELS]; // 6 Primary SW DPM states (6 + 6 Shadow) + uint8_t UclkDpmShadowPstates [NUM_UCLK_DPM_LEVELS]; // 6 Shadow SW DPM states (6 + 6 Shadow) + uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 + uint8_t FreqTableShadowUclkDiv [NUM_UCLK_DPM_LEVELS]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 + uint16_t MemVmempVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + uint16_t MemVddioVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + uint16_t DalDcModeMaxUclkFreq; + uint8_t PaddingsMem[2]; + //FCLK Section + uint16_t FclkDpmDisallowPstateFreq; //Frequency which FW will target when indicated that display config cannot support P-state. Set to 0 use FW calculated value + uint16_t PaddingFclk; + + // Link DPM Settings + uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 4:PciE-gen5 + uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 + uint16_t LclkFreq[NUM_LINK_LEVELS]; + + // SECTION: VDD_GFX AVFS + uint8_t OverrideGfxAvfsFuses; + uint8_t GfxAvfsPadding[3]; + + uint32_t SocHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //new added for Soc domain + uint32_t GfxL2HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; //see fusedoc for encoding + //uint32_t GfxSeHwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; + uint32_t spare_HwRtAvfsFuses[PP_GRTAVFS_HW_FUSE_COUNT]; + + uint32_t SocCommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT]; + uint32_t GfxCommonRtAvfs[PP_GRTAVFS_FW_COMMON_FUSE_COUNT]; + + uint32_t SocFwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT]; + uint32_t GfxL2FwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT]; + //uint32_t GfxSeFwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT]; + uint32_t spare_FwRtAvfsFuses[PP_GRTAVFS_FW_SEP_FUSE_COUNT]; + + uint32_t Soc_Droop_PWL_F[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Soc_Droop_PWL_a[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Soc_Droop_PWL_b[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Soc_Droop_PWL_c[PP_NUM_RTAVFS_PWL_ZONES]; + + uint32_t Gfx_Droop_PWL_F[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Gfx_Droop_PWL_a[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Gfx_Droop_PWL_b[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Gfx_Droop_PWL_c[PP_NUM_RTAVFS_PWL_ZONES]; + + uint32_t Gfx_Static_PWL_Offset[PP_NUM_RTAVFS_PWL_ZONES]; + uint32_t Soc_Static_PWL_Offset[PP_NUM_RTAVFS_PWL_ZONES]; + + uint32_t dGbV_dT_vmin; + uint32_t dGbV_dT_vmax; + + //Unused: PMFW-9370 + uint32_t V2F_vmin_range_low; + uint32_t V2F_vmin_range_high; + uint32_t V2F_vmax_range_low; + uint32_t V2F_vmax_range_high; + + AvfsDcBtcParams_t DcBtcGfxParams; + QuadraticInt_t SSCurve_GFX; + uint32_t GfxAvfsSpare[29]; + + //SECTION: VDD_SOC AVFS + uint8_t OverrideSocAvfsFuses; + uint8_t MinSocAvfsRevision; + uint8_t SocAvfsPadding[2]; + + AvfsFuseOverride_t SocAvfsFuseOverride[AVFS_D_COUNT]; + + DroopInt_t dBtcGbSoc[AVFS_D_COUNT]; // GHz->V BtcGb + + LinearInt_t qAgingGb[AVFS_D_COUNT]; // GHz->V + + QuadraticInt_t qStaticVoltageOffset[AVFS_D_COUNT]; // GHz->V + + AvfsDcBtcParams_t DcBtcSocParams[AVFS_D_COUNT]; + + QuadraticInt_t SSCurve_SOC; + uint32_t SocAvfsSpare[29]; + + //SECTION: Boot clock and voltage values + BootValues_t BootValues; + + //SECTION: Driver Reported Clocks + DriverReportedClocks_t DriverReportedClocks; + + //SECTION: Message Limits + MsgLimits_t MsgLimits; + + //SECTION: OverDrive Limits + OverDriveLimits_t OverDriveLimitsBasicMin; + OverDriveLimits_t OverDriveLimitsBasicMax; + OverDriveLimits_t OverDriveLimitsAdvancedMin; + OverDriveLimits_t OverDriveLimitsAdvancedMax; + + // Section: Total Board Power idle vs active coefficients + uint8_t TotalBoardPowerSupport; + uint8_t TotalBoardPowerPadding[1]; + uint16_t TotalBoardPowerRoc; + + //PMFW-11158 + QuadraticInt_t qFeffCoeffGameClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBaseClock[POWER_SOURCE_COUNT]; + QuadraticInt_t qFeffCoeffBoostClock[POWER_SOURCE_COUNT]; + + // APT GFX to UCLK mapping + int32_t AptUclkGfxclkLookup[POWER_SOURCE_COUNT][6]; + uint32_t AptUclkGfxclkLookupHyst[POWER_SOURCE_COUNT][6]; + uint32_t AptPadding; + + // Xvmin didt + QuadraticInt_t GfxXvminDidtDroopThresh; + uint32_t GfxXvminDidtResetDDWait; + uint32_t GfxXvminDidtClkStopWait; + uint32_t GfxXvminDidtFcsStepCtrl; + uint32_t GfxXvminDidtFcsWaitCtrl; + + // PSM based didt controller + uint32_t PsmModeEnabled; //0: all disabled 1: static mode only 2: dynamic mode only 3:static + dynamic mode + uint32_t P2v_a; // floating point in U32 format + uint32_t P2v_b; + uint32_t P2v_c; + uint32_t T2p_a; + uint32_t T2p_b; + uint32_t T2p_c; + uint32_t P2vTemp; + QuadraticInt_t PsmDidtStaticSettings; + QuadraticInt_t PsmDidtDynamicSettings; + uint8_t PsmDidtAvgDiv; + uint8_t PsmDidtForceStall; + uint16_t PsmDidtReleaseTimer; + uint32_t PsmDidtStallPattern; //Will be written to both pattern 1 and didt_static_level_prog + // CAC EDC + uint32_t Leakage_C0; // in IEEE float + uint32_t Leakage_C1; // in IEEE float + uint32_t Leakage_C2; // in IEEE float + uint32_t Leakage_C3; // in IEEE float + uint32_t Leakage_C4; // in IEEE float + uint32_t Leakage_C5; // in IEEE float + uint32_t GFX_CLK_SCALAR; // in IEEE float + uint32_t GFX_CLK_INTERCEPT; // in IEEE float + uint32_t GFX_CAC_M; // in IEEE float + uint32_t GFX_CAC_B; // in IEEE float + uint32_t VDD_GFX_CurrentLimitGuardband; // in IEEE float + uint32_t DynToTotalCacScalar; // in IEEE + // GFX EDC XVMIN + uint32_t XVmin_Gfx_EdcThreshScalar; + uint32_t XVmin_Gfx_EdcEnableFreq; + uint32_t XVmin_Gfx_EdcPccAsStepCtrl; + uint32_t XVmin_Gfx_EdcPccAsWaitCtrl; + uint16_t XVmin_Gfx_EdcThreshold; + uint16_t XVmin_Gfx_EdcFiltHysWaitCtrl; + // SOC EDC XVMIN + uint32_t XVmin_Soc_EdcThreshScalar; + uint32_t XVmin_Soc_EdcEnableFreq; + uint32_t XVmin_Soc_EdcThreshold; // LPF: number of cycles Xvmin_trig_filt will react. + uint16_t XVmin_Soc_EdcStepUpTime; // 10 bit, refclk count to step up throttle when PCC remains asserted. + uint16_t XVmin_Soc_EdcStepDownTime;// 10 bit, refclk count to step down throttle when PCC remains asserted. + uint8_t XVmin_Soc_EdcInitPccStep; // 3 bit, First Pcc Step number that will applied when PCC asserts. + uint8_t PaddingSocEdc[3]; + + // Fuse Override for SOC and GFX XVMIN + uint8_t GfxXvminFuseOverride; + uint8_t SocXvminFuseOverride; + uint8_t PaddingXvminFuseOverride[2]; + uint8_t GfxXvminFddTempLow; // bit 7: sign, bit 0-6: ABS value + uint8_t GfxXvminFddTempHigh; // bit 7: sign, bit 0-6: ABS value + uint8_t SocXvminFddTempLow; // bit 7: sign, bit 0-6: ABS value + uint8_t SocXvminFddTempHigh; // bit 7: sign, bit 0-6: ABS value + + + uint16_t GfxXvminFddVolt0; // low voltage, in VID + uint16_t GfxXvminFddVolt1; // mid voltage, in VID + uint16_t GfxXvminFddVolt2; // high voltage, in VID + uint16_t SocXvminFddVolt0; // low voltage, in VID + uint16_t SocXvminFddVolt1; // mid voltage, in VID + uint16_t SocXvminFddVolt2; // high voltage, in VID + uint16_t GfxXvminDsFddDsm[6]; // XVMIN DS, same organization with fuse + uint16_t GfxXvminEdcFddDsm[6];// XVMIN GFX EDC, same organization with fuse + uint16_t SocXvminEdcFddDsm[6];// XVMIN SOC EDC, same organization with fuse + + // SECTION: Sku Reserved + uint32_t Spare; + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; +} SkuTable_t; + +typedef struct { + uint8_t SlewRateConditions; + uint8_t LoadLineAdjust; + uint8_t VoutOffset; + uint8_t VidMax; + uint8_t VidMin; + uint8_t TenBitTelEn; + uint8_t SixteenBitTelEn; + uint8_t OcpThresh; + uint8_t OcpWarnThresh; + uint8_t OcpSettings; + uint8_t VrhotThresh; + uint8_t OtpThresh; + uint8_t UvpOvpDeltaRef; + uint8_t PhaseShed; + uint8_t Padding[10]; + uint32_t SettingOverrideMask; +} Svi3RegulatorSettings_t; + +typedef struct { + // SECTION: Version + uint32_t Version; //should be unique to each board type + + // SECTION: I2C Control + I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; + + //SECTION SVI3 Board Parameters + uint8_t SlaveAddrMapping[SVI_PLANE_COUNT]; + uint8_t VrPsiSupport[SVI_PLANE_COUNT]; + + uint32_t Svi3SvcSpeed; + uint8_t EnablePsi6[SVI_PLANE_COUNT]; // only applicable in SVI3 + + // SECTION: Voltage Regulator Settings + Svi3RegulatorSettings_t Svi3RegSettings[SVI_PLANE_COUNT]; + + // SECTION: GPIO Settings + uint8_t LedOffGpio; + uint8_t FanOffGpio; + uint8_t GfxVrPowerStageOffGpio; + + uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching + uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching + uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event + uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event + + uint8_t GthrGpio; // GPIO pin configured for GTHR Event + uint8_t GthrPolarity; // replace GPIO polarity for GTHR + + // LED Display Settings + uint8_t LedPin0; // GPIO number for LedPin[0] + uint8_t LedPin1; // GPIO number for LedPin[1] + uint8_t LedPin2; // GPIO number for LedPin[2] + uint8_t LedEnableMask; + + uint8_t LedPcie; // GPIO number for PCIE results + uint8_t LedError; // GPIO number for Error Cases + uint8_t PaddingLed; + + // SECTION: Clock Spread Spectrum + + // UCLK Spread Spectrum + uint8_t UclkTrainingModeSpreadPercent; // Q4.4 + uint8_t UclkSpreadPadding; + uint16_t UclkSpreadFreq; // kHz + + // UCLK Spread Spectrum + uint8_t UclkSpreadPercent[MEM_VENDOR_COUNT]; + + // DFLL Spread Spectrum + uint8_t GfxclkSpreadEnable; + + // FCLK Spread Spectrum + uint8_t FclkSpreadPercent; // Q4.4 + uint16_t FclkSpreadFreq; // kHz + + // Section: Memory Config + uint8_t DramWidth; // Width of interface to the channel for each DRAM module. See DRAM_BIT_WIDTH_TYPE_e + uint8_t PaddingMem1[7]; + + // SECTION: UMC feature flags + uint8_t HsrEnabled; + uint8_t VddqOffEnabled; + uint8_t PaddingUmcFlags[2]; + + uint32_t PostVoltageSetBacoDelay; // in microseconds. Amount of time FW will wait after power good is established or PSI0 command is issued + uint32_t BacoEntryDelay; // in milliseconds. Amount of time FW will wait to trigger BACO entry after receiving entry notification from OS + + uint8_t FuseWritePowerMuxPresent; + uint8_t FuseWritePadding[3]; + + // SECTION: EDC Params + uint32_t LoadlineGfx; + uint32_t LoadlineSoc; + uint32_t GfxEdcLimit; + uint32_t SocEdcLimit; + + uint32_t RestBoardPower; //power consumed by board that is not captured by the SVI3 input telemetry + uint32_t ConnectorsImpedance; // impedance of the input ATX power connectors + + uint8_t EpcsSens0; //GPIO number for External Power Connector Support Sense0 + uint8_t EpcsSens1; //GPIO Number for External Power Connector Support Sense1 + uint8_t PaddingEpcs[2]; + + // SECTION: Board Reserved + uint32_t BoardSpare[52]; + + // SECTION: Structure Padding + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; +} BoardTable_t; + +typedef struct { + // SECTION: Infrastructure Limits + uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in AC mode. Multiple limits supported + + uint16_t VrTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with VR regulator maximum temperature + + int16_t TotalIdleBoardPowerM; + int16_t TotalIdleBoardPowerB; + int16_t TotalBoardPowerM; + int16_t TotalBoardPowerB; + + uint16_t TemperatureLimit[TEMP_COUNT]; // In degrees Celsius. Temperature limit associated with each input + + // SECTION: Fan Control + uint16_t FanStopTemp[TEMP_COUNT]; //Celsius + uint16_t FanStartTemp[TEMP_COUNT]; //Celsius + + uint16_t FanGain[TEMP_COUNT]; + + uint16_t FanPwmMin; + uint16_t AcousticTargetRpmThreshold; + uint16_t AcousticLimitRpmThreshold; + uint16_t FanMaximumRpm; + uint16_t MGpuAcousticLimitRpmThreshold; + uint16_t FanTargetGfxclk; + uint32_t TempInputSelectMask; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + uint16_t FanPadding; + uint16_t FanTargetTemperature[TEMP_COUNT]; + + // The following are AFC override parameters. Leave at 0 to use FW defaults. + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + uint16_t FwCtfLimit[TEMP_COUNT]; + + uint16_t IntakeTempEnableRPM; + int16_t IntakeTempOffsetTemp; + uint16_t IntakeTempReleaseTemp; + uint16_t IntakeTempHighIntakeAcousticLimit; + + uint16_t IntakeTempAcouticLimitReleaseRate; + int16_t FanAbnormalTempLimitOffset; // FanStalledTempLimitOffset + uint16_t FanStalledTriggerRpm; // + uint16_t FanAbnormalTriggerRpmCoeff; // FanAbnormalTriggerRpm + + uint16_t FanSpare[1]; + uint8_t FanIntakeSensorSupport; + uint8_t FanIntakePadding; + uint32_t FanAmbientPerfBoostThreshold; + uint32_t FanSpare2[12]; + + uint16_t TemperatureLimit_Hynix; // In degrees Celsius. Memory temperature limit associated with Hynix + uint16_t TemperatureLimit_Micron; // In degrees Celsius. Memory temperature limit associated with Micron + uint16_t TemperatureFwCtfLimit_Hynix; + uint16_t TemperatureFwCtfLimit_Micron; + + // SECTION: Board Reserved + uint16_t PlatformTdcLimit[TDC_THROTTLER_COUNT]; // In Amperes. Current limit associated with platform maximum temperature per VR current rail + uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; // In Watts. Power limit that PMFW attempts to control to in DC mode. Multiple limits supported + uint16_t SocketPowerLimitSmartShift2; // In Watts. Power limit used SmartShift + uint16_t CustomSkuSpare16b; + uint32_t CustomSkuSpare32b[10]; + + // SECTION: Structure Padding + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; +} CustomSkuTable_t; + +typedef struct { + PFE_Settings_t PFE_Settings; + SkuTable_t SkuTable; + CustomSkuTable_t CustomSkuTable; + BoardTable_t BoardTable; +} PPTable_t; + +typedef struct { + // Time constant parameters for clock averages in ms + uint16_t GfxclkAverageLpfTau; + uint16_t FclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + uint16_t UclkMaxActivityLpfTau; + uint16_t SocketPowerLpfTau; + uint16_t VcnClkAverageLpfTau; + uint16_t VcnUsageAverageLpfTau; + uint16_t PcieActivityLpTau; +} DriverSmuConfig_t; + +typedef struct { + DriverSmuConfig_t DriverSmuConfig; + + uint32_t Spare[8]; + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} DriverSmuConfigExternal_t; + + +typedef struct { + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDppClk [NUM_DPPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDprefclk [NUM_DPREFCLK_DPM_LEVELS]; // In MHz + uint16_t FreqTableDcfclk [NUM_DCFCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz + + uint16_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz + + uint16_t Padding; + + uint32_t Spare[32]; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use + +} DriverInfoTable_t; + +typedef struct { + uint32_t CurrClock[PPCLK_COUNT]; + + uint16_t AverageGfxclkFrequencyTarget; + uint16_t AverageGfxclkFrequencyPreDs; + uint16_t AverageGfxclkFrequencyPostDs; + uint16_t AverageFclkFrequencyPreDs; + uint16_t AverageFclkFrequencyPostDs; + uint16_t AverageMemclkFrequencyPreDs ; // this is scaled to actual memory clock + uint16_t AverageMemclkFrequencyPostDs ; // this is scaled to actual memory clock + uint16_t AverageVclk0Frequency ; + uint16_t AverageDclk0Frequency ; + uint16_t AverageVclk1Frequency ; + uint16_t AverageDclk1Frequency ; + uint16_t PCIeBusy ; + uint16_t dGPU_W_MAX ; + uint16_t padding ; + + uint32_t MetricsCounter ; + + uint16_t AvgVoltage[SVI_PLANE_COUNT]; + uint16_t AvgCurrent[SVI_PLANE_COUNT]; + + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint16_t Vcn0ActivityPercentage ; + uint16_t Vcn1ActivityPercentage ; + + uint32_t EnergyAccumulator; + uint16_t AverageSocketPower; + uint16_t AverageTotalBoardPower; + + uint16_t AvgTemperature[TEMP_COUNT]; + uint16_t AvgTemperatureFanIntake; + + uint8_t PcieRate ; + uint8_t PcieWidth ; + + uint8_t AvgFanPwm; + uint8_t Padding[1]; + uint16_t AvgFanRpm; + + + uint8_t ThrottlingPercentage[THROTTLER_COUNT]; + uint8_t padding1[3]; + + //metrics for D3hot entry/exit and driver ARM msgs + uint32_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT]; + uint32_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT]; + uint32_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT]; + + uint16_t ApuSTAPMSmartShiftLimit; + uint16_t ApuSTAPMLimit; + uint16_t AvgApuSocketPower; + + uint16_t AverageUclkActivity_MAX; + + uint32_t PublicSerialNumberLower; + uint32_t PublicSerialNumberUpper; + +} SmuMetrics_t; + +typedef struct { + SmuMetrics_t SmuMetrics; + uint32_t Spare[30]; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetricsExternal_t; + +typedef struct { + uint8_t WmSetting; + uint8_t Flags; + uint8_t Padding[2]; + +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WATERMARKS_CLOCK_RANGE = 0, + WATERMARKS_DUMMY_PSTATE, + WATERMARKS_MALL, + WATERMARKS_COUNT, +} WATERMARKS_FLAGS_e; + +typedef struct { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[NUM_WM_RANGES]; +} Watermarks_t; + +typedef struct { + Watermarks_t Watermarks; + uint32_t Spare[16]; + + uint32_t MmHubPadding[8]; // SMU internal use +} WatermarksExternal_t; + +typedef struct { + uint16_t avgPsmCount[76]; + uint16_t minPsmCount[76]; + uint16_t maxPsmCount[76]; + float avgPsmVoltage[76]; + float minPsmVoltage[76]; + float maxPsmVoltage[76]; +} AvfsDebugTable_t; + +typedef struct { + AvfsDebugTable_t AvfsDebugTable; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsDebugTableExternal_t; + + +typedef struct { + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t PaddingGfx; + uint16_t Gfx_MinActiveFreq; // MHz + uint16_t Gfx_BoosterFreq; // MHz + uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Gfx_PD_Data_limit_a; // Q16 + uint32_t Gfx_PD_Data_limit_b; // Q16 + uint32_t Gfx_PD_Data_limit_c; // Q16 + uint32_t Gfx_PD_Data_error_coeff; // Q16 + uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 + + uint8_t Fclk_ActiveHystLimit; + uint8_t Fclk_IdleHystLimit; + uint8_t Fclk_FPS; + uint8_t Fclk_MinActiveFreqType; + uint8_t Fclk_BoosterFreqType; + uint8_t PaddingFclk; + uint16_t Fclk_MinActiveFreq; // MHz + uint16_t Fclk_BoosterFreq; // MHz + uint16_t Fclk_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Fclk_PD_Data_limit_a; // Q16 + uint32_t Fclk_PD_Data_limit_b; // Q16 + uint32_t Fclk_PD_Data_limit_c; // Q16 + uint32_t Fclk_PD_Data_error_coeff; // Q16 + uint32_t Fclk_PD_Data_error_rate_coeff; // Q16 + + uint32_t Mem_UpThreshold_Limit[NUM_UCLK_DPM_LEVELS]; // Q16 + uint8_t Mem_UpHystLimit[NUM_UCLK_DPM_LEVELS]; + uint16_t Mem_DownHystLimit[NUM_UCLK_DPM_LEVELS]; + uint16_t Mem_Fps; + +} DpmActivityMonitorCoeffInt_t; + + +typedef struct { + DpmActivityMonitorCoeffInt_t DpmActivityMonitorCoeffInt; + uint32_t MmHubPadding[8]; // SMU internal use +} DpmActivityMonitorCoeffIntExternal_t; + + + +// Workload bits +#define WORKLOAD_PPLIB_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_WINDOW_3D_BIT 7 +#define WORKLOAD_PPLIB_DIRECT_ML_BIT 8 +#define WORKLOAD_PPLIB_CGVDI_BIT 9 +#define WORKLOAD_PPLIB_COUNT 10 + + +// These defines are used with the following messages: +// SMC_MSG_TransferTableDram2Smu +// SMC_MSG_TransferTableSmu2Dram + +// Table transfer status +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF +#define TABLE_TRANSFER_PENDING 0xAB + +// Table types +#define TABLE_PPTABLE 0 +#define TABLE_COMBO_PPTABLE 1 +#define TABLE_WATERMARKS 2 +#define TABLE_AVFS_PSM_DEBUG 3 +#define TABLE_PMSTATUSLOG 4 +#define TABLE_SMU_METRICS 5 +#define TABLE_DRIVER_SMU_CONFIG 6 +#define TABLE_ACTIVITY_MONITOR_COEFF 7 +#define TABLE_OVERDRIVE 8 +#define TABLE_I2C_COMMANDS 9 +#define TABLE_DRIVER_INFO 10 +#define TABLE_ECCINFO 11 +#define TABLE_CUSTOM_SKUTABLE 12 +#define TABLE_COUNT 13 + +//IH Interupt ID +#define IH_INTERRUPT_ID_TO_DRIVER 0xFE +#define IH_INTERRUPT_CONTEXT_ID_BACO 0x2 +#define IH_INTERRUPT_CONTEXT_ID_AC 0x3 +#define IH_INTERRUPT_CONTEXT_ID_DC 0x4 +#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D0 0x5 +#define IH_INTERRUPT_CONTEXT_ID_AUDIO_D3 0x6 +#define IH_INTERRUPT_CONTEXT_ID_THERMAL_THROTTLING 0x7 +#define IH_INTERRUPT_CONTEXT_ID_FAN_ABNORMAL 0x8 +#define IH_INTERRUPT_CONTEXT_ID_FAN_RECOVERY 0x9 + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h index 5bb7a63c0602..97522c085258 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h @@ -144,6 +144,37 @@ typedef struct { uint32_t MaxGfxClk; } DpmClocks_t; +//Freq in MHz +//Voltage in milli volts with 2 fractional bits +typedef struct { + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + uint32_t VClocks0[NUM_VCN_DPM_LEVELS]; + uint32_t VClocks1[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks0[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks1[NUM_VCN_DPM_LEVELS]; + uint32_t VPEClocks[NUM_VPE_DPM_LEVELS]; + uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS]; + uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS]; + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; + MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS]; + + uint8_t NumDcfClkLevelsEnabled; + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk + uint8_t NumSocClkLevelsEnabled; + uint8_t Vcn0ClkLevelsEnabled; //Applies to both Vclk0 and Dclk0 + uint8_t Vcn1ClkLevelsEnabled; //Applies to both Vclk1 and Dclk1 + uint8_t VpeClkLevelsEnabled; + uint8_t NumMemPstatesEnabled; + uint8_t NumFclkLevelsEnabled; + uint8_t spare; + + uint32_t MinGfxClk; + uint32_t MaxGfxClk; +} DpmClocks_t_v14_0_1; + typedef struct { uint16_t CoreFrequency[16]; //Target core frequency [MHz] uint16_t CorePower[16]; //CAC calculated core power [mW] @@ -224,7 +255,7 @@ typedef enum { #define TABLE_CUSTOM_DPM 2 // Called by Driver #define TABLE_BIOS_GPIO_CONFIG 3 // Called by BIOS #define TABLE_DPMCLOCKS 4 // Called by Driver and VBIOS -#define TABLE_SPARE0 5 // Unused +#define TABLE_MOMENTARY_PM 5 // Called by Tools #define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log #define TABLE_SMU_METRICS 7 // Called by Driver and SMF/PMF #define TABLE_COUNT 8 diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h index 7b812b9994d7..0b3c2f54a343 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_6_pmfw.h @@ -123,7 +123,7 @@ typedef enum { VOLTAGE_GUARDBAND_COUNT } GFX_GUARDBAND_e; -#define SMU_METRICS_TABLE_VERSION 0xB +#define SMU_METRICS_TABLE_VERSION 0xC typedef struct __attribute__((packed, aligned(4))) { uint32_t AccumulationCounter; @@ -223,6 +223,10 @@ typedef struct __attribute__((packed, aligned(4))) { // VCN/JPEG ACTIVITY uint32_t VcnBusy[4]; uint32_t JpegBusy[32]; + + // PCIE LINK Speed and width + uint32_t PCIeLinkSpeed; + uint32_t PCIeLinkWidth; } MetricsTableX_t; typedef struct __attribute__((packed, aligned(4))) { diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h index 356e0f57a426..ddb625860083 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h @@ -42,7 +42,7 @@ #define FEATURE_EDC_BIT 7 #define FEATURE_PLL_POWER_DOWN_BIT 8 #define FEATURE_VDDOFF_BIT 9 -#define FEATURE_VCN_DPM_BIT 10 +#define FEATURE_VCN_DPM_BIT 10 /* this is for both VCN0 and VCN1 */ #define FEATURE_DS_MPM_BIT 11 #define FEATURE_FCLK_DPM_BIT 12 #define FEATURE_SOCCLK_DPM_BIT 13 @@ -56,9 +56,9 @@ #define FEATURE_DS_GFXCLK_BIT 21 #define FEATURE_DS_SOCCLK_BIT 22 #define FEATURE_DS_LCLK_BIT 23 -#define FEATURE_LOW_POWER_DCNCLKS_BIT 24 // for all DISP clks +#define FEATURE_LOW_POWER_DCNCLKS_BIT 24 #define FEATURE_DS_SHUBCLK_BIT 25 -#define FEATURE_SPARE0_BIT 26 //SPARE +#define FEATURE_RESERVED0_BIT 26 #define FEATURE_ZSTATES_BIT 27 #define FEATURE_IOMMUL2_PG_BIT 28 #define FEATURE_DS_FCLK_BIT 29 @@ -66,8 +66,8 @@ #define FEATURE_DS_MP1CLK_BIT 31 #define FEATURE_WHISPER_MODE_BIT 32 #define FEATURE_SMU_LOW_POWER_BIT 33 -#define FEATURE_SMART_L3_RINSER_BIT 34 -#define FEATURE_SPARE1_BIT 35 //SPARE +#define FEATURE_RESERVED1_BIT 34 /* v14_0_0 SMART_L3_RINSER; v14_0_1 RESERVED1 */ +#define FEATURE_GFX_DEM_BIT 35 /* v14_0_0 SPARE; v14_0_1 GFX_DEM */ #define FEATURE_PSI_BIT 36 #define FEATURE_PROCHOT_BIT 37 #define FEATURE_CPUOFF_BIT 38 @@ -77,11 +77,11 @@ #define FEATURE_PERF_LIMIT_BIT 42 #define FEATURE_CORE_DLDO_BIT 43 #define FEATURE_DVO_BIT 44 -#define FEATURE_DS_VCN_BIT 45 +#define FEATURE_DS_VCN_BIT 45 /* v14_0_1 this is for both VCN0 and VCN1 */ #define FEATURE_CPPC_BIT 46 #define FEATURE_CPPC_PREFERRED_CORES 47 #define FEATURE_DF_CSTATES_BIT 48 -#define FEATURE_SPARE2_BIT 49 //SPARE +#define FEATURE_FAST_PSTATE_CLDO_BIT 49 /* v14_0_0 SPARE */ #define FEATURE_ATHUB_PG_BIT 50 #define FEATURE_VDDOFF_ECO_BIT 51 #define FEATURE_ZSTATES_ECO_BIT 52 @@ -93,8 +93,8 @@ #define FEATURE_DS_IPUCLK_BIT 58 #define FEATURE_DS_VPECLK_BIT 59 #define FEATURE_VPE_DPM_BIT 60 -#define FEATURE_SPARE_61 61 -#define FEATURE_FP_DIDT 62 +#define FEATURE_SMART_L3_RINSER_BIT 61 /* v14_0_0 SPARE*/ +#define FEATURE_PCC_BIT 62 /* v14_0_0 FP_DIDT v14_0_1 PCC_BIT */ #define NUM_FEATURES 63 // Firmware Header/Footer @@ -151,6 +151,43 @@ typedef struct { // MP1_EXT_SCRATCH7 = RTOS Current Job } FwStatus_t; +typedef struct { + // MP1_EXT_SCRATCH0 + uint32_t DpmHandlerID : 8; + uint32_t ActivityMonitorID : 8; + uint32_t DpmTimerID : 8; + uint32_t DpmHubID : 4; + uint32_t DpmHubTask : 4; + // MP1_EXT_SCRATCH1 + uint32_t CclkSyncStatus : 8; + uint32_t ZstateStatus : 4; + uint32_t Cpu1VddOff : 4; + uint32_t DstateFun : 4; + uint32_t DstateDev : 4; + uint32_t GfxOffStatus : 2; + uint32_t Cpu0Off : 2; + uint32_t Cpu1Off : 2; + uint32_t Cpu0VddOff : 2; + // MP1_EXT_SCRATCH2 + uint32_t P2JobHandler :32; + // MP1_EXT_SCRATCH3 + uint32_t PostCode :32; + // MP1_EXT_SCRATCH4 + uint32_t MsgPortBusy :15; + uint32_t RsmuPmiP1Pending : 1; + uint32_t RsmuPmiP2PendingCnt : 8; + uint32_t DfCstateExitPending : 1; + uint32_t Pc6EntryPending : 1; + uint32_t Pc6ExitPending : 1; + uint32_t WarmResetPending : 1; + uint32_t Mp0ClkPending : 1; + uint32_t InWhisperMode : 1; + uint32_t spare2 : 2; + // MP1_EXT_SCRATCH5 + uint32_t IdleMask :32; + // MP1_EXT_SCRATCH6 = RTOS threads' status + // MP1_EXT_SCRATCH7 = RTOS Current Job +} FwStatus_t_v14_0_1; #pragma pack(pop) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h index ca7ce4251482..c4dc5881d8df 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h @@ -72,23 +72,19 @@ #define PPSMC_MSG_SetHardMinSocclkByFreq 0x13 ///< Set hard min for SOC CLK #define PPSMC_MSG_SetSoftMinFclk 0x14 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinVcn0 0x15 ///< Set soft min for VCN0 clocks (VCLK0 and DCLK0) - #define PPSMC_MSG_EnableGfxImu 0x16 ///< Enable GFX IMU - -#define PPSMC_MSG_spare_0x17 0x17 -#define PPSMC_MSG_spare_0x18 0x18 +#define PPSMC_MSG_spare_0x17 0x17 ///< Get GFX clock frequency +#define PPSMC_MSG_spare_0x18 0x18 ///< Get FCLK frequency #define PPSMC_MSG_AllowGfxOff 0x19 ///< Inform PMFW of allowing GFXOFF entry #define PPSMC_MSG_DisallowGfxOff 0x1A ///< Inform PMFW of disallowing GFXOFF entry #define PPSMC_MSG_SetSoftMaxGfxClk 0x1B ///< Set soft max for GFX CLK #define PPSMC_MSG_SetHardMinGfxClk 0x1C ///< Set hard min for GFX CLK - #define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x1D ///< Set soft max for SOC CLK #define PPSMC_MSG_SetSoftMaxFclkByFreq 0x1E ///< Set soft max for FCLK #define PPSMC_MSG_SetSoftMaxVcn0 0x1F ///< Set soft max for VCN0 clocks (VCLK0 and DCLK0) -#define PPSMC_MSG_spare_0x20 0x20 +#define PPSMC_MSG_spare_0x20 0x20 ///< Set power limit percentage #define PPSMC_MSG_PowerDownJpeg0 0x21 ///< Power down Jpeg of VCN0 #define PPSMC_MSG_PowerUpJpeg0 0x22 ///< Power up Jpeg of VCN0; VCN0 is power gated by default - #define PPSMC_MSG_SetHardMinFclkByFreq 0x23 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinSocclkByFreq 0x24 ///< Set soft min for SOC CLK #define PPSMC_MSG_AllowZstates 0x25 ///< Inform PMFM of allowing Zstate entry, i.e. no Miracast activity @@ -99,8 +95,8 @@ #define PPSMC_MSG_PowerUpIspByTile 0x2A ///< This message is used to power up ISP tiles and enable the ISP DPM #define PPSMC_MSG_SetHardMinIspiclkByFreq 0x2B ///< Set HardMin by frequency for ISPICLK #define PPSMC_MSG_SetHardMinIspxclkByFreq 0x2C ///< Set HardMin by frequency for ISPXCLK -#define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN.UMSCH (aka VSCH) scheduler -#define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN.UMSCH (aka VSCH) scheduler +#define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN0.UMSCH (aka VSCH) scheduler +#define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN0.UMSCH (aka VSCH) scheduler #define PPSMC_Message_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis #define PPSMC_Message_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn #define PPSMC_MSG_PowerUpVpe 0x31 ///< Power up VPE @@ -110,7 +106,9 @@ #define PPSMC_MSG_DisableLSdma 0x35 ///< Disable LSDMA #define PPSMC_MSG_SetSoftMaxVpe 0x36 ///< #define PPSMC_MSG_SetSoftMinVpe 0x37 ///< -#define PPSMC_Message_Count 0x38 ///< Total number of PPSMC messages +#define PPSMC_MSG_AllocMALLCache 0x38 ///< Allocating MALL Cache +#define PPSMC_MSG_ReleaseMALLCache 0x39 ///< Releasing MALL Cache +#define PPSMC_Message_Count 0x3A ///< Total number of PPSMC messages /** @}*/ /** diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_2_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_2_ppsmc.h new file mode 100644 index 000000000000..de2e442281ff --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_2_ppsmc.h @@ -0,0 +1,140 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU_V14_0_2_PPSMC_H +#define SMU_V14_0_2_PPSMC_H + +#define PPSMC_VERSION 0x1 + +// SMU Response Codes: +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +// Message Definitions: +// BASIC +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 +#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 +#define PPSMC_MSG_EnableAllSmuFeatures 0x6 +#define PPSMC_MSG_DisableAllSmuFeatures 0x7 +#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 +#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 +#define PPSMC_MSG_DisableSmuFeaturesLow 0xA +#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB +#define PPSMC_MSG_GetRunningSmuFeaturesLow 0xC +#define PPSMC_MSG_GetRunningSmuFeaturesHigh 0xD +#define PPSMC_MSG_SetDriverDramAddrHigh 0xE +#define PPSMC_MSG_SetDriverDramAddrLow 0xF +#define PPSMC_MSG_SetToolsDramAddrHigh 0x10 +#define PPSMC_MSG_SetToolsDramAddrLow 0x11 +#define PPSMC_MSG_TransferTableSmu2Dram 0x12 +#define PPSMC_MSG_TransferTableDram2Smu 0x13 +#define PPSMC_MSG_UseDefaultPPTable 0x14 + +//BACO/BAMACO/BOMACO +#define PPSMC_MSG_EnterBaco 0x15 +#define PPSMC_MSG_ExitBaco 0x16 +#define PPSMC_MSG_ArmD3 0x17 +#define PPSMC_MSG_BacoAudioD3PME 0x18 + +//DPM +#define PPSMC_MSG_SetSoftMinByFreq 0x19 +#define PPSMC_MSG_SetSoftMaxByFreq 0x1A +#define PPSMC_MSG_SetHardMinByFreq 0x1B +#define PPSMC_MSG_SetHardMaxByFreq 0x1C +#define PPSMC_MSG_GetMinDpmFreq 0x1D +#define PPSMC_MSG_GetMaxDpmFreq 0x1E +#define PPSMC_MSG_GetDpmFreqByIndex 0x1F +#define PPSMC_MSG_OverridePcieParameters 0x20 + +//DramLog Set DramAddr +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x21 +#define PPSMC_MSG_DramLogSetDramAddrLow 0x22 +#define PPSMC_MSG_DramLogSetDramSize 0x23 +#define PPSMC_MSG_SetWorkloadMask 0x24 + +#define PPSMC_MSG_GetVoltageByDpm 0x25 // Can be removed +#define PPSMC_MSG_SetVideoFps 0x26 // Can be removed +#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x27 + +//Power Gating +#define PPSMC_MSG_AllowGfxOff 0x28 +#define PPSMC_MSG_DisallowGfxOff 0x29 +#define PPSMC_MSG_PowerUpVcn 0x2A +#define PPSMC_MSG_PowerDownVcn 0x2B +#define PPSMC_MSG_PowerUpJpeg 0x2C +#define PPSMC_MSG_PowerDownJpeg 0x2D + +//Resets +#define PPSMC_MSG_PrepareMp1ForUnload 0x2E +#define PPSMC_MSG_Mode1Reset 0x2F + +//Set SystemVirtual DramAddrHigh +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x30 +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x31 +//ACDC Power Source +#define PPSMC_MSG_SetPptLimit 0x32 +#define PPSMC_MSG_GetPptLimit 0x33 +#define PPSMC_MSG_ReenableAcDcInterrupt 0x34 +#define PPSMC_MSG_NotifyPowerSource 0x35 + +//BTC +#define PPSMC_MSG_RunDcBtc 0x36 + +// 0x37 + +//Others +#define PPSMC_MSG_SetTemperatureInputSelect 0x38 // Can be removed +#define PPSMC_MSG_SetFwDstatesMask 0x39 +#define PPSMC_MSG_SetThrottlerMask 0x3A + +#define PPSMC_MSG_SetExternalClientDfCstateAllow 0x3B + +#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x3C + +//STB to dram log +#define PPSMC_MSG_DumpSTBtoDram 0x3D +#define PPSMC_MSG_STBtoDramLogSetDramAddrHigh 0x3E +#define PPSMC_MSG_STBtoDramLogSetDramAddrLow 0x3F +#define PPSMC_MSG_STBtoDramLogSetDramSize 0x40 +#define PPSMC_MSG_SetOBMTraceBufferLogging 0x41 + +#define PPSMC_MSG_AllowGfxDcs 0x43 +#define PPSMC_MSG_DisallowGfxDcs 0x44 +#define PPSMC_MSG_EnableAudioStutterWA 0x45 +#define PPSMC_MSG_PowerUpUmsch 0x46 +#define PPSMC_MSG_PowerDownUmsch 0x47 +#define PPSMC_MSG_SetDcsArch 0x48 +#define PPSMC_MSG_TriggerVFFLR 0x49 +#define PPSMC_MSG_SetNumBadMemoryPagesRetired 0x4A +#define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4B +#define PPSMC_MSG_SetPriorityDeltaGain 0x4C +#define PPSMC_MSG_AllowIHHostInterrupt 0x4D +#define PPSMC_MSG_Mode3Reset 0x4F +#define PPSMC_Message_Count 0x50 +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h index af427cc7dbb8..c48214e3dc8e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h @@ -445,4 +445,11 @@ enum smu_feature_mask { SMU_FEATURE_COUNT, }; +/* Message category flags */ +#define SMU_MSG_VF_FLAG (1U << 0) +#define SMU_MSG_RAS_PRI (1U << 1) + +/* Firmware capability flags */ +#define SMU_FW_CAP_RAS_PRI (1U << 0) + #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h index a0e5ad0381d6..c2ab336bb530 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h @@ -237,7 +237,7 @@ int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu); int smu_v11_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); -bool smu_v11_0_baco_is_support(struct smu_context *smu); +int smu_v11_0_get_bamaco_support(struct smu_context *smu); enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h index fbd57fa1a004..d9700a3f28d2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h @@ -210,7 +210,7 @@ int smu_v13_0_set_azalia_d3_pme(struct smu_context *smu); int smu_v13_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); -bool smu_v13_0_baco_is_support(struct smu_context *smu); +int smu_v13_0_get_bamaco_support(struct smu_context *smu); int smu_v13_0_baco_enter(struct smu_context *smu); int smu_v13_0_baco_exit(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h index 3f7463c1c1a9..1fc4557e6fb4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h @@ -27,7 +27,8 @@ #define SMU14_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7 -#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x1 +#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_1 0x6 +#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x25 #define FEATURE_MASK(feature) (1ULL << feature) @@ -38,7 +39,8 @@ #define MP1_SRAM 0x03c00004 /* address block */ -#define smnMP1_FIRMWARE_FLAGS 0x3010028 +#define smnMP1_FIRMWARE_FLAGS_14_0_0 0x3010028 +#define smnMP1_FIRMWARE_FLAGS 0x3010024 #define smnMP1_PUB_CTRL 0x3010d10 #define MAX_DPM_LEVELS 16 @@ -159,7 +161,7 @@ int smu_v14_0_register_irq_handler(struct smu_context *smu); int smu_v14_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_baco_seq baco_seq); -bool smu_v14_0_baco_is_support(struct smu_context *smu); +int smu_v14_0_get_bamaco_support(struct smu_context *smu); enum smu_baco_state smu_v14_0_baco_get_state(struct smu_context *smu); diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h new file mode 100644 index 000000000000..4a3fde89aed7 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0_2_pptable.h @@ -0,0 +1,164 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU_14_0_2_PPTABLE_H +#define SMU_14_0_2_PPTABLE_H + + +#pragma pack(push, 1) + +#define SMU_14_0_2_TABLE_FORMAT_REVISION 3 + +// POWERPLAYTABLE::ulPlatformCaps +#define SMU_14_0_2_PP_PLATFORM_CAP_POWERPLAY 0x1 // This cap indicates whether CCC need to show Powerplay page. +#define SMU_14_0_2_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 // This cap indicates whether power source notificaiton is done by SBIOS instead of OS. +#define SMU_14_0_2_PP_PLATFORM_CAP_HARDWAREDC 0x4 // This cap indicates whether DC mode notificaiton is done by GPIO pin directly. +#define SMU_14_0_2_PP_PLATFORM_CAP_BACO 0x8 // This cap indicates whether board supports the BACO circuitry. +#define SMU_14_0_2_PP_PLATFORM_CAP_MACO 0x10 // This cap indicates whether board supports the MACO circuitry. +#define SMU_14_0_2_PP_PLATFORM_CAP_SHADOWPSTATE 0x20 // This cap indicates whether board supports the Shadow Pstate. +#define SMU_14_0_2_PP_PLATFORM_CAP_LEDSUPPORTED 0x40 // This cap indicates whether board supports the LED. +#define SMU_14_0_2_PP_PLATFORM_CAP_MOBILEOVERDRIVE 0x80 // This cap indicates whether board supports the Mobile Overdrive. + +// SMU_14_0_2_PP_THERMALCONTROLLER - Thermal Controller Type +#define SMU_14_0_2_PP_THERMALCONTROLLER_NONE 0 + +#define SMU_14_0_2_PP_OVERDRIVE_VERSION 0x1 // TODO: FIX OverDrive Version TBD +#define SMU_14_0_2_PP_POWERSAVINGCLOCK_VERSION 0x01 // Power Saving Clock Table Version 1.00 + +enum SMU_14_0_2_OD_SW_FEATURE_CAP +{ + SMU_14_0_2_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT = 0, + SMU_14_0_2_ODCAP_POWER_MODE = 1, + SMU_14_0_2_ODCAP_AUTO_UV_ENGINE = 2, + SMU_14_0_2_ODCAP_AUTO_OC_ENGINE = 3, + SMU_14_0_2_ODCAP_AUTO_OC_MEMORY = 4, + SMU_14_0_2_ODCAP_MEMORY_TIMING_TUNE = 5, + SMU_14_0_2_ODCAP_MANUAL_AC_TIMING = 6, + SMU_14_0_2_ODCAP_AUTO_VF_CURVE_OPTIMIZER = 7, + SMU_14_0_2_ODCAP_AUTO_SOC_UV = 8, + SMU_14_0_2_ODCAP_COUNT = 9, +}; + +enum SMU_14_0_2_OD_SW_FEATURE_ID +{ + SMU_14_0_2_ODFEATURE_AUTO_FAN_ACOUSTIC_LIMIT = 1 << SMU_14_0_2_ODCAP_AUTO_FAN_ACOUSTIC_LIMIT, // Auto Fan Acoustic RPM + SMU_14_0_2_ODFEATURE_POWER_MODE = 1 << SMU_14_0_2_ODCAP_POWER_MODE, // Optimized GPU Power Mode + SMU_14_0_2_ODFEATURE_AUTO_UV_ENGINE = 1 << SMU_14_0_2_ODCAP_AUTO_UV_ENGINE, // Auto Under Volt GFXCLK + SMU_14_0_2_ODFEATURE_AUTO_OC_ENGINE = 1 << SMU_14_0_2_ODCAP_AUTO_OC_ENGINE, // Auto Over Clock GFXCLK + SMU_14_0_2_ODFEATURE_AUTO_OC_MEMORY = 1 << SMU_14_0_2_ODCAP_AUTO_OC_MEMORY, // Auto Over Clock MCLK + SMU_14_0_2_ODFEATURE_MEMORY_TIMING_TUNE = 1 << SMU_14_0_2_ODCAP_MEMORY_TIMING_TUNE, // Auto AC Timing Tuning + SMU_14_0_2_ODFEATURE_MANUAL_AC_TIMING = 1 << SMU_14_0_2_ODCAP_MANUAL_AC_TIMING, // Manual fine grain AC Timing tuning + SMU_14_0_2_ODFEATURE_AUTO_VF_CURVE_OPTIMIZER = 1 << SMU_14_0_2_ODCAP_AUTO_VF_CURVE_OPTIMIZER, // Fine grain auto VF curve tuning + SMU_14_0_2_ODFEATURE_AUTO_SOC_UV = 1 << SMU_14_0_2_ODCAP_AUTO_SOC_UV, // Auto Unver Volt VDDSOC +}; + +#define SMU_14_0_2_MAX_ODFEATURE 32 // Maximum Number of OD Features + +enum SMU_14_0_2_OD_SW_FEATURE_SETTING_ID +{ + SMU_14_0_2_ODSETTING_AUTO_FAN_ACOUSTIC_LIMIT = 0, + SMU_14_0_2_ODSETTING_POWER_MODE = 1, + SMU_14_0_2_ODSETTING_AUTOUVENGINE = 2, + SMU_14_0_2_ODSETTING_AUTOOCENGINE = 3, + SMU_14_0_2_ODSETTING_AUTOOCMEMORY = 4, + SMU_14_0_2_ODSETTING_ACTIMING = 5, + SMU_14_0_2_ODSETTING_MANUAL_AC_TIMING = 6, + SMU_14_0_2_ODSETTING_AUTO_VF_CURVE_OPTIMIZER = 7, + SMU_14_0_2_ODSETTING_AUTO_SOC_UV = 8, + SMU_14_0_2_ODSETTING_COUNT = 9, +}; +#define SMU_14_0_2_MAX_ODSETTING 64 // Maximum Number of ODSettings + +enum SMU_14_0_2_PWRMODE_SETTING +{ + SMU_14_0_2_PMSETTING_POWER_LIMIT_QUIET = 0, + SMU_14_0_2_PMSETTING_POWER_LIMIT_BALANCE, + SMU_14_0_2_PMSETTING_POWER_LIMIT_TURBO, + SMU_14_0_2_PMSETTING_POWER_LIMIT_RAGE, + SMU_14_0_2_PMSETTING_ACOUSTIC_TEMP_QUIET, + SMU_14_0_2_PMSETTING_ACOUSTIC_TEMP_BALANCE, + SMU_14_0_2_PMSETTING_ACOUSTIC_TEMP_TURBO, + SMU_14_0_2_PMSETTING_ACOUSTIC_TEMP_RAGE, + SMU_14_0_2_PMSETTING_ACOUSTIC_TARGET_RPM_QUIET, + SMU_14_0_2_PMSETTING_ACOUSTIC_TARGET_RPM_BALANCE, + SMU_14_0_2_PMSETTING_ACOUSTIC_TARGET_RPM_TURBO, + SMU_14_0_2_PMSETTING_ACOUSTIC_TARGET_RPM_RAGE, + SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_QUIET, + SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_BALANCE, + SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_TURBO, + SMU_14_0_2_PMSETTING_ACOUSTIC_LIMIT_RPM_RAGE, +}; +#define SMU_14_0_2_MAX_PMSETTING 32 // Maximum Number of PowerMode Settings + +enum SMU_14_0_2_overdrive_table_id +{ + SMU_14_0_2_OVERDRIVE_TABLE_BASIC = 0, + SMU_14_0_2_OVERDRIVE_TABLE_ADVANCED = 1, + SMU_14_0_2_OVERDRIVE_TABLE_COUNT = 2, +}; + +struct smu_14_0_2_overdrive_table +{ + uint8_t revision; // Revision = SMU_14_0_2_PP_OVERDRIVE_VERSION + uint8_t reserve[3]; // Zero filled field reserved for future use + uint8_t cap[SMU_14_0_2_OVERDRIVE_TABLE_COUNT][SMU_14_0_2_MAX_ODFEATURE]; // OD feature support flags + int32_t max[SMU_14_0_2_OVERDRIVE_TABLE_COUNT][SMU_14_0_2_MAX_ODSETTING]; // maximum settings + int32_t min[SMU_14_0_2_OVERDRIVE_TABLE_COUNT][SMU_14_0_2_MAX_ODSETTING]; // minimum settings + int16_t pm_setting[SMU_14_0_2_MAX_PMSETTING]; // Optimized power mode feature settings +}; + +struct smu_14_0_2_powerplay_table +{ + struct atom_common_table_header header; // header.format_revision = 3 (HAS TO MATCH SMU_14_0_2_TABLE_FORMAT_REVISION), header.content_revision = ? structuresize is calculated by PPGen. + uint8_t table_revision; // PPGen use only: table_revision = 3 + uint8_t padding; // Padding 1 byte to align table_size offset to 6 bytes (pmfw_start_offset, for PMFW to know the starting offset of PPTable_t). + uint16_t pmfw_pptable_start_offset; // The start offset of the pmfw portion. i.e. start of PPTable_t (start of SkuTable_t) + uint16_t pmfw_pptable_size; // The total size of pmfw_pptable, i.e PPTable_t. + uint16_t pmfw_pfe_table_start_offset; // The start offset of the PFE_Settings_t within pmfw_pptable. + uint16_t pmfw_pfe_table_size; // The size of PFE_Settings_t. + uint16_t pmfw_board_table_start_offset; // The start offset of the BoardTable_t within pmfw_pptable. + uint16_t pmfw_board_table_size; // The size of BoardTable_t. + uint16_t pmfw_custom_sku_table_start_offset; // The start offset of the CustomSkuTable_t within pmfw_pptable. + uint16_t pmfw_custom_sku_table_size; // The size of the CustomSkuTable_t. + uint32_t golden_pp_id; // PPGen use only: PP Table ID on the Golden Data Base + uint32_t golden_revision; // PPGen use only: PP Table Revision on the Golden Data Base + uint16_t format_id; // PPGen use only: PPTable for different ASICs. + uint32_t platform_caps; // POWERPLAYTABLE::ulPlatformCaps + + uint8_t thermal_controller_type; // one of smu_14_0_2_PP_THERMALCONTROLLER + + uint16_t small_power_limit1; + uint16_t small_power_limit2; + uint16_t boost_power_limit; // For Gemini Board, when the slave adapter is in BACO mode, the master adapter will use this boost power limit instead of the default power limit to boost the power limit. + uint16_t software_shutdown_temp; + + uint8_t reserve[143]; // Zero filled field reserved for future use + + struct smu_14_0_2_overdrive_table overdrive_table; + + PPTable_t smc_pptable; // PPTable_t in driver_if.h -- as requested by PMFW, this offset should start at a 32-byte boundary, and the table_size above should remain at offset=6 bytes +}; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 0c2d04f978ac..6d334a2aff67 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2387,7 +2387,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support = smu_v11_0_baco_is_support, + .get_bamaco_support = smu_v11_0_get_bamaco_support, .baco_enter = smu_v11_0_baco_enter, .baco_exit = smu_v11_0_baco_exit, .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 836b1df79928..5a68d365967f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -3538,7 +3538,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support = smu_v11_0_baco_is_support, + .get_bamaco_support = smu_v11_0_get_bamaco_support, .baco_enter = navi10_baco_enter, .baco_exit = navi10_baco_exit, .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 1f18b61884f3..e426f457a017 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -4431,7 +4431,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .register_irq_handler = smu_v11_0_register_irq_handler, .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support = smu_v11_0_baco_is_support, + .get_bamaco_support = smu_v11_0_get_bamaco_support, .baco_enter = sienna_cichlid_baco_enter, .baco_exit = sienna_cichlid_baco_exit, .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index f6545093bfc1..9d5ab2ea643a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -93,7 +93,7 @@ static void smu_v11_0_poll_baco_exit(struct smu_context *smu) int smu_v11_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; - char ucode_prefix[30]; + char ucode_prefix[25]; char fw_name[SMU_FW_NAME_LEN]; int err = 0; const struct smc_firmware_header_v1_0 *hdr; @@ -1557,23 +1557,27 @@ int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); } -bool smu_v11_0_baco_is_support(struct smu_context *smu) +int smu_v11_0_get_bamaco_support(struct smu_context *smu) { struct smu_baco_context *smu_baco = &smu->smu_baco; + int bamaco_support = 0; if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) - return false; + return 0; + + if (smu_baco->maco_support) + bamaco_support |= MACO_SUPPORT; /* return true if ASIC is in BACO state already */ if (smu_v11_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) - return true; + return bamaco_support |= BACO_SUPPORT; /* Arcturus does not support this bit mask */ if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) - return false; + return 0; - return true; + return (bamaco_support |= BACO_SUPPORT); } enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) @@ -1603,7 +1607,7 @@ int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) case IP_VERSION(11, 0, 11): case IP_VERSION(11, 0, 12): case IP_VERSION(11, 0, 13): - if (amdgpu_runtime_pm == 2) + if (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO) ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, D3HOT_BAMACO_SEQUENCE, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index da1f43999d09..379e44eb0019 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -301,7 +301,7 @@ static int vangogh_get_legacy_smu_metrics_data(struct smu_context *smu, *value = metrics->GfxActivity / 100; break; case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->UvdActivity; + *value = metrics->UvdActivity / 100; break; case METRICS_AVERAGE_SOCKETPOWER: *value = (metrics->CurrentSocketPower << 8) / @@ -1507,6 +1507,12 @@ static int vangogh_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_VCN_LOAD: + ret = vangogh_common_get_smu_metrics_data(smu, + METRICS_AVERAGE_VCNACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_AVG_POWER: ret = vangogh_common_get_smu_metrics_data(smu, METRICS_AVERAGE_SOCKETPOWER, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c index f41ac6465f2a..ce941fbb9cfb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c @@ -759,8 +759,11 @@ static int aldebaran_emit_clk_levels(struct smu_context *smu, switch (type) { case SMU_OD_SCLK: - *offset += sysfs_emit_at(buf, *offset, "%s:\n", "GFXCLK"); - fallthrough; + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_SCLK"); + *offset += sysfs_emit_at(buf, *offset, "0: %uMhz\n1: %uMhz\n", + pstate_table->gfxclk_pstate.curr.min, + pstate_table->gfxclk_pstate.curr.max); + return 0; case SMU_SCLK: ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &cur_value); if (ret) { @@ -788,8 +791,11 @@ static int aldebaran_emit_clk_levels(struct smu_context *smu, break; case SMU_OD_MCLK: - *offset += sysfs_emit_at(buf, *offset, "%s:\n", "MCLK"); - fallthrough; + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_MCLK"); + *offset += sysfs_emit_at(buf, *offset, "0: %uMhz\n1: %uMhz\n", + pstate_table->uclk_pstate.curr.min, + pstate_table->uclk_pstate.curr.max); + return 0; case SMU_MCLK: ret = aldebaran_get_current_clk_freq_by_table(smu, SMU_UCLK, &cur_value); if (ret) { @@ -850,7 +856,6 @@ static int aldebaran_emit_clk_levels(struct smu_context *smu, } switch (type) { - case SMU_OD_SCLK: case SMU_SCLK: for (i = 0; i < display_levels; i++) { clock_mhz = freq_values[i]; @@ -863,7 +868,6 @@ static int aldebaran_emit_clk_levels(struct smu_context *smu, } break; - case SMU_OD_MCLK: case SMU_MCLK: case SMU_SOCCLK: case SMU_FCLK: @@ -1581,11 +1585,11 @@ static void aldebaran_get_unique_id(struct smu_context *smu) adev->unique_id = ((uint64_t)upper32 << 32) | lower32; } -static bool aldebaran_is_baco_supported(struct smu_context *smu) +static int aldebaran_get_bamaco_support(struct smu_context *smu) { /* aldebaran is not support baco */ - return false; + return 0; } static int aldebaran_set_df_cstate(struct smu_context *smu, @@ -2059,7 +2063,7 @@ static const struct pptable_funcs aldebaran_ppt_funcs = { .register_irq_handler = smu_v13_0_register_irq_handler, .set_azalia_d3_pme = smu_v13_0_set_azalia_d3_pme, .get_max_sustainable_clocks_by_dc = smu_v13_0_get_max_sustainable_clocks_by_dc, - .baco_is_support = aldebaran_is_baco_supported, + .get_bamaco_support = aldebaran_get_bamaco_support, .get_dpm_ultimate_freq = smu_v13_0_get_dpm_ultimate_freq, .set_soft_freq_limited_range = aldebaran_set_soft_freq_limited_range, .od_edit_dpm_table = aldebaran_usr_edit_dpm_table, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c index 48170bb5112e..a8d34adc7d3f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c @@ -93,7 +93,7 @@ int smu_v13_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; char fw_name[30]; - char ucode_prefix[30]; + char ucode_prefix[15]; int err = 0; const struct smc_firmware_header_v1_0 *hdr; const struct common_firmware_header *header; @@ -2247,7 +2247,7 @@ static int smu_v13_0_baco_set_state(struct smu_context *smu, if (state == SMU_BACO_STATE_ENTER) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, - (smu_baco->maco_support && amdgpu_runtime_pm != 1) ? + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO) ? BACO_SEQ_BAMACO : BACO_SEQ_BACO, NULL); } else { @@ -2268,33 +2268,36 @@ static int smu_v13_0_baco_set_state(struct smu_context *smu, return ret; } -bool smu_v13_0_baco_is_support(struct smu_context *smu) +int smu_v13_0_get_bamaco_support(struct smu_context *smu) { struct smu_baco_context *smu_baco = &smu->smu_baco; + int bamaco_support = 0; if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) - return false; + return 0; + + if (smu_baco->maco_support) + bamaco_support |= MACO_SUPPORT; /* return true if ASIC is in BACO state already */ if (smu_v13_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) - return true; + return bamaco_support |= BACO_SUPPORT; if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) - return false; + return 0; - return true; + return (bamaco_support |= BACO_SUPPORT); } int smu_v13_0_baco_enter(struct smu_context *smu) { - struct smu_baco_context *smu_baco = &smu->smu_baco; struct amdgpu_device *adev = smu->adev; int ret; if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { return smu_v13_0_baco_set_armd3_sequence(smu, - (smu_baco->maco_support && amdgpu_runtime_pm != 1) ? + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO) ? BACO_SEQ_BAMACO : BACO_SEQ_BACO); } else { ret = smu_v13_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 9c03296f92cd..1e09d5f2d82f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -2751,7 +2751,13 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, switch (mp1_state) { case PP_MP1_STATE_UNLOAD: - ret = smu_cmn_set_mp1_state(smu, mp1_state); + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_PrepareMp1ForUnload, + 0x55, NULL); + + if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) + ret = smu_v13_0_disable_pmfw_state(smu); + break; default: /* Ignore others */ @@ -3070,7 +3076,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = { .set_tool_table_location = smu_v13_0_set_tool_table_location, .deep_sleep_control = smu_v13_0_deep_sleep_control, .gfx_ulv_control = smu_v13_0_gfx_ulv_control, - .baco_is_support = smu_v13_0_baco_is_support, + .get_bamaco_support = smu_v13_0_get_bamaco_support, .baco_enter = smu_v13_0_baco_enter, .baco_exit = smu_v13_0_baco_exit, .mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c index bb98156b2fa1..88f1a0d878f3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c @@ -226,8 +226,18 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en) struct amdgpu_device *adev = smu->adev; int ret = 0; - if (!en && !adev->in_s0ix) + if (!en && !adev->in_s0ix) { + /* Adds a GFX reset as workaround just before sending the + * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering + * an invalid state. + */ + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, + SMU_RESET_MODE_2, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); + } return ret; } @@ -318,7 +328,7 @@ static int smu_v13_0_4_get_smu_metrics_data(struct smu_context *smu, *value = metrics->GfxActivity / 100; break; case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->UvdActivity; + *value = metrics->UvdActivity / 100; break; case METRICS_AVERAGE_SOCKETPOWER: *value = (metrics->AverageSocketPower << 8) / 1000; @@ -572,6 +582,12 @@ static int smu_v13_0_4_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_VCN_LOAD: + ret = smu_v13_0_4_get_smu_metrics_data(smu, + METRICS_AVERAGE_VCNACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_AVG_POWER: ret = smu_v13_0_4_get_smu_metrics_data(smu, METRICS_AVERAGE_SOCKETPOWER, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c index 0dce672ac1b9..218f209c3775 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c @@ -286,7 +286,7 @@ static int smu_v13_0_5_get_smu_metrics_data(struct smu_context *smu, *value = metrics->GfxActivity / 100; break; case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->UvdActivity; + *value = metrics->UvdActivity / 100; break; case METRICS_CURR_SOCKETPOWER: *value = (metrics->CurrentSocketPower << 8) / 1000; @@ -332,6 +332,12 @@ static int smu_v13_0_5_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_VCN_LOAD: + ret = smu_v13_0_5_get_smu_metrics_data(smu, + METRICS_AVERAGE_VCNACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: ret = smu_v13_0_5_get_smu_metrics_data(smu, METRICS_CURR_SOCKETPOWER, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 3957af057d54..4d3eca2fc3f1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -138,13 +138,13 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), - MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), - MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, 0), + MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDriverReset, SMU_MSG_RAS_PRI), MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), @@ -167,10 +167,10 @@ static const struct cmn2asic_msg_mapping smu_v13_0_6_message_map[SMU_MSG_MAX_COU MSG_MAP(GetCTFLimit, PPSMC_MSG_GetCTFLimit, 0), MSG_MAP(GetThermalLimit, PPSMC_MSG_ReadThrottlerLimit, 0), MSG_MAP(ClearMcaOnRead, PPSMC_MSG_ClearMcaOnRead, 0), - MSG_MAP(QueryValidMcaCount, PPSMC_MSG_QueryValidMcaCount, 0), - MSG_MAP(QueryValidMcaCeCount, PPSMC_MSG_QueryValidMcaCeCount, 0), - MSG_MAP(McaBankDumpDW, PPSMC_MSG_McaBankDumpDW, 0), - MSG_MAP(McaBankCeDumpDW, PPSMC_MSG_McaBankCeDumpDW, 0), + MSG_MAP(QueryValidMcaCount, PPSMC_MSG_QueryValidMcaCount, SMU_MSG_RAS_PRI), + MSG_MAP(QueryValidMcaCeCount, PPSMC_MSG_QueryValidMcaCeCount, SMU_MSG_RAS_PRI), + MSG_MAP(McaBankDumpDW, PPSMC_MSG_McaBankDumpDW, SMU_MSG_RAS_PRI), + MSG_MAP(McaBankCeDumpDW, PPSMC_MSG_McaBankCeDumpDW, SMU_MSG_RAS_PRI), MSG_MAP(SelectPLPDMode, PPSMC_MSG_SelectPLPDMode, 0), MSG_MAP(RmaDueToBadPageThreshold, PPSMC_MSG_RmaDueToBadPageThreshold, 0), }; @@ -1010,8 +1010,11 @@ static int smu_v13_0_6_print_clk_levels(struct smu_context *smu, switch (type) { case SMU_OD_SCLK: - size += sysfs_emit_at(buf, size, "%s:\n", "GFXCLK"); - fallthrough; + size += sysfs_emit_at(buf, size, "%s:\n", "OD_SCLK"); + size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", + pstate_table->gfxclk_pstate.curr.min, + pstate_table->gfxclk_pstate.curr.max); + break; case SMU_SCLK: ret = smu_v13_0_6_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); @@ -1052,8 +1055,11 @@ static int smu_v13_0_6_print_clk_levels(struct smu_context *smu, break; case SMU_OD_MCLK: - size += sysfs_emit_at(buf, size, "%s:\n", "MCLK"); - fallthrough; + size += sysfs_emit_at(buf, size, "%s:\n", "OD_MCLK"); + size += sysfs_emit_at(buf, size, "0: %uMhz\n1: %uMhz\n", + pstate_table->uclk_pstate.curr.min, + pstate_table->uclk_pstate.curr.max); + break; case SMU_MCLK: ret = smu_v13_0_6_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); @@ -1670,6 +1676,11 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu, if (clk_type == SMU_UCLK) { if (max == pstate_table->uclk_pstate.curr.max) return 0; + /* For VF, only allowed in FW versions 85.102 or greater */ + if (amdgpu_sriov_vf(adev) && + ((smu->smc_fw_version < 0x556600) || + (adev->flags & AMD_IS_APU))) + return -EOPNOTSUPP; /* Only max clock limiting is allowed for UCLK */ ret = smu_v13_0_set_soft_freq_limited_range( smu, SMU_UCLK, 0, max); @@ -2077,11 +2088,11 @@ static void smu_v13_0_6_get_unique_id(struct smu_context *smu) adev->unique_id = pptable->PublicSerialNumber_AID; } -static bool smu_v13_0_6_is_baco_supported(struct smu_context *smu) +static int smu_v13_0_6_get_bamaco_support(struct smu_context *smu) { /* smu_13_0_6 does not support baco */ - return false; + return 0; } static const char *const throttling_logging_label[] = { @@ -2228,7 +2239,15 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table gpu_metrics->gfxclk_lock_status = GET_METRIC_FIELD(GfxLockXCDMak) >> GET_INST(GC, 0); if (!(adev->flags & AMD_IS_APU)) { - if (!amdgpu_sriov_vf(adev)) { + /*Check smu version, PCIE link speed and width will be reported from pmfw metric + * table for both pf & one vf for smu version 85.99.0 or higher else report only + * for pf from registers + */ + if (smu->smc_fw_version >= 0x556300) { + gpu_metrics->pcie_link_width = metrics_x->PCIeLinkWidth; + gpu_metrics->pcie_link_speed = + pcie_gen_to_speed(metrics_x->PCIeLinkSpeed); + } else if (!amdgpu_sriov_vf(adev)) { link_width_level = smu_v13_0_6_get_current_pcie_link_width_level(smu); if (link_width_level > MAX_LINK_WIDTH) link_width_level = 0; @@ -2238,6 +2257,7 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table gpu_metrics->pcie_link_speed = smu_v13_0_6_get_current_pcie_link_speed(smu); } + gpu_metrics->pcie_bandwidth_acc = SMUQ10_ROUND(metrics_x->PcieBandwidthAcc[0]); gpu_metrics->pcie_bandwidth_inst = @@ -2294,6 +2314,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table return sizeof(*gpu_metrics); } +static void smu_v13_0_6_restore_pci_config(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < 16; i++) + pci_write_config_dword(adev->pdev, i * 4, + adev->pdev->saved_config_space[i]); + pci_restore_msi_state(adev->pdev); +} + static int smu_v13_0_6_mode2_reset(struct smu_context *smu) { int ret = 0, index; @@ -2315,6 +2346,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu) /* Restore the config space saved during init */ amdgpu_device_load_pci_state(adev->pdev); + /* Certain platforms have switches which assign virtual BAR values to + * devices. OS uses the virtual BAR values and device behind the switch + * is assgined another BAR value. When device's config space registers + * are queried, switch returns the virtual BAR values. When mode-2 reset + * is performed, switch is unaware of it, and will continue to return + * the same virtual values to the OS.This affects + * pci_restore_config_space() API as it doesn't write the value saved if + * the current value read from config space is the same as what is + * saved. As a workaround, make sure the config space is restored + * always. + */ + if (!(adev->flags & AMD_IS_APU)) + smu_v13_0_6_restore_pci_config(smu); + dev_dbg(smu->adev->dev, "wait for reset ack\n"); do { ret = smu_cmn_wait_for_response(smu); @@ -2671,6 +2716,11 @@ static int mca_umc_mca_get_err_count(const struct mca_ras_info *mca_ras, struct umc_v12_0_is_correctable_error(adev, status0)) *count = (ext_error_code == 0) ? odecc_err_cnt : 1; + amdgpu_umc_update_ecc_status(adev, + entry->regs[MCA_REG_IDX_STATUS], + entry->regs[MCA_REG_IDX_IPID], + entry->regs[MCA_REG_IDX_ADDR]); + return 0; } @@ -2684,7 +2734,8 @@ static int mca_pcs_xgmi_mca_get_err_count(const struct mca_ras_info *mca_ras, st ext_error_code = MCA_REG__STATUS__ERRORCODEEXT(entry->regs[MCA_REG_IDX_STATUS]); err_cnt = MCA_REG__MISC0__ERRCNT(entry->regs[MCA_REG_IDX_MISC0]); - if (type == AMDGPU_MCA_ERROR_TYPE_UE && ext_error_code == 0) + if (type == AMDGPU_MCA_ERROR_TYPE_UE && + (ext_error_code == 0 || ext_error_code == 9)) *count = err_cnt; else if (type == AMDGPU_MCA_ERROR_TYPE_CE && ext_error_code == 6) *count = err_cnt; @@ -2975,7 +3026,7 @@ static int aca_smu_set_debug_mode(struct amdgpu_device *adev, bool enable) return smu_v13_0_6_mca_set_debug_mode(smu, enable); } -static int smu_v13_0_6_get_valid_aca_count(struct smu_context *smu, enum aca_error_type type, u32 *count) +static int smu_v13_0_6_get_valid_aca_count(struct smu_context *smu, enum aca_smu_type type, u32 *count) { uint32_t msg; int ret; @@ -2984,10 +3035,10 @@ static int smu_v13_0_6_get_valid_aca_count(struct smu_context *smu, enum aca_err return -EINVAL; switch (type) { - case ACA_ERROR_TYPE_UE: + case ACA_SMU_TYPE_UE: msg = SMU_MSG_QueryValidMcaCount; break; - case ACA_ERROR_TYPE_CE: + case ACA_SMU_TYPE_CE: msg = SMU_MSG_QueryValidMcaCeCount; break; default: @@ -3004,14 +3055,14 @@ static int smu_v13_0_6_get_valid_aca_count(struct smu_context *smu, enum aca_err } static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, - enum aca_error_type type, u32 *count) + enum aca_smu_type type, u32 *count) { struct smu_context *smu = adev->powerplay.pp_handle; int ret; switch (type) { - case ACA_ERROR_TYPE_UE: - case ACA_ERROR_TYPE_CE: + case ACA_SMU_TYPE_UE: + case ACA_SMU_TYPE_CE: ret = smu_v13_0_6_get_valid_aca_count(smu, type, count); break; default: @@ -3022,16 +3073,16 @@ static int aca_smu_get_valid_aca_count(struct amdgpu_device *adev, return ret; } -static int __smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_type type, +static int __smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_smu_type type, int idx, int offset, u32 *val) { uint32_t msg, param; switch (type) { - case ACA_ERROR_TYPE_UE: + case ACA_SMU_TYPE_UE: msg = SMU_MSG_McaBankDumpDW; break; - case ACA_ERROR_TYPE_CE: + case ACA_SMU_TYPE_CE: msg = SMU_MSG_McaBankCeDumpDW; break; default: @@ -3043,7 +3094,7 @@ static int __smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_t return smu_cmn_send_smc_msg_with_param(smu, msg, param, (uint32_t *)val); } -static int smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_type type, +static int smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_smu_type type, int idx, int offset, u32 *val, int count) { int ret, i; @@ -3060,7 +3111,7 @@ static int smu_v13_0_6_aca_bank_dump(struct smu_context *smu, enum aca_error_typ return 0; } -static int aca_bank_read_reg(struct amdgpu_device *adev, enum aca_error_type type, +static int aca_bank_read_reg(struct amdgpu_device *adev, enum aca_smu_type type, int idx, int reg_idx, u64 *val) { struct smu_context *smu = adev->powerplay.pp_handle; @@ -3077,13 +3128,13 @@ static int aca_bank_read_reg(struct amdgpu_device *adev, enum aca_error_type typ *val = (u64)data[1] << 32 | data[0]; dev_dbg(adev->dev, "mca read bank reg: type:%s, index: %d, reg_idx: %d, val: 0x%016llx\n", - type == ACA_ERROR_TYPE_UE ? "UE" : "CE", idx, reg_idx, *val); + type == ACA_SMU_TYPE_UE ? "UE" : "CE", idx, reg_idx, *val); return 0; } static int aca_smu_get_valid_aca_bank(struct amdgpu_device *adev, - enum aca_error_type type, int idx, struct aca_bank *bank) + enum aca_smu_type type, int idx, struct aca_bank *bank) { int i, ret, count; @@ -3097,12 +3148,25 @@ static int aca_smu_get_valid_aca_bank(struct amdgpu_device *adev, return 0; } +static int aca_smu_parse_error_code(struct amdgpu_device *adev, struct aca_bank *bank) +{ + int error_code; + + if (!(adev->flags & AMD_IS_APU) && adev->pm.fw_version >= 0x00555600) + error_code = ACA_REG__SYND__ERRORINFORMATION(bank->regs[ACA_REG_IDX_SYND]); + else + error_code = ACA_REG__STATUS__ERRORCODE(bank->regs[ACA_REG_IDX_STATUS]); + + return error_code & 0xff; +} + static const struct aca_smu_funcs smu_v13_0_6_aca_smu_funcs = { .max_ue_bank_count = 12, .max_ce_bank_count = 12, .set_debug_mode = aca_smu_set_debug_mode, .get_valid_aca_count = aca_smu_get_valid_aca_count, .get_valid_aca_bank = aca_smu_get_valid_aca_bank, + .parse_error_code = aca_smu_parse_error_code, }; static int smu_v13_0_6_select_xgmi_plpd_policy(struct smu_context *smu, @@ -3179,7 +3243,7 @@ static const struct pptable_funcs smu_v13_0_6_ppt_funcs = { .enable_thermal_alert = smu_v13_0_enable_thermal_alert, .disable_thermal_alert = smu_v13_0_disable_thermal_alert, .setup_pptable = smu_v13_0_6_setup_pptable, - .baco_is_support = smu_v13_0_6_is_baco_supported, + .get_bamaco_support = smu_v13_0_6_get_bamaco_support, .get_dpm_ultimate_freq = smu_v13_0_6_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v13_0_6_set_soft_freq_limited_range, .od_edit_dpm_table = smu_v13_0_6_usr_edit_dpm_table, @@ -3208,6 +3272,7 @@ void smu_v13_0_6_set_ppt_funcs(struct smu_context *smu) smu->feature_map = smu_v13_0_6_feature_mask_map; smu->table_map = smu_v13_0_6_table_map; smu->smc_driver_if_version = SMU13_0_6_DRIVER_IF_VERSION; + smu->smc_fw_caps |= SMU_FW_CAP_RAS_PRI; smu_v13_0_set_smu_mailbox_registers(smu); amdgpu_mca_smu_init_funcs(smu->adev, &smu_v13_0_6_mca_smu_funcs); amdgpu_aca_set_smu_funcs(smu->adev, &smu_v13_0_6_aca_smu_funcs); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 7318964f1f14..e996a0a4d33e 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -2650,7 +2650,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .set_tool_table_location = smu_v13_0_set_tool_table_location, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, - .baco_is_support = smu_v13_0_baco_is_support, + .get_bamaco_support = smu_v13_0_get_bamaco_support, .baco_enter = smu_v13_0_baco_enter, .baco_exit = smu_v13_0_baco_exit, .mode1_reset_is_support = smu_v13_0_7_is_mode1_reset_supported, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 2d1736234b4a..d8bcf765a803 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -363,7 +363,7 @@ static int yellow_carp_get_smu_metrics_data(struct smu_context *smu, *value = metrics->GfxActivity / 100; break; case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->UvdActivity; + *value = metrics->UvdActivity / 100; break; case METRICS_CURR_SOCKETPOWER: *value = (metrics->CurrentSocketPower << 8) / 1000; @@ -423,6 +423,12 @@ static int yellow_carp_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_VCN_LOAD: + ret = yellow_carp_get_smu_metrics_data(smu, + METRICS_AVERAGE_VCNACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_INPUT_POWER: ret = yellow_carp_get_smu_metrics_data(smu, METRICS_CURR_SOCKETPOWER, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu14/Makefile index ddbac5c655f7..4593e29e8ff8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/Makefile +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/Makefile @@ -23,7 +23,7 @@ # Makefile for the 'smu manager' sub-component of powerplay. # It provides the smu management services for the driver. -SMU14_MGR = smu_v14_0.o smu_v14_0_0_ppt.o +SMU14_MGR = smu_v14_0.o smu_v14_0_0_ppt.o smu_v14_0_2_ppt.o AMD_SWSMU_SMU14MGR = $(addprefix $(AMD_SWSMU_PATH)/smu14/,$(SMU14_MGR)) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 9e39f99154f9..68b9bf822e8d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -38,8 +38,13 @@ #include "amdgpu_ras.h" #include "smu_cmn.h" -#include "asic_reg/mp/mp_14_0_0_offset.h" -#include "asic_reg/mp/mp_14_0_0_sh_mask.h" +#include "asic_reg/mp/mp_14_0_2_offset.h" +#include "asic_reg/mp/mp_14_0_2_sh_mask.h" + +#define regMP1_SMN_IH_SW_INT_mp1_14_0_0 0x0341 +#define regMP1_SMN_IH_SW_INT_mp1_14_0_0_BASE_IDX 0 +#define regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0 0x0342 +#define regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0_BASE_IDX 0 /* * DO NOT use these for err/warn/info/debug messages. @@ -52,6 +57,7 @@ #undef pr_debug MODULE_FIRMWARE("amdgpu/smu_14_0_2.bin"); +MODULE_FIRMWARE("amdgpu/smu_14_0_3.bin"); #define ENABLE_IMU_ARG_GFXOFF_ENABLE 1 @@ -106,7 +112,6 @@ void smu_v14_0_fini_microcode(struct smu_context *smu) int smu_v14_0_load_microcode(struct smu_context *smu) { -#if 0 struct amdgpu_device *adev = smu->adev; const uint32_t *src; const struct smc_firmware_header_v1_0 *hdr; @@ -131,8 +136,13 @@ int smu_v14_0_load_microcode(struct smu_context *smu) 1 & ~MP1_SMN_PUB_CTRL__LX3_RESET_MASK); for (i = 0; i < adev->usec_timeout; i++) { - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || + amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff)); + else + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); if ((mp1_fw_flags & MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) break; @@ -142,9 +152,7 @@ int smu_v14_0_load_microcode(struct smu_context *smu) if (i == adev->usec_timeout) return -ETIME; -#endif return 0; - } int smu_v14_0_init_pptable_microcode(struct smu_context *smu) @@ -165,6 +173,10 @@ int smu_v14_0_init_pptable_microcode(struct smu_context *smu) if (!adev->scpm_enabled) return 0; + if ((amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 2)) || + (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 3))) + return 0; + /* override pptable_id from driver parameter */ if (amdgpu_smu_pptable_id >= 0) { pptable_id = amdgpu_smu_pptable_id; @@ -198,7 +210,12 @@ int smu_v14_0_check_fw_status(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; uint32_t mp1_fw_flags; - mp1_fw_flags = RREG32_PCIE(MP1_Public | + if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || + amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS_14_0_0 & 0xffffffff)); + else + mp1_fw_flags = RREG32_PCIE(MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); if ((mp1_fw_flags & MP1_CRU1_MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> @@ -227,16 +244,16 @@ int smu_v14_0_check_fw_version(struct smu_context *smu) adev->pm.fw_version = smu_version; switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { - case IP_VERSION(14, 0, 2): - smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2; - break; case IP_VERSION(14, 0, 0): smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0; break; case IP_VERSION(14, 0, 1): - smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0; + smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_1; + break; + case IP_VERSION(14, 0, 2): + case IP_VERSION(14, 0, 3): + smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_2; break; - default: dev_err(adev->dev, "smu unsupported IP version: 0x%x.\n", amdgpu_ip_version(adev, MP1_HWIP, 0)); @@ -738,9 +755,9 @@ int smu_v14_0_gfx_off_control(struct smu_context *smu, bool enable) struct amdgpu_device *adev = smu->adev; switch (amdgpu_ip_version(adev, MP1_HWIP, 0)) { - case IP_VERSION(14, 0, 2): case IP_VERSION(14, 0, 0): case IP_VERSION(14, 0, 1): + case IP_VERSION(14, 0, 2): if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) @@ -841,9 +858,16 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev, // TODO /* For MP1 SW irqs */ - val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); - WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val); + if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || + amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0, val); + } else { + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val); + } break; case AMDGPU_IRQ_STATE_ENABLE: @@ -851,14 +875,26 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev, // TODO /* For MP1 SW irqs */ - val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); - WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val); + if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0) || + amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) { + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_mp1_14_0_0); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_mp1_14_0_0, val); - val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0); - WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val); + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0, val); + } else { + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT, val); + + val = RREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0); + WREG32_SOC15(MP1, 0, regMP1_SMN_IH_SW_INT_CTRL, val); + } break; default: @@ -868,11 +904,32 @@ static int smu_v14_0_set_irq_state(struct amdgpu_device *adev, return 0; } +#define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ +#define THM_11_0__SRCID__THM_DIG_THERM_H2L 1 /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL */ + static int smu_v14_0_irq_process(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { - // TODO + struct smu_context *smu = adev->powerplay.pp_handle; + uint32_t client_id = entry->client_id; + uint32_t src_id = entry->src_id; + + if (client_id == SOC15_IH_CLIENTID_THM) { + switch (src_id) { + case THM_11_0__SRCID__THM_DIG_THERM_L2H: + schedule_delayed_work(&smu->swctf_delayed_work, + msecs_to_jiffies(AMDGPU_SWCTF_EXTRA_DELAY)); + break; + case THM_11_0__SRCID__THM_DIG_THERM_H2L: + dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n"); + break; + default: + dev_emerg(adev->dev, "ERROR: GPU under temperature range unknown src id (%d)\n", + src_id); + break; + } + } return 0; } @@ -894,7 +951,17 @@ int smu_v14_0_register_irq_handler(struct smu_context *smu) irq_src->num_types = 1; irq_src->funcs = &smu_v14_0_irq_funcs; - // TODO: THM related + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, + THM_11_0__SRCID__THM_DIG_THERM_L2H, + irq_src); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, + THM_11_0__SRCID__THM_DIG_THERM_H2L, + irq_src); + if (ret) + return ret; ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1, SMU_IH_INTERRUPT_ID_TO_DRIVER, @@ -1590,23 +1657,27 @@ int smu_v14_0_baco_set_armd3_sequence(struct smu_context *smu, return 0; } -bool smu_v14_0_baco_is_support(struct smu_context *smu) +int smu_v14_0_get_bamaco_support(struct smu_context *smu) { struct smu_baco_context *smu_baco = &smu->smu_baco; + int bamaco_support = 0; if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support) - return false; + return 0; + + if (smu_baco->maco_support) + bamaco_support |= MACO_SUPPORT; /* return true if ASIC is in BACO state already */ if (smu_v14_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER) - return true; + return (bamaco_support |= BACO_SUPPORT); if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) - return false; + return 0; - return true; + return (bamaco_support |= BACO_SUPPORT); } enum smu_baco_state smu_v14_0_baco_get_state(struct smu_context *smu) @@ -1629,7 +1700,7 @@ int smu_v14_0_baco_set_state(struct smu_context *smu, if (state == SMU_BACO_STATE_ENTER) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, - smu_baco->maco_support ? + (adev->pm.rpm_mode == AMDGPU_RUNPM_BAMACO) ? BACO_SEQ_BAMACO : BACO_SEQ_BACO, NULL); } else { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c index d6de6d97286c..e4419e1561ef 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c @@ -161,7 +161,7 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu) SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), + SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); @@ -171,7 +171,7 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu) goto err0_out; smu_table->metrics_time = 0; - smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); + smu_table->clocks_table = kzalloc(max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)), GFP_KERNEL); if (!smu_table->clocks_table) goto err1_out; @@ -362,6 +362,12 @@ static int smu_v14_0_0_read_sensor(struct smu_context *smu, (uint32_t *)data); *size = 4; break; + case AMDGPU_PP_SENSOR_VCN_LOAD: + ret = smu_v14_0_0_get_smu_metrics_data(smu, + METRICS_AVERAGE_VCNACTIVITY, + (uint32_t *)data); + *size = 4; + break; case AMDGPU_PP_SENSOR_GPU_AVG_POWER: ret = smu_v14_0_0_get_smu_metrics_data(smu, METRICS_AVERAGE_SOCKETPOWER, @@ -593,6 +599,60 @@ static int smu_v14_0_0_mode2_reset(struct smu_context *smu) return ret; } +static int smu_v14_0_1_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t dpm_level, + uint32_t *freq) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + if (!clk_table || clk_type >= SMU_CLK_COUNT) + return -EINVAL; + + switch (clk_type) { + case SMU_SOCCLK: + if (dpm_level >= clk_table->NumSocClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->SocClocks[dpm_level]; + break; + case SMU_VCLK: + if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->VClocks0[dpm_level]; + break; + case SMU_DCLK: + if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->DClocks0[dpm_level]; + break; + case SMU_VCLK1: + if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->VClocks1[dpm_level]; + break; + case SMU_DCLK1: + if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->DClocks1[dpm_level]; + break; + case SMU_UCLK: + case SMU_MCLK: + if (dpm_level >= clk_table->NumMemPstatesEnabled) + return -EINVAL; + *freq = clk_table->MemPstateTable[dpm_level].MemClk; + break; + case SMU_FCLK: + if (dpm_level >= clk_table->NumFclkLevelsEnabled) + return -EINVAL; + *freq = clk_table->FclkClocks_Freq[dpm_level]; + break; + default: + return -EINVAL; + } + + return 0; +} + static int smu_v14_0_0_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t dpm_level, @@ -637,6 +697,19 @@ static int smu_v14_0_0_get_dpm_freq_by_index(struct smu_context *smu, return 0; } +static int smu_v14_0_common_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t dpm_level, + uint32_t *freq) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); + + return 0; +} + static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type) { @@ -657,6 +730,8 @@ static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, break; case SMU_VCLK: case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: feature_id = SMU_FEATURE_VCN_DPM_BIT; break; default: @@ -666,6 +741,126 @@ static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, return smu_cmn_feature_is_enabled(smu, feature_id); } +static int smu_v14_0_1_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + uint32_t clock_limit; + uint32_t max_dpm_level, min_dpm_level; + int ret = 0; + + if (!smu_v14_0_0_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_FCLK: + clock_limit = smu->smu_table.boot_values.fclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + case SMU_VCLK: + case SMU_VCLK1: + clock_limit = smu->smu_table.boot_values.vclk; + break; + case SMU_DCLK: + case SMU_DCLK1: + clock_limit = smu->smu_table.boot_values.dclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } + + if (max) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + *max = clk_table->MaxGfxClk; + break; + case SMU_MCLK: + case SMU_UCLK: + case SMU_FCLK: + max_dpm_level = 0; + break; + case SMU_SOCCLK: + max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1; + break; + case SMU_VCLK: + case SMU_DCLK: + max_dpm_level = clk_table->Vcn0ClkLevelsEnabled - 1; + break; + case SMU_VCLK1: + case SMU_DCLK1: + max_dpm_level = clk_table->Vcn1ClkLevelsEnabled - 1; + break; + default: + ret = -EINVAL; + goto failed; + } + + if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); + if (ret) + goto failed; + } + } + + if (min) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + *min = clk_table->MinGfxClk; + break; + case SMU_MCLK: + case SMU_UCLK: + min_dpm_level = clk_table->NumMemPstatesEnabled - 1; + break; + case SMU_FCLK: + min_dpm_level = clk_table->NumFclkLevelsEnabled - 1; + break; + case SMU_SOCCLK: + min_dpm_level = 0; + break; + case SMU_VCLK: + case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: + min_dpm_level = 0; + break; + default: + ret = -EINVAL; + goto failed; + } + + if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); + if (ret) + goto failed; + } + } + +failed: + return ret; +} + static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, @@ -736,7 +931,7 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, } if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); if (ret) goto failed; } @@ -768,7 +963,7 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, } if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); if (ret) goto failed; } @@ -778,6 +973,19 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, return ret; } +static int smu_v14_0_common_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_ultimate_freq(smu, clk_type, min, max); + + return 0; +} + static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *value) @@ -811,6 +1019,37 @@ static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu, return smu_v14_0_0_get_smu_metrics_data(smu, member_type, value); } +static int smu_v14_0_1_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *count) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + switch (clk_type) { + case SMU_SOCCLK: + *count = clk_table->NumSocClkLevelsEnabled; + break; + case SMU_VCLK: + case SMU_DCLK: + *count = clk_table->Vcn0ClkLevelsEnabled; + break; + case SMU_VCLK1: + case SMU_DCLK1: + *count = clk_table->Vcn1ClkLevelsEnabled; + break; + case SMU_MCLK: + *count = clk_table->NumMemPstatesEnabled; + break; + case SMU_FCLK: + *count = clk_table->NumFclkLevelsEnabled; + break; + default: + break; + } + + return 0; +} + static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *count) @@ -840,6 +1079,18 @@ static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu, return 0; } +static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *count) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_level_count(smu, clk_type, count); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_level_count(smu, clk_type, count); + + return 0; +} + static int smu_v14_0_0_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { @@ -866,18 +1117,20 @@ static int smu_v14_0_0_print_clk_levels(struct smu_context *smu, case SMU_SOCCLK: case SMU_VCLK: case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: case SMU_MCLK: case SMU_FCLK: ret = smu_v14_0_0_get_current_clk_freq(smu, clk_type, &cur_value); if (ret) break; - ret = smu_v14_0_0_get_dpm_level_count(smu, clk_type, &count); + ret = smu_v14_0_common_get_dpm_level_count(smu, clk_type, &count); if (ret) break; for (i = 0; i < count; i++) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, i, &value); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, i, &value); if (ret) break; @@ -940,8 +1193,13 @@ static int smu_v14_0_0_set_soft_freq_limited_range(struct smu_context *smu, break; case SMU_VCLK: case SMU_DCLK: - msg_set_min = SMU_MSG_SetHardMinVcn; - msg_set_max = SMU_MSG_SetSoftMaxVcn; + msg_set_min = SMU_MSG_SetHardMinVcn0; + msg_set_max = SMU_MSG_SetSoftMaxVcn0; + break; + case SMU_VCLK1: + case SMU_DCLK1: + msg_set_min = SMU_MSG_SetHardMinVcn1; + msg_set_max = SMU_MSG_SetSoftMaxVcn1; break; default: return -EINVAL; @@ -971,11 +1229,11 @@ static int smu_v14_0_0_force_clk_levels(struct smu_context *smu, case SMU_FCLK: case SMU_VCLK: case SMU_DCLK: - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); if (ret) break; - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); if (ret) break; @@ -1000,25 +1258,25 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu, switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max); sclk_min = sclk_max; fclk_min = fclk_max; socclk_min = socclk_max; break; case AMD_DPM_FORCED_LEVEL_LOW: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL); sclk_max = sclk_min; fclk_max = fclk_min; socclk_max = socclk_min; break; case AMD_DPM_FORCED_LEVEL_AUTO: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max); break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -1067,6 +1325,18 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu, return ret; } +static int smu_v14_0_1_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; + smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; + smu->gfx_actual_hard_min_freq = 0; + smu->gfx_actual_soft_max_freq = 0; + + return 0; +} + static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) { DpmClocks_t *clk_table = smu->smu_table.clocks_table; @@ -1079,6 +1349,16 @@ static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *sm return 0; } +static int smu_v14_0_common_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_set_fine_grain_gfx_freq_parameters(smu); + + return 0; +} + static int smu_v14_0_0_set_vpe_enable(struct smu_context *smu, bool enable) { @@ -1095,6 +1375,25 @@ static int smu_v14_0_0_set_umsch_mm_enable(struct smu_context *smu, 0, NULL); } +static int smu_14_0_1_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + uint8_t idx; + + /* Only the Clock information of SOC and VPE is copied to provide VPE DPM settings for use. */ + for (idx = 0; idx < NUM_SOCCLK_DPM_LEVELS; idx++) { + clock_table->SocClocks[idx].Freq = (idx < clk_table->NumSocClkLevelsEnabled) ? clk_table->SocClocks[idx]:0; + clock_table->SocClocks[idx].Vol = 0; + } + + for (idx = 0; idx < NUM_VPE_DPM_LEVELS; idx++) { + clock_table->VPEClocks[idx].Freq = (idx < clk_table->VpeClkLevelsEnabled) ? clk_table->VPEClocks[idx]:0; + clock_table->VPEClocks[idx].Vol = 0; + } + + return 0; +} + static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) { DpmClocks_t *clk_table = smu->smu_table.clocks_table; @@ -1114,6 +1413,16 @@ static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks * return 0; } +static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_14_0_0_get_dpm_table(smu, clock_table); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_14_0_1_get_dpm_table(smu, clock_table); + + return 0; +} + static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { .check_fw_status = smu_v14_0_check_fw_status, .check_fw_version = smu_v14_0_check_fw_version, @@ -1135,16 +1444,16 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { .set_driver_table_location = smu_v14_0_set_driver_table_location, .gfx_off_control = smu_v14_0_gfx_off_control, .mode2_reset = smu_v14_0_0_mode2_reset, - .get_dpm_ultimate_freq = smu_v14_0_0_get_dpm_ultimate_freq, + .get_dpm_ultimate_freq = smu_v14_0_common_get_dpm_ultimate_freq, .od_edit_dpm_table = smu_v14_0_od_edit_dpm_table, .print_clk_levels = smu_v14_0_0_print_clk_levels, .force_clk_levels = smu_v14_0_0_force_clk_levels, .set_performance_level = smu_v14_0_0_set_performance_level, - .set_fine_grain_gfx_freq_parameters = smu_v14_0_0_set_fine_grain_gfx_freq_parameters, + .set_fine_grain_gfx_freq_parameters = smu_v14_0_common_set_fine_grain_gfx_freq_parameters, .set_gfx_power_up_by_imu = smu_v14_0_set_gfx_power_up_by_imu, .dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable, .dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable, - .get_dpm_clock_table = smu_14_0_0_get_dpm_table, + .get_dpm_clock_table = smu_v14_0_common_get_dpm_table, }; static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c new file mode 100644 index 000000000000..706265220292 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -0,0 +1,1796 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include +#include +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "smu_v14_0.h" +#include "smu14_driver_if_v14_0.h" +#include "soc15_common.h" +#include "atom.h" +#include "smu_v14_0_2_ppt.h" +#include "smu_v14_0_2_pptable.h" +#include "smu_v14_0_2_ppsmc.h" +#include "mp/mp_14_0_2_offset.h" +#include "mp/mp_14_0_2_sh_mask.h" + +#include "smu_cmn.h" +#include "amdgpu_ras.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) + +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_FCLK_BIT)) + +#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000 + +static struct cmn2asic_msg_mapping smu_v14_0_2_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 1), + MSG_MAP(SetAllowedFeaturesMaskLow, PPSMC_MSG_SetAllowedFeaturesMaskLow, 0), + MSG_MAP(SetAllowedFeaturesMaskHigh, PPSMC_MSG_SetAllowedFeaturesMaskHigh, 0), + MSG_MAP(EnableAllSmuFeatures, PPSMC_MSG_EnableAllSmuFeatures, 0), + MSG_MAP(DisableAllSmuFeatures, PPSMC_MSG_DisableAllSmuFeatures, 0), + MSG_MAP(EnableSmuFeaturesLow, PPSMC_MSG_EnableSmuFeaturesLow, 1), + MSG_MAP(EnableSmuFeaturesHigh, PPSMC_MSG_EnableSmuFeaturesHigh, 1), + MSG_MAP(DisableSmuFeaturesLow, PPSMC_MSG_DisableSmuFeaturesLow, 1), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetRunningSmuFeaturesLow, 1), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetRunningSmuFeaturesHigh, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 1), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 1), + MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 1), + MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 0), + MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 0), + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 0), + MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 0), + MSG_MAP(GetDcModeMaxDpmFreq, PPSMC_MSG_GetDcModeMaxDpmFreq, 1), + MSG_MAP(OverridePcieParameters, PPSMC_MSG_OverridePcieParameters, 0), + MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(AllowGfxOff, PPSMC_MSG_AllowGfxOff, 0), + MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisallowGfxOff, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), + MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), + MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), + MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), + MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0), + MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), + MSG_MAP(SetNumBadMemoryPagesRetired, PPSMC_MSG_SetNumBadMemoryPagesRetired, 0), + MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel, + PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, 0), + MSG_MAP(AllowIHHostInterrupt, PPSMC_MSG_AllowIHHostInterrupt, 0), + MSG_MAP(ReenableAcDcInterrupt, PPSMC_MSG_ReenableAcDcInterrupt, 0), +}; + +static struct cmn2asic_mapping smu_v14_0_2_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, PPCLK_GFXCLK), + CLK_MAP(SCLK, PPCLK_GFXCLK), + CLK_MAP(SOCCLK, PPCLK_SOCCLK), + CLK_MAP(FCLK, PPCLK_FCLK), + CLK_MAP(UCLK, PPCLK_UCLK), + CLK_MAP(MCLK, PPCLK_UCLK), + CLK_MAP(VCLK, PPCLK_VCLK_0), + CLK_MAP(DCLK, PPCLK_DCLK_0), +}; + +static struct cmn2asic_mapping smu_v14_0_2_feature_mask_map[SMU_FEATURE_COUNT] = { + FEA_MAP(FW_DATA_READ), + FEA_MAP(DPM_GFXCLK), + FEA_MAP(DPM_GFX_POWER_OPTIMIZER), + FEA_MAP(DPM_UCLK), + FEA_MAP(DPM_FCLK), + FEA_MAP(DPM_SOCCLK), + FEA_MAP(DPM_LINK), + FEA_MAP(DPM_DCN), + FEA_MAP(VMEMP_SCALING), + FEA_MAP(VDDIO_MEM_SCALING), + FEA_MAP(DS_GFXCLK), + FEA_MAP(DS_SOCCLK), + FEA_MAP(DS_FCLK), + FEA_MAP(DS_LCLK), + FEA_MAP(DS_DCFCLK), + FEA_MAP(DS_UCLK), + FEA_MAP(GFX_ULV), + FEA_MAP(FW_DSTATE), + FEA_MAP(GFXOFF), + FEA_MAP(BACO), + FEA_MAP(MM_DPM), + FEA_MAP(SOC_MPCLK_DS), + FEA_MAP(BACO_MPCLK_DS), + FEA_MAP(THROTTLERS), + FEA_MAP(SMARTSHIFT), + FEA_MAP(GTHR), + FEA_MAP(ACDC), + FEA_MAP(VR0HOT), + FEA_MAP(FW_CTF), + FEA_MAP(FAN_CONTROL), + FEA_MAP(GFX_DCS), + FEA_MAP(GFX_READ_MARGIN), + FEA_MAP(LED_DISPLAY), + FEA_MAP(GFXCLK_SPREAD_SPECTRUM), + FEA_MAP(OUT_OF_BAND_MONITOR), + FEA_MAP(OPTIMIZED_VMIN), + FEA_MAP(GFX_IMU), + FEA_MAP(BOOT_TIME_CAL), + FEA_MAP(GFX_PCC_DFLL), + FEA_MAP(SOC_CG), + FEA_MAP(DF_CSTATE), + FEA_MAP(GFX_EDC), + FEA_MAP(BOOT_POWER_OPT), + FEA_MAP(CLOCK_POWER_DOWN_BYPASS), + FEA_MAP(DS_VCN), + FEA_MAP(BACO_CG), + FEA_MAP(MEM_TEMP_READ), + FEA_MAP(ATHUB_MMHUB_PG), + FEA_MAP(SOC_PCC), + [SMU_FEATURE_DPM_VCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, + [SMU_FEATURE_DPM_DCLK_BIT] = {1, FEATURE_MM_DPM_BIT}, + [SMU_FEATURE_PPT_BIT] = {1, FEATURE_THROTTLERS_BIT}, +}; + +static struct cmn2asic_mapping smu_v14_0_2_table_map[SMU_TABLE_COUNT] = { + TAB_MAP(PPTABLE), + TAB_MAP(WATERMARKS), + TAB_MAP(AVFS_PSM_DEBUG), + TAB_MAP(PMSTATUSLOG), + TAB_MAP(SMU_METRICS), + TAB_MAP(DRIVER_SMU_CONFIG), + TAB_MAP(ACTIVITY_MONITOR_COEFF), + [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE}, + TAB_MAP(I2C_COMMANDS), + TAB_MAP(ECCINFO), +}; + +static struct cmn2asic_mapping smu_v14_0_2_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { + PWR_MAP(AC), + PWR_MAP(DC), +}; + +static struct cmn2asic_mapping smu_v14_0_2_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_WINDOW3D, WORKLOAD_PPLIB_WINDOW_3D_BIT), +}; + +#if 0 +static const uint8_t smu_v14_0_2_throttler_map[] = { + [THROTTLER_PPT0_BIT] = (SMU_THROTTLER_PPT0_BIT), + [THROTTLER_PPT1_BIT] = (SMU_THROTTLER_PPT1_BIT), + [THROTTLER_PPT2_BIT] = (SMU_THROTTLER_PPT2_BIT), + [THROTTLER_PPT3_BIT] = (SMU_THROTTLER_PPT3_BIT), + [THROTTLER_TDC_GFX_BIT] = (SMU_THROTTLER_TDC_GFX_BIT), + [THROTTLER_TDC_SOC_BIT] = (SMU_THROTTLER_TDC_SOC_BIT), + [THROTTLER_TEMP_EDGE_BIT] = (SMU_THROTTLER_TEMP_EDGE_BIT), + [THROTTLER_TEMP_HOTSPOT_BIT] = (SMU_THROTTLER_TEMP_HOTSPOT_BIT), + [THROTTLER_TEMP_MEM_BIT] = (SMU_THROTTLER_TEMP_MEM_BIT), + [THROTTLER_TEMP_VR_GFX_BIT] = (SMU_THROTTLER_TEMP_VR_GFX_BIT), + [THROTTLER_TEMP_VR_SOC_BIT] = (SMU_THROTTLER_TEMP_VR_SOC_BIT), + [THROTTLER_TEMP_VR_MEM0_BIT] = (SMU_THROTTLER_TEMP_VR_MEM0_BIT), + [THROTTLER_TEMP_VR_MEM1_BIT] = (SMU_THROTTLER_TEMP_VR_MEM1_BIT), + [THROTTLER_TEMP_LIQUID0_BIT] = (SMU_THROTTLER_TEMP_LIQUID0_BIT), + [THROTTLER_TEMP_LIQUID1_BIT] = (SMU_THROTTLER_TEMP_LIQUID1_BIT), + [THROTTLER_GFX_APCC_PLUS_BIT] = (SMU_THROTTLER_APCC_BIT), + [THROTTLER_FIT_BIT] = (SMU_THROTTLER_FIT_BIT), +}; +#endif + +static int +smu_v14_0_2_get_allowed_feature_mask(struct smu_context *smu, + uint32_t *feature_mask, uint32_t num) +{ + struct amdgpu_device *adev = smu->adev; + /*u32 smu_version;*/ + + if (num > 2) + return -EINVAL; + + memset(feature_mask, 0xff, sizeof(uint32_t) * num); + + if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) { + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_IMU_BIT); + } +#if 0 + if (!(adev->pg_flags & AMD_PG_SUPPORT_ATHUB) || + !(adev->pg_flags & AMD_PG_SUPPORT_MMHUB)) + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_ATHUB_MMHUB_PG_BIT); + + if (!(adev->pm.pp_feature & PP_SOCCLK_DPM_MASK)) + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + /* PMFW 78.58 contains a critical fix for gfxoff feature */ + smu_cmn_get_smc_version(smu, NULL, &smu_version); + if ((smu_version < 0x004e3a00) || + !(adev->pm.pp_feature & PP_GFXOFF_MASK)) + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFXOFF_BIT); + + if (!(adev->pm.pp_feature & PP_MCLK_DPM_MASK)) { + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_UCLK_BIT); + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VMEMP_SCALING_BIT); + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_VDDIO_MEM_SCALING_BIT); + } + + if (!(adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK)) + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); + + if (!(adev->pm.pp_feature & PP_PCIE_DPM_MASK)) { + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DPM_LINK_BIT); + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_DS_LCLK_BIT); + } + + if (!(adev->pm.pp_feature & PP_ULV_MASK)) + *(uint64_t *)feature_mask &= ~FEATURE_MASK(FEATURE_GFX_ULV_BIT); +#endif + + return 0; +} + +static int smu_v14_0_2_check_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_14_0_2_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + PPTable_t *pptable = smu->smu_table.driver_pptable; + const OverDriveLimits_t * const overdrive_upperlimits = + &pptable->SkuTable.OverDriveLimitsBasicMax; + const OverDriveLimits_t * const overdrive_lowerlimits = + &pptable->SkuTable.OverDriveLimitsBasicMin; + + if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_HARDWAREDC) + smu->dc_controlled_by_gpio = true; + + if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_BACO) { + smu_baco->platform_support = true; + + if (powerplay_table->platform_caps & SMU_14_0_2_PP_PLATFORM_CAP_MACO) + smu_baco->maco_support = true; + } + + if (!overdrive_lowerlimits->FeatureCtrlMask || + !overdrive_upperlimits->FeatureCtrlMask) + smu->od_enabled = false; + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + /* + * Instead of having its own buffer space and get overdrive_table copied, + * smu->od_settings just points to the actual overdrive_table + */ + smu->od_settings = &powerplay_table->overdrive_table; + + smu->adev->pm.no_fan = + !(pptable->PFE_Settings.FeaturesToRun[0] & (1 << FEATURE_FAN_CONTROL_BIT)); + + return 0; +} + +static int smu_v14_0_2_store_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_14_0_2_powerplay_table *powerplay_table = + table_context->power_play_table; + + memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, + sizeof(PPTable_t)); + + return 0; +} + +#ifndef atom_smc_dpm_info_table_14_0_0 +struct atom_smc_dpm_info_table_14_0_0 { + struct atom_common_table_header table_header; + BoardTable_t BoardTable; +}; +#endif + +static int smu_v14_0_2_append_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + struct atom_smc_dpm_info_table_14_0_0 *smc_dpm_table; + BoardTable_t *BoardTable = &smc_pptable->BoardTable; + int index, ret; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smc_dpm_info); + + ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table); + if (ret) + return ret; + + memcpy(BoardTable, &smc_dpm_table->BoardTable, sizeof(BoardTable_t)); + + return 0; +} + +#if 0 +static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu, + void **table, + uint32_t *size) +{ + struct smu_table_context *smu_table = &smu->smu_table; + void *combo_pptable = smu_table->combo_pptable; + int ret = 0; + + ret = smu_cmn_get_combo_pptable(smu); + if (ret) + return ret; + + *table = combo_pptable; + *size = sizeof(struct smu_14_0_powerplay_table); + + return 0; +} +#endif + +static int smu_v14_0_2_get_pptable_from_pmfw(struct smu_context *smu, + void **table, + uint32_t *size) +{ + struct smu_table_context *smu_table = &smu->smu_table; + void *combo_pptable = smu_table->combo_pptable; + int ret = 0; + + ret = smu_cmn_get_combo_pptable(smu); + if (ret) + return ret; + + *table = combo_pptable; + *size = sizeof(struct smu_14_0_2_powerplay_table); + + return 0; +} + +static int smu_v14_0_2_setup_pptable(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if (amdgpu_sriov_vf(smu->adev)) + return 0; + + if (!adev->scpm_enabled) + ret = smu_v14_0_setup_pptable(smu); + else + ret = smu_v14_0_2_get_pptable_from_pmfw(smu, + &smu_table->power_play_table, + &smu_table->power_play_table_size); + if (ret) + return ret; + + ret = smu_v14_0_2_store_powerplay_table(smu); + if (ret) + return ret; + + /* + * With SCPM enabled, the operation below will be handled + * by PSP. Driver involvment is unnecessary and useless. + */ + if (!adev->scpm_enabled) { + ret = smu_v14_0_2_append_powerplay_table(smu); + if (ret) + return ret; + } + + ret = smu_v14_0_2_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; +} + +static int smu_v14_0_2_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetricsExternal_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, + sizeof(DpmActivityMonitorCoeffIntExternal_t), PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_COMBO_PPTABLE, MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ECCINFO, sizeof(EccInfoTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(sizeof(SmuMetricsExternal_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err0_out; + smu_table->metrics_time = 0; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_3); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); + if (!smu_table->watermarks_table) + goto err2_out; + + smu_table->ecc_table = kzalloc(tables[SMU_TABLE_ECCINFO].size, GFP_KERNEL); + if (!smu_table->ecc_table) + goto err3_out; + + return 0; + +err3_out: + kfree(smu_table->watermarks_table); +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; +} + +static int smu_v14_0_2_allocate_dpm_context(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_14_0_dpm_context), + GFP_KERNEL); + if (!smu_dpm->dpm_context) + return -ENOMEM; + + smu_dpm->dpm_context_size = sizeof(struct smu_14_0_dpm_context); + + return 0; +} + +static int smu_v14_0_2_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v14_0_2_tables_init(smu); + if (ret) + return ret; + + ret = smu_v14_0_2_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v14_0_init_smc_tables(smu); +} + +static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + SkuTable_t *skutable = &pptable->SkuTable; + struct smu_14_0_dpm_table *dpm_table; + struct smu_14_0_pcie_table *pcie_table; + uint32_t link_level; + int ret = 0; + + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + + /* + * Update the reported maximum shader clock to the value + * which can be guarded to be achieved on all cards. This + * is aligned with Window setting. And considering that value + * might be not the peak frequency the card can achieve, it + * is normal some real-time clock frequency can overtake this + * labelled maximum clock frequency(for example in pp_dpm_sclk + * sysfs output). + */ + if (skutable->DriverReportedClocks.GameClockAc && + (dpm_table->dpm_levels[dpm_table->count - 1].value > + skutable->DriverReportedClocks.GameClockAc)) { + dpm_table->dpm_levels[dpm_table->count - 1].value = + skutable->DriverReportedClocks.GameClockAc; + dpm_table->max = skutable->DriverReportedClocks.GameClockAc; + } + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* vclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* dclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) { + ret = smu_v14_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* lclk dpm table setup */ + pcie_table = &dpm_context->dpm_tables.pcie_table; + pcie_table->num_of_link_levels = 0; + for (link_level = 0; link_level < NUM_LINK_LEVELS; link_level++) { + if (!skutable->PcieGenSpeed[link_level] && + !skutable->PcieLaneCount[link_level] && + !skutable->LclkFreq[link_level]) + continue; + + pcie_table->pcie_gen[pcie_table->num_of_link_levels] = + skutable->PcieGenSpeed[link_level]; + pcie_table->pcie_lane[pcie_table->num_of_link_levels] = + skutable->PcieLaneCount[link_level]; + pcie_table->clk_freq[pcie_table->num_of_link_levels] = + skutable->LclkFreq[link_level]; + pcie_table->num_of_link_levels++; + } + + return 0; +} + +static bool smu_v14_0_2_is_dpm_running(struct smu_context *smu) +{ + int ret = 0; + uint64_t feature_enabled; + + ret = smu_cmn_get_enabled_mask(smu, &feature_enabled); + if (ret) + return false; + + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static void smu_v14_0_2_dump_pptable(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + PFE_Settings_t *PFEsettings = &pptable->PFE_Settings; + + dev_info(smu->adev->dev, "Dumped PPTable:\n"); + + dev_info(smu->adev->dev, "Version = 0x%08x\n", PFEsettings->Version); + dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", PFEsettings->FeaturesToRun[0]); + dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", PFEsettings->FeaturesToRun[1]); +} + +static uint32_t smu_v14_0_2_get_throttler_status(SmuMetrics_t *metrics) +{ + uint32_t throttler_status = 0; + int i; + + for (i = 0; i < THROTTLER_COUNT; i++) + throttler_status |= + (metrics->ThrottlingPercentage[i] ? 1U << i : 0); + + return throttler_status; +} + +#define SMU_14_0_2_BUSY_THRESHOLD 5 +static int smu_v14_0_2_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table = &smu->smu_table; + SmuMetrics_t *metrics = + &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + NULL, + false); + if (ret) + return ret; + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK_0]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK_0]; + break; + case METRICS_CURR_FCLK: + *value = metrics->CurrClock[PPCLK_FCLK]; + break; + case METRICS_CURR_DCEFCLK: + *value = metrics->CurrClock[PPCLK_DCFCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + if (metrics->AverageGfxActivity <= SMU_14_0_2_BUSY_THRESHOLD) + *value = metrics->AverageGfxclkFrequencyPostDs; + else + *value = metrics->AverageGfxclkFrequencyPreDs; + break; + case METRICS_AVERAGE_FCLK: + if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) + *value = metrics->AverageFclkFrequencyPostDs; + else + *value = metrics->AverageFclkFrequencyPreDs; + break; + case METRICS_AVERAGE_UCLK: + if (metrics->AverageUclkActivity <= SMU_14_0_2_BUSY_THRESHOLD) + *value = metrics->AverageMemclkFrequencyPostDs; + else + *value = metrics->AverageMemclkFrequencyPreDs; + break; + case METRICS_AVERAGE_VCLK: + *value = metrics->AverageVclk0Frequency; + break; + case METRICS_AVERAGE_DCLK: + *value = metrics->AverageDclk0Frequency; + break; + case METRICS_AVERAGE_VCLK1: + *value = metrics->AverageVclk1Frequency; + break; + case METRICS_AVERAGE_DCLK1: + *value = metrics->AverageDclk1Frequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->AvgTemperature[TEMP_EDGE] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->AvgTemperature[TEMP_HOTSPOT] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->AvgTemperature[TEMP_MEM] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->AvgTemperature[TEMP_VR_GFX] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->AvgTemperature[TEMP_VR_SOC] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = smu_v14_0_2_get_throttler_status(metrics); + break; + case METRICS_CURR_FANSPEED: + *value = metrics->AvgFanRpm; + break; + case METRICS_CURR_FANPWM: + *value = metrics->AvgFanPwm; + break; + case METRICS_VOLTAGE_VDDGFX: + *value = metrics->AvgVoltage[SVI_PLANE_VDD_GFX]; + break; + case METRICS_PCIE_RATE: + *value = metrics->PcieRate; + break; + case METRICS_PCIE_WIDTH: + *value = metrics->PcieWidth; + break; + default: + *value = UINT_MAX; + break; + } + + return ret; +} + +static int smu_v14_0_2_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + struct smu_14_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_14_0_dpm_table *dpm_table; + + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + /* uclk dpm table */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + break; + case SMU_GFXCLK: + case SMU_SCLK: + /* gfxclk dpm table */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + break; + case SMU_SOCCLK: + /* socclk dpm table */ + dpm_table = &dpm_context->dpm_tables.soc_table; + break; + case SMU_FCLK: + /* fclk dpm table */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + break; + case SMU_VCLK: + case SMU_VCLK1: + /* vclk dpm table */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + break; + case SMU_DCLK: + case SMU_DCLK1: + /* dclk dpm table */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + break; + default: + dev_err(smu->adev->dev, "Unsupported clock type!\n"); + return -EINVAL; + } + + if (min) + *min = dpm_table->min; + if (max) + *max = dpm_table->max; + + return 0; +} + +static int smu_v14_0_2_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, + uint32_t *size) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + int ret = 0; + + switch (sensor) { + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *(uint16_t *)data = smc_pptable->CustomSkuTable.FanMaximumRpm; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_AVG_POWER: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_CURR_UCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXCLK, + (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v14_0_2_get_smu_metrics_data(smu, + METRICS_VOLTAGE_VDDGFX, + (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + + return ret; +} + +static int smu_v14_0_2_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return -EINVAL; + + switch (clk_id) { + case PPCLK_GFXCLK: + member_type = METRICS_AVERAGE_GFXCLK; + break; + case PPCLK_UCLK: + member_type = METRICS_CURR_UCLK; + break; + case PPCLK_FCLK: + member_type = METRICS_CURR_FCLK; + break; + case PPCLK_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case PPCLK_VCLK_0: + member_type = METRICS_AVERAGE_VCLK; + break; + case PPCLK_DCLK_0: + member_type = METRICS_AVERAGE_DCLK; + break; + default: + return -EINVAL; + } + + return smu_v14_0_2_get_smu_metrics_data(smu, + member_type, + value); +} + +static int smu_v14_0_2_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + char *buf) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; + struct smu_14_0_dpm_table *single_dpm_table; + int i, curr_freq, size = 0; + int ret = 0; + + smu_cmn_get_sysfs_buf(&buf, &size); + + if (amdgpu_ras_intr_triggered()) { + size += sysfs_emit_at(buf, size, "unavailable\n"); + return size; + } + + switch (clk_type) { + case SMU_SCLK: + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + break; + case SMU_MCLK: + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); + break; + case SMU_SOCCLK: + single_dpm_table = &(dpm_context->dpm_tables.soc_table); + break; + case SMU_FCLK: + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); + break; + case SMU_VCLK: + case SMU_VCLK1: + single_dpm_table = &(dpm_context->dpm_tables.vclk_table); + break; + case SMU_DCLK: + case SMU_DCLK1: + single_dpm_table = &(dpm_context->dpm_tables.dclk_table); + break; + default: + break; + } + + switch (clk_type) { + case SMU_SCLK: + case SMU_MCLK: + case SMU_SOCCLK: + case SMU_FCLK: + case SMU_VCLK: + case SMU_VCLK1: + case SMU_DCLK: + case SMU_DCLK1: + ret = smu_v14_0_2_get_current_clk_freq_by_table(smu, clk_type, &curr_freq); + if (ret) { + dev_err(smu->adev->dev, "Failed to get current clock freq!"); + return ret; + } + + if (single_dpm_table->is_fine_grained) { + /* + * For fine grained dpms, there are only two dpm levels: + * - level 0 -> min clock freq + * - level 1 -> max clock freq + * And the current clock frequency can be any value between them. + * So, if the current clock frequency is not at level 0 or level 1, + * we will fake it as three dpm levels: + * - level 0 -> min clock freq + * - level 1 -> current actual clock freq + * - level 2 -> max clock freq + */ + if ((single_dpm_table->dpm_levels[0].value != curr_freq) && + (single_dpm_table->dpm_levels[1].value != curr_freq)) { + size += sysfs_emit_at(buf, size, "0: %uMhz\n", + single_dpm_table->dpm_levels[0].value); + size += sysfs_emit_at(buf, size, "1: %uMhz *\n", + curr_freq); + size += sysfs_emit_at(buf, size, "2: %uMhz\n", + single_dpm_table->dpm_levels[1].value); + } else { + size += sysfs_emit_at(buf, size, "0: %uMhz %s\n", + single_dpm_table->dpm_levels[0].value, + single_dpm_table->dpm_levels[0].value == curr_freq ? "*" : ""); + size += sysfs_emit_at(buf, size, "1: %uMhz %s\n", + single_dpm_table->dpm_levels[1].value, + single_dpm_table->dpm_levels[1].value == curr_freq ? "*" : ""); + } + } else { + for (i = 0; i < single_dpm_table->count; i++) + size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", + i, single_dpm_table->dpm_levels[i].value, + single_dpm_table->dpm_levels[i].value == curr_freq ? "*" : ""); + } + break; + case SMU_PCIE: + // TODO + break; + + default: + break; + } + + return size; +} + +static int smu_v14_0_2_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t mask) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; + struct smu_14_0_dpm_table *single_dpm_table; + uint32_t soft_min_level, soft_max_level; + uint32_t min_freq, max_freq; + int ret = 0; + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + break; + case SMU_MCLK: + case SMU_UCLK: + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); + break; + case SMU_SOCCLK: + single_dpm_table = &(dpm_context->dpm_tables.soc_table); + break; + case SMU_FCLK: + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); + break; + case SMU_VCLK: + case SMU_VCLK1: + single_dpm_table = &(dpm_context->dpm_tables.vclk_table); + break; + case SMU_DCLK: + case SMU_DCLK1: + single_dpm_table = &(dpm_context->dpm_tables.dclk_table); + break; + default: + break; + } + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_SOCCLK: + case SMU_FCLK: + case SMU_VCLK: + case SMU_VCLK1: + case SMU_DCLK: + case SMU_DCLK1: + if (single_dpm_table->is_fine_grained) { + /* There is only 2 levels for fine grained DPM */ + soft_max_level = (soft_max_level >= 1 ? 1 : 0); + soft_min_level = (soft_min_level >= 1 ? 1 : 0); + } else { + if ((soft_max_level >= single_dpm_table->count) || + (soft_min_level >= single_dpm_table->count)) + return -EINVAL; + } + + min_freq = single_dpm_table->dpm_levels[soft_min_level].value; + max_freq = single_dpm_table->dpm_levels[soft_max_level].value; + + ret = smu_v14_0_set_soft_freq_limited_range(smu, + clk_type, + min_freq, + max_freq); + break; + case SMU_DCEFCLK: + case SMU_PCIE: + default: + break; + } + + return ret; +} + +static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu, + uint8_t pcie_gen_cap, + uint8_t pcie_width_cap) +{ + struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_14_0_pcie_table *pcie_table = + &dpm_context->dpm_tables.pcie_table; + uint32_t smu_pcie_arg; + int ret, i; + + for (i = 0; i < pcie_table->num_of_link_levels; i++) { + if (pcie_table->pcie_gen[i] > pcie_gen_cap) + pcie_table->pcie_gen[i] = pcie_gen_cap; + if (pcie_table->pcie_lane[i] > pcie_width_cap) + pcie_table->pcie_lane[i] = pcie_width_cap; + + smu_pcie_arg = i << 16; + smu_pcie_arg |= pcie_table->pcie_gen[i] << 8; + smu_pcie_arg |= pcie_table->pcie_lane[i]; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, + NULL); + if (ret) + return ret; + } + + return 0; +} + +static int smu_v14_0_2_get_thermal_temperature_range(struct smu_context *smu, + struct smu_temperature_range *range) +{ + // TODO + + return 0; +} + +static int smu_v14_0_2_populate_umd_state_clk(struct smu_context *smu) +{ + // TODO + + return 0; +} + +static void smu_v14_0_2_get_unique_id(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + SmuMetrics_t *metrics = + &(((SmuMetricsExternal_t *)(smu_table->metrics_table))->SmuMetrics); + struct amdgpu_device *adev = smu->adev; + uint32_t upper32 = 0, lower32 = 0; + int ret; + + ret = smu_cmn_get_metrics_table(smu, NULL, false); + if (ret) + goto out; + + upper32 = metrics->PublicSerialNumberUpper; + lower32 = metrics->PublicSerialNumberLower; + +out: + adev->unique_id = ((uint64_t)upper32 << 32) | lower32; +} + +static int smu_v14_0_2_get_power_limit(struct smu_context *smu, + uint32_t *current_power_limit, + uint32_t *default_power_limit, + uint32_t *max_power_limit, + uint32_t *min_power_limit) +{ + // TODO + + return 0; +} + +static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu, + char *buf) +{ + DpmActivityMonitorCoeffIntExternal_t activity_monitor_external; + DpmActivityMonitorCoeffInt_t *activity_monitor = + &(activity_monitor_external.DpmActivityMonitorCoeffInt); + static const char *title[] = { + "PROFILE_INDEX(NAME)", + "CLOCK_TYPE(NAME)", + "FPS", + "MinActiveFreqType", + "MinActiveFreq", + "BoosterFreqType", + "BoosterFreq", + "PD_Data_limit_c", + "PD_Data_error_coeff", + "PD_Data_error_rate_coeff"}; + int16_t workload_type = 0; + uint32_t i, size = 0; + int result = 0; + + if (!buf) + return -EINVAL; + + size += sysfs_emit_at(buf, size, "%16s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9]); + + for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) { + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type == -ENOTSUPP) + continue; + else if (workload_type < 0) + return -EINVAL; + + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + workload_type, + (void *)(&activity_monitor_external), + false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return result; + } + + size += sysfs_emit_at(buf, size, "%2d %14s%s:\n", + i, amdgpu_pp_profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + + size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 0, + "GFXCLK", + activity_monitor->Gfx_FPS, + activity_monitor->Gfx_MinActiveFreqType, + activity_monitor->Gfx_MinActiveFreq, + activity_monitor->Gfx_BoosterFreqType, + activity_monitor->Gfx_BoosterFreq, + activity_monitor->Gfx_PD_Data_limit_c, + activity_monitor->Gfx_PD_Data_error_coeff, + activity_monitor->Gfx_PD_Data_error_rate_coeff); + + size += sysfs_emit_at(buf, size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 1, + "FCLK", + activity_monitor->Fclk_FPS, + activity_monitor->Fclk_MinActiveFreqType, + activity_monitor->Fclk_MinActiveFreq, + activity_monitor->Fclk_BoosterFreqType, + activity_monitor->Fclk_BoosterFreq, + activity_monitor->Fclk_PD_Data_limit_c, + activity_monitor->Fclk_PD_Data_error_coeff, + activity_monitor->Fclk_PD_Data_error_rate_coeff); + } + + return size; +} + +static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu, + long *input, + uint32_t size) +{ + DpmActivityMonitorCoeffIntExternal_t activity_monitor_external; + DpmActivityMonitorCoeffInt_t *activity_monitor = + &(activity_monitor_external.DpmActivityMonitorCoeffInt); + int workload_type, ret = 0; + + smu->power_profile_mode = input[size]; + + if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); + return -EINVAL; + } + + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor_external), + false); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return ret; + } + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor->Gfx_FPS = input[1]; + activity_monitor->Gfx_MinActiveFreqType = input[2]; + activity_monitor->Gfx_MinActiveFreq = input[3]; + activity_monitor->Gfx_BoosterFreqType = input[4]; + activity_monitor->Gfx_BoosterFreq = input[5]; + activity_monitor->Gfx_PD_Data_limit_c = input[6]; + activity_monitor->Gfx_PD_Data_error_coeff = input[7]; + activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8]; + break; + case 1: /* Fclk */ + activity_monitor->Fclk_FPS = input[1]; + activity_monitor->Fclk_MinActiveFreqType = input[2]; + activity_monitor->Fclk_MinActiveFreq = input[3]; + activity_monitor->Fclk_BoosterFreqType = input[4]; + activity_monitor->Fclk_BoosterFreq = input[5]; + activity_monitor->Fclk_PD_Data_limit_c = input[6]; + activity_monitor->Fclk_PD_Data_error_coeff = input[7]; + activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8]; + break; + } + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor_external), + true); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); + return ret; + } + } + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + smu->power_profile_mode); + if (workload_type < 0) + return -EINVAL; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetWorkloadMask, + 1 << workload_type, + NULL); +} + +static int smu_v14_0_2_baco_enter(struct smu_context *smu) +{ + struct smu_baco_context *smu_baco = &smu->smu_baco; + struct amdgpu_device *adev = smu->adev; + + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) + return smu_v14_0_baco_set_armd3_sequence(smu, + smu_baco->maco_support ? BACO_SEQ_BAMACO : BACO_SEQ_BACO); + else + return smu_v14_0_baco_enter(smu); +} + +static int smu_v14_0_2_baco_exit(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + if (adev->in_runpm && smu_cmn_is_audio_func_enabled(adev)) { + /* Wait for PMFW handling for the Dstate change */ + usleep_range(10000, 11000); + return smu_v14_0_baco_set_armd3_sequence(smu, BACO_SEQ_ULPS); + } else { + return smu_v14_0_baco_exit(smu); + } +} + +static bool smu_v14_0_2_is_mode1_reset_supported(struct smu_context *smu) +{ + // TODO + + return true; +} + +static int smu_v14_0_2_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msg, int num_msgs) +{ + struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap); + struct amdgpu_device *adev = smu_i2c->adev; + struct smu_context *smu = adev->powerplay.pp_handle; + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *table = &smu_table->driver_table; + SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr; + int i, j, r, c; + u16 dir; + + if (!adev->pm.dpm_enabled) + return -EBUSY; + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) + return -ENOMEM; + + req->I2CcontrollerPort = smu_i2c->port; + req->I2CSpeed = I2C_SPEED_FAST_400K; + req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */ + dir = msg[0].flags & I2C_M_RD; + + for (c = i = 0; i < num_msgs; i++) { + for (j = 0; j < msg[i].len; j++, c++) { + SwI2cCmd_t *cmd = &req->SwI2cCmds[c]; + + if (!(msg[i].flags & I2C_M_RD)) { + /* write */ + cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK; + cmd->ReadWriteData = msg[i].buf[j]; + } + + if ((dir ^ msg[i].flags) & I2C_M_RD) { + /* The direction changes. + */ + dir = msg[i].flags & I2C_M_RD; + cmd->CmdConfig |= CMDCONFIG_RESTART_MASK; + } + + req->NumCmds++; + + /* + * Insert STOP if we are at the last byte of either last + * message for the transaction or the client explicitly + * requires a STOP at this particular message. + */ + if ((j == msg[i].len - 1) && + ((i == num_msgs - 1) || (msg[i].flags & I2C_M_STOP))) { + cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK; + cmd->CmdConfig |= CMDCONFIG_STOP_MASK; + } + } + } + mutex_lock(&adev->pm.mutex); + r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true); + mutex_unlock(&adev->pm.mutex); + if (r) + goto fail; + + for (c = i = 0; i < num_msgs; i++) { + if (!(msg[i].flags & I2C_M_RD)) { + c += msg[i].len; + continue; + } + for (j = 0; j < msg[i].len; j++, c++) { + SwI2cCmd_t *cmd = &res->SwI2cCmds[c]; + + msg[i].buf[j] = cmd->ReadWriteData; + } + } + r = num_msgs; +fail: + kfree(req); + return r; +} + +static u32 smu_v14_0_2_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm smu_v14_0_2_i2c_algo = { + .master_xfer = smu_v14_0_2_i2c_xfer, + .functionality = smu_v14_0_2_i2c_func, +}; + +static const struct i2c_adapter_quirks smu_v14_0_2_i2c_control_quirks = { + .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN, + .max_read_len = MAX_SW_I2C_COMMANDS, + .max_write_len = MAX_SW_I2C_COMMANDS, + .max_comb_1st_msg_len = 2, + .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, +}; + +static int smu_v14_0_2_i2c_control_init(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int res, i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + smu_i2c->adev = adev; + smu_i2c->port = i; + mutex_init(&smu_i2c->mutex); + control->owner = THIS_MODULE; + control->class = I2C_CLASS_SPD; + control->dev.parent = &adev->pdev->dev; + control->algo = &smu_v14_0_2_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i); + control->quirks = &smu_v14_0_2_i2c_control_quirks; + i2c_set_adapdata(control, smu_i2c); + + res = i2c_add_adapter(control); + if (res) { + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + goto Out_err; + } + } + + /* assign the buses used for the FRU EEPROM and RAS EEPROM */ + /* XXX ideally this would be something in a vbios data table */ + adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter; + adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter; + + return 0; +Out_err: + for ( ; i >= 0; i--) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + return res; +} + +static void smu_v14_0_2_i2c_control_fini(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int i; + + for (i = 0; i < MAX_SMU_I2C_BUSES; i++) { + struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i]; + struct i2c_adapter *control = &smu_i2c->adapter; + + i2c_del_adapter(control); + } + adev->pm.ras_eeprom_i2c_bus = NULL; + adev->pm.fru_eeprom_i2c_bus = NULL; +} + +static int smu_v14_0_2_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + int ret; + + switch (mp1_state) { + case PP_MP1_STATE_UNLOAD: + ret = smu_cmn_set_mp1_state(smu, mp1_state); + break; + default: + /* Ignore others */ + ret = 0; + } + + return ret; +} + +static int smu_v14_0_2_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_DFCstateControl, + state, + NULL); +} + +static int smu_v14_0_2_mode1_reset(struct smu_context *smu) +{ + int ret = 0; + + // TODO + + return ret; +} + +static int smu_v14_0_2_mode2_reset(struct smu_context *smu) +{ + int ret = 0; + + // TODO + + return ret; +} + +static int smu_v14_0_2_enable_gfx_features(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(14, 0, 2)) + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableAllSmuFeatures, + FEATURE_PWR_GFX, NULL); + else + return -EOPNOTSUPP; +} + +static void smu_v14_0_2_set_smu_mailbox_registers(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + smu->param_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_82); + smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_66); + smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, regMP1_SMN_C2PMSG_90); +} + +static int smu_v14_0_2_smu_send_bad_mem_page_num(struct smu_context *smu, + uint32_t size) +{ + int ret = 0; + + /* message SMU to update the bad page number on SMUBUS */ + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetNumBadMemoryPagesRetired, + size, NULL); + if (ret) + dev_err(smu->adev->dev, + "[%s] failed to message SMU to update bad memory pages number\n", + __func__); + + return ret; +} + +static int smu_v14_0_2_send_bad_mem_channel_flag(struct smu_context *smu, + uint32_t size) +{ + int ret = 0; + + /* message SMU to update the bad channel info on SMUBUS */ + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, + size, NULL); + if (ret) + dev_err(smu->adev->dev, + "[%s] failed to message SMU to update bad memory pages channel info\n", + __func__); + + return ret; +} + +static ssize_t smu_v14_0_2_get_ecc_info(struct smu_context *smu, + void *table) +{ + int ret = 0; + + // TODO + + return ret; +} + +static const struct pptable_funcs smu_v14_0_2_ppt_funcs = { + .get_allowed_feature_mask = smu_v14_0_2_get_allowed_feature_mask, + .set_default_dpm_table = smu_v14_0_2_set_default_dpm_table, + .i2c_init = smu_v14_0_2_i2c_control_init, + .i2c_fini = smu_v14_0_2_i2c_control_fini, + .is_dpm_running = smu_v14_0_2_is_dpm_running, + .dump_pptable = smu_v14_0_2_dump_pptable, + .init_microcode = smu_v14_0_init_microcode, + .load_microcode = smu_v14_0_load_microcode, + .fini_microcode = smu_v14_0_fini_microcode, + .init_smc_tables = smu_v14_0_2_init_smc_tables, + .fini_smc_tables = smu_v14_0_fini_smc_tables, + .init_power = smu_v14_0_init_power, + .fini_power = smu_v14_0_fini_power, + .check_fw_status = smu_v14_0_check_fw_status, + .setup_pptable = smu_v14_0_2_setup_pptable, + .check_fw_version = smu_v14_0_check_fw_version, + .write_pptable = smu_cmn_write_pptable, + .set_driver_table_location = smu_v14_0_set_driver_table_location, + .system_features_control = smu_v14_0_system_features_control, + .set_allowed_mask = smu_v14_0_set_allowed_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .dpm_set_vcn_enable = smu_v14_0_set_vcn_enable, + .dpm_set_jpeg_enable = smu_v14_0_set_jpeg_enable, + .get_dpm_ultimate_freq = smu_v14_0_2_get_dpm_ultimate_freq, + .get_vbios_bootup_values = smu_v14_0_get_vbios_bootup_values, + .read_sensor = smu_v14_0_2_read_sensor, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .print_clk_levels = smu_v14_0_2_print_clk_levels, + .force_clk_levels = smu_v14_0_2_force_clk_levels, + .update_pcie_parameters = smu_v14_0_2_update_pcie_parameters, + .get_thermal_temperature_range = smu_v14_0_2_get_thermal_temperature_range, + .register_irq_handler = smu_v14_0_register_irq_handler, + .notify_memory_pool_location = smu_v14_0_notify_memory_pool_location, + .set_soft_freq_limited_range = smu_v14_0_set_soft_freq_limited_range, + .init_pptable_microcode = smu_v14_0_init_pptable_microcode, + .populate_umd_state_clk = smu_v14_0_2_populate_umd_state_clk, + .set_performance_level = smu_v14_0_set_performance_level, + .gfx_off_control = smu_v14_0_gfx_off_control, + .get_unique_id = smu_v14_0_2_get_unique_id, + .get_power_limit = smu_v14_0_2_get_power_limit, + .set_power_limit = smu_v14_0_set_power_limit, + .set_power_source = smu_v14_0_set_power_source, + .get_power_profile_mode = smu_v14_0_2_get_power_profile_mode, + .set_power_profile_mode = smu_v14_0_2_set_power_profile_mode, + .run_btc = smu_v14_0_run_btc, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .set_tool_table_location = smu_v14_0_set_tool_table_location, + .deep_sleep_control = smu_v14_0_deep_sleep_control, + .gfx_ulv_control = smu_v14_0_gfx_ulv_control, + .get_bamaco_support = smu_v14_0_get_bamaco_support, + .baco_get_state = smu_v14_0_baco_get_state, + .baco_set_state = smu_v14_0_baco_set_state, + .baco_enter = smu_v14_0_2_baco_enter, + .baco_exit = smu_v14_0_2_baco_exit, + .mode1_reset_is_support = smu_v14_0_2_is_mode1_reset_supported, + .mode1_reset = smu_v14_0_2_mode1_reset, + .mode2_reset = smu_v14_0_2_mode2_reset, + .enable_gfx_features = smu_v14_0_2_enable_gfx_features, + .set_mp1_state = smu_v14_0_2_set_mp1_state, + .set_df_cstate = smu_v14_0_2_set_df_cstate, + .send_hbm_bad_pages_num = smu_v14_0_2_smu_send_bad_mem_page_num, + .send_hbm_bad_channel_flag = smu_v14_0_2_send_bad_mem_channel_flag, + .gpo_control = smu_v14_0_gpo_control, + .get_ecc_info = smu_v14_0_2_get_ecc_info, +}; + +void smu_v14_0_2_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &smu_v14_0_2_ppt_funcs; + smu->message_map = smu_v14_0_2_message_map; + smu->clock_map = smu_v14_0_2_clk_map; + smu->feature_map = smu_v14_0_2_feature_mask_map; + smu->table_map = smu_v14_0_2_table_map; + smu->pwr_src_map = smu_v14_0_2_pwr_src_map; + smu->workload_map = smu_v14_0_2_workload_map; + smu_v14_0_2_set_smu_mailbox_registers(smu); +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.h new file mode 100644 index 000000000000..b83729e5d6f9 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.h @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SMU_V14_0_2_PPT_H__ +#define __SMU_V14_0_2_PPT_H__ + +extern void smu_v14_0_2_set_ppt_funcs(struct smu_context *smu); + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c index b8dbd4e25348..6d1c3af927ca 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -235,6 +235,50 @@ static void __smu_cmn_send_msg(struct smu_context *smu, WREG32(smu->msg_reg, msg); } +static inline uint32_t __smu_cmn_get_msg_flags(struct smu_context *smu, + enum smu_message_type msg) +{ + return smu->message_map[msg].flags; +} + +static int __smu_cmn_ras_filter_msg(struct smu_context *smu, + enum smu_message_type msg, bool *poll) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t flags, resp; + bool fed_status; + + flags = __smu_cmn_get_msg_flags(smu, msg); + *poll = true; + + /* When there is RAS fatal error, FW won't process non-RAS priority + * messages. Don't allow any messages other than RAS priority messages. + */ + fed_status = amdgpu_ras_get_fed_status(adev); + if (fed_status) { + if (!(flags & SMU_MSG_RAS_PRI)) { + dev_dbg(adev->dev, + "RAS error detected, skip sending %s", + smu_get_message_name(smu, msg)); + return -EACCES; + } + + /* FW will ignore non-priority messages when a RAS fatal error + * is detected. Hence it is possible that a previous message + * wouldn't have got response. Allow to continue without polling + * for response status for priority messages. + */ + resp = RREG32(smu->resp_reg); + dev_dbg(adev->dev, + "Sending RAS priority message %s response status: %x", + smu_get_message_name(smu, msg), resp); + if (resp == 0) + *poll = false; + } + + return 0; +} + static int __smu_cmn_send_debug_msg(struct smu_context *smu, u32 msg, u32 param) @@ -354,6 +398,7 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, { struct amdgpu_device *adev = smu->adev; int res, index; + bool poll = true; u32 reg; if (adev->no_hw_access) @@ -366,12 +411,20 @@ int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, return index == -EACCES ? 0 : index; mutex_lock(&smu->message_lock); - reg = __smu_cmn_poll_stat(smu); - res = __smu_cmn_reg2errno(smu, reg); - if (reg == SMU_RESP_NONE || - res == -EREMOTEIO) { - __smu_cmn_reg_print_error(smu, reg, index, param, msg); - goto Out; + + if (smu->smc_fw_caps & SMU_FW_CAP_RAS_PRI) { + res = __smu_cmn_ras_filter_msg(smu, msg, &poll); + if (res) + goto Out; + } + + if (poll) { + reg = __smu_cmn_poll_stat(smu); + res = __smu_cmn_reg2errno(smu, reg); + if (reg == SMU_RESP_NONE || res == -EREMOTEIO) { + __smu_cmn_reg_print_error(smu, reg, index, param, msg); + goto Out; + } } __smu_cmn_send_msg(smu, (uint16_t) index, param); reg = __smu_cmn_poll_stat(smu); @@ -437,7 +490,7 @@ int smu_cmn_to_asic_specific_index(struct smu_context *smu, return -EINVAL; if (amdgpu_sriov_vf(smu->adev) && - !msg_mapping.valid_in_vf) + !(msg_mapping.flags & SMU_MSG_VF_FLAG)) return -EACCES; return msg_mapping.map_to; diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c index 42510fdea27e..67e5d3b4190f 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c @@ -4,6 +4,8 @@ * Author: James.Qian.Wang * */ + +#include #include "d71_dev.h" #include "komeda_kms.h" #include "malidp_io.h" diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c index 4b7d94961527..00f5864a0495 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c @@ -5,6 +5,7 @@ * */ #include +#include #include diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index 626709bec6f5..2577f0cef8fc 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -72,7 +72,10 @@ static void malidp_mw_connector_reset(struct drm_connector *connector) __drm_atomic_helper_connector_destroy_state(connector->state); kfree(connector->state); - __drm_atomic_helper_connector_reset(connector, &mw_state->base); + connector->state = NULL; + + if (mw_state) + __drm_atomic_helper_connector_reset(connector, &mw_state->base); } static enum drm_connector_status diff --git a/drivers/gpu/drm/armada/armada_debugfs.c b/drivers/gpu/drm/armada/armada_debugfs.c index 29f4b52e3c8d..a763349dd89f 100644 --- a/drivers/gpu/drm/armada/armada_debugfs.c +++ b/drivers/gpu/drm/armada/armada_debugfs.c @@ -5,6 +5,7 @@ */ #include +#include #include #include #include diff --git a/drivers/gpu/drm/ast/ast_ddc.c b/drivers/gpu/drm/ast/ast_ddc.c index b7718084422f..29cf5d157f34 100644 --- a/drivers/gpu/drm/ast/ast_ddc.c +++ b/drivers/gpu/drm/ast/ast_ddc.c @@ -21,12 +21,22 @@ * of the Software. */ +#include +#include + #include #include #include "ast_ddc.h" #include "ast_drv.h" +struct ast_ddc { + struct ast_device *ast; + + struct i2c_algo_bit_data bit; + struct i2c_adapter adapter; +}; + static void ast_ddc_algo_bit_data_setsda(void *data, int state) { struct ast_ddc *ddc = data; @@ -132,7 +142,7 @@ static void ast_ddc_release(struct drm_device *dev, void *res) i2c_del_adapter(&ddc->adapter); } -struct ast_ddc *ast_ddc_create(struct ast_device *ast) +struct i2c_adapter *ast_ddc_create(struct ast_device *ast) { struct drm_device *dev = &ast->base; struct ast_ddc *ddc; @@ -145,15 +155,7 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) return ERR_PTR(-ENOMEM); ddc->ast = ast; - adapter = &ddc->adapter; - adapter->owner = THIS_MODULE; - adapter->dev.parent = dev->dev; - i2c_set_adapdata(adapter, ddc); - snprintf(adapter->name, sizeof(adapter->name), "AST DDC bus"); - bit = &ddc->bit; - bit->udelay = 20; - bit->timeout = 2; bit->data = ddc; bit->setsda = ast_ddc_algo_bit_data_setsda; bit->setscl = ast_ddc_algo_bit_data_setscl; @@ -161,8 +163,16 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) bit->getscl = ast_ddc_algo_bit_data_getscl; bit->pre_xfer = ast_ddc_algo_bit_data_pre_xfer; bit->post_xfer = ast_ddc_algo_bit_data_post_xfer; + bit->udelay = 20; + bit->timeout = usecs_to_jiffies(2200); + adapter = &ddc->adapter; + adapter->owner = THIS_MODULE; adapter->algo_data = bit; + adapter->dev.parent = dev->dev; + snprintf(adapter->name, sizeof(adapter->name), "AST DDC bus"); + i2c_set_adapdata(adapter, ddc); + ret = i2c_bit_add_bus(adapter); if (ret) { drm_err(dev, "Failed to register bit i2c\n"); @@ -173,5 +183,5 @@ struct ast_ddc *ast_ddc_create(struct ast_device *ast) if (ret) return ERR_PTR(ret); - return ddc; + return &ddc->adapter; } diff --git a/drivers/gpu/drm/ast/ast_ddc.h b/drivers/gpu/drm/ast/ast_ddc.h index 08f3994e09cc..85c93edc9ae1 100644 --- a/drivers/gpu/drm/ast/ast_ddc.h +++ b/drivers/gpu/drm/ast/ast_ddc.h @@ -3,18 +3,9 @@ #ifndef __AST_DDC_H__ #define __AST_DDC_H__ -#include -#include - struct ast_device; +struct i2c_adapter; -struct ast_ddc { - struct ast_device *ast; - - struct i2c_adapter adapter; - struct i2c_algo_bit_data bit; -}; - -struct ast_ddc *ast_ddc_create(struct ast_device *ast); +struct i2c_adapter *ast_ddc_create(struct ast_device *ast); #endif diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index ebb6d8ebd44e..1e9259416980 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -180,6 +180,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) { struct ast_device *ast = to_ast_device(dev); u8 video_on_off = on; + u32 i = 0; // Video On/Off ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on); @@ -192,6 +193,8 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) { // wait 1 ms mdelay(1); + if (++i > 200) + break; } } } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index bb9b66aba9ee..6695af70768f 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -701,12 +702,29 @@ static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane, ast_set_index_reg_mask(ast, AST_IO_VGASRI, 0x1, 0xdf, 0x20); } +static int ast_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb) +{ + struct ast_plane *ast_plane = to_ast_plane(plane); + + if (plane->state && plane->state->fb && ast_plane->vaddr) { + sb->format = plane->state->fb->format; + sb->width = plane->state->fb->width; + sb->height = plane->state->fb->height; + sb->pitch[0] = plane->state->fb->pitches[0]; + iosys_map_set_vaddr_iomem(&sb->map[0], ast_plane->vaddr); + return 0; + } + return -ENODEV; +} + static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = { DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, .atomic_check = ast_primary_plane_helper_atomic_check, .atomic_update = ast_primary_plane_helper_atomic_update, .atomic_enable = ast_primary_plane_helper_atomic_enable, .atomic_disable = ast_primary_plane_helper_atomic_disable, + .get_scanout_buffer = ast_primary_plane_helper_get_scanout_buffer, }; static const struct drm_plane_funcs ast_primary_plane_funcs = { @@ -1360,7 +1378,7 @@ static const struct drm_connector_funcs ast_vga_connector_funcs = { static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector) { struct ast_device *ast = to_ast_device(dev); - struct ast_ddc *ddc; + struct i2c_adapter *ddc; int ret; ddc = ast_ddc_create(ast); @@ -1371,7 +1389,7 @@ static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector * } ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs, - DRM_MODE_CONNECTOR_VGA, &ddc->adapter); + DRM_MODE_CONNECTOR_VGA, ddc); if (ret) return ret; @@ -1429,7 +1447,7 @@ static const struct drm_connector_funcs ast_sil164_connector_funcs = { static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connector *connector) { struct ast_device *ast = to_ast_device(dev); - struct ast_ddc *ddc; + struct i2c_adapter *ddc; int ret; ddc = ast_ddc_create(ast); @@ -1440,7 +1458,7 @@ static int ast_sil164_connector_init(struct drm_device *dev, struct drm_connecto } ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, - DRM_MODE_CONNECTOR_DVII, &ddc->adapter); + DRM_MODE_CONNECTOR_DVII, ddc); if (ret) return ret; diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index d1fbf8796fea..30a17876ff50 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -189,6 +189,13 @@ config DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW to DP++. This is used with the i.MX6 imx-ldb driver. You are likely to say N here. +config DRM_MICROCHIP_LVDS_SERIALIZER + tristate "Microchip LVDS serializer support" + depends on OF + depends on DRM_ATMEL_HLCDC + help + Support for Microchip's LVDS serializer. + config DRM_NWL_MIPI_DSI tristate "Northwest Logic MIPI DSI Host controller" depends on DRM diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 017b5832733b..7df87b582dca 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_DRM_LONTIUM_LT9611) += lontium-lt9611.o obj-$(CONFIG_DRM_LONTIUM_LT9611UXC) += lontium-lt9611uxc.o obj-$(CONFIG_DRM_LVDS_CODEC) += lvds-codec.o obj-$(CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW) += megachips-stdpxxxx-ge-b850v3-fw.o +obj-$(CONFIG_DRM_MICROCHIP_LVDS_SERIALIZER) += microchip-lvds.o obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o obj-$(CONFIG_DRM_PARADE_PS8640) += parade-ps8640.o diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h index 39c9ece373b0..ea271f62b214 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h @@ -356,6 +356,7 @@ struct adv7511 { enum drm_connector_status status; bool powered; + struct drm_bridge *next_bridge; struct drm_display_mode curr_mode; unsigned int f_tmds; diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index f3b4616a8fb6..dd21b81bd28f 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -951,6 +952,12 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge, struct adv7511 *adv = bridge_to_adv7511(bridge); int ret = 0; + if (adv->next_bridge) { + ret = drm_bridge_attach(bridge->encoder, adv->next_bridge, bridge, flags); + if (ret) + return ret; + } + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) { ret = adv7511_connector_init(adv); if (ret < 0) @@ -1221,6 +1228,11 @@ static int adv7511_probe(struct i2c_client *i2c) memset(&link_config, 0, sizeof(link_config)); + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL, + &adv7511->next_bridge); + if (ret && ret != -ENODEV) + return ret; + if (adv7511->info->link_config) ret = adv7511_parse_dt(dev->of_node, &link_config); else diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index 12bfea53bf24..5b564fded6d6 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -28,7 +28,7 @@ config DRM_ANALOGIX_ANX78XX config DRM_ANALOGIX_DP tristate - depends on DRM + depends on DRM_DISPLAY_HELPER config DRM_ANALOGIX_ANX7625 tristate "Analogix Anx7625 MIPI to DP interface support" diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 9d96d28d6fe8..59e9ad349969 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2066,10 +2066,8 @@ static int anx7625_setup_dsi_device(struct anx7625_data *ctx) }; host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node); - if (!host) { - DRM_DEV_ERROR(dev, "fail to find dsi host.\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "fail to find dsi host.\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { @@ -2471,15 +2469,22 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, mutex_unlock(&ctx->aux_lock); } +static void +anx7625_audio_update_connector_status(struct anx7625_data *ctx, + enum drm_connector_status status); + static enum drm_connector_status anx7625_bridge_detect(struct drm_bridge *bridge) { struct anx7625_data *ctx = bridge_to_anx7625(bridge); struct device *dev = ctx->dev; + enum drm_connector_status status; DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n"); - return anx7625_sink_detect(ctx); + status = anx7625_sink_detect(ctx); + anx7625_audio_update_connector_status(ctx, status); + return status; } static const struct drm_edid *anx7625_bridge_edid_read(struct drm_bridge *bridge, diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c index 82d23e4df09e..9eecac457dcf 100644 --- a/drivers/gpu/drm/bridge/chipone-icn6211.c +++ b/drivers/gpu/drm/bridge/chipone-icn6211.c @@ -563,10 +563,8 @@ static int chipone_dsi_host_attach(struct chipone *icn) host = of_find_mipi_dsi_host_by_node(host_node); of_node_put(host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = mipi_dsi_device_register_full(host, &info); if (IS_ERR(dsi)) { @@ -783,7 +781,6 @@ static struct mipi_dsi_driver chipone_dsi_driver = { .remove = chipone_dsi_remove, .driver = { .name = "chipone-icn6211", - .owner = THIS_MODULE, .of_match_table = chipone_of_match, }, }; diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig index 7687ed652df5..13142a6b8590 100644 --- a/drivers/gpu/drm/bridge/imx/Kconfig +++ b/drivers/gpu/drm/bridge/imx/Kconfig @@ -8,8 +8,8 @@ config DRM_IMX8MP_DW_HDMI_BRIDGE depends on COMMON_CLK depends on DRM_DW_HDMI depends on OF - select DRM_IMX8MP_HDMI_PVI - select PHY_FSL_SAMSUNG_HDMI_PHY + imply DRM_IMX8MP_HDMI_PVI + imply PHY_FSL_SAMSUNG_HDMI_PHY help Choose this to enable support for the internal HDMI encoder found on the i.MX8MP SoC. diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c index 89fc432ac611..13bc570c5473 100644 --- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c +++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c @@ -104,13 +104,11 @@ static int imx8mp_dw_hdmi_probe(struct platform_device *pdev) return 0; } -static int imx8mp_dw_hdmi_remove(struct platform_device *pdev) +static void imx8mp_dw_hdmi_remove(struct platform_device *pdev) { struct imx8mp_hdmi *hdmi = platform_get_drvdata(pdev); dw_hdmi_remove(hdmi->dw_hdmi); - - return 0; } static int __maybe_unused imx8mp_dw_hdmi_pm_suspend(struct device *dev) @@ -140,7 +138,7 @@ MODULE_DEVICE_TABLE(of, imx8mp_dw_hdmi_of_table); static struct platform_driver imx8mp_dw_hdmi_platform_driver = { .probe = imx8mp_dw_hdmi_probe, - .remove = imx8mp_dw_hdmi_remove, + .remove_new = imx8mp_dw_hdmi_remove, .driver = { .name = "imx8mp-dw-hdmi-tx", .of_match_table = imx8mp_dw_hdmi_of_table, diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c index 27334173e911..3f68c82888c2 100644 --- a/drivers/gpu/drm/bridge/ite-it6505.c +++ b/drivers/gpu/drm/bridge/ite-it6505.c @@ -3,6 +3,7 @@ * Copyright (c) 2020, The Linux Foundation. All rights reserved. */ #include +#include #include #include #include diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c index 4b2ae27f0a57..1a9defa15663 100644 --- a/drivers/gpu/drm/bridge/lontium-lt8912b.c +++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c @@ -494,10 +494,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt) }; host = of_find_mipi_dsi_host_by_node(lt->host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index a9c7e2b07ea1..b99fe87ec738 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -761,10 +761,8 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611, int ret; host = of_find_mipi_dsi_host_by_node(dsi_node); - if (!host) { - dev_err(lt9611->dev, "failed to find dsi host\n"); - return ERR_PTR(-EPROBE_DEFER); - } + if (!host) + return ERR_PTR(dev_err_probe(lt9611->dev, -EPROBE_DEFER, "failed to find dsi host\n")); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c index f4f593ad8f79..ab702471f3ab 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c @@ -266,10 +266,8 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc, int ret; host = of_find_mipi_dsi_host_by_node(dsi_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return ERR_PTR(-EPROBE_DEFER); - } + if (!host) + return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n")); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { diff --git a/drivers/gpu/drm/bridge/microchip-lvds.c b/drivers/gpu/drm/bridge/microchip-lvds.c new file mode 100644 index 000000000000..b8313dad6072 --- /dev/null +++ b/drivers/gpu/drm/bridge/microchip-lvds.c @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 Microchip Technology Inc. and its subsidiaries + * + * Author: Manikandan Muralidharan + * Author: Dharma Balasubiramani + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define LVDS_POLL_TIMEOUT_MS 1000 + +/* LVDSC register offsets */ +#define LVDSC_CR 0x00 +#define LVDSC_CFGR 0x04 +#define LVDSC_SR 0x0C +#define LVDSC_WPMR 0xE4 + +/* Bitfields in LVDSC_CR (Control Register) */ +#define LVDSC_CR_SER_EN BIT(0) + +/* Bitfields in LVDSC_CFGR (Configuration Register) */ +#define LVDSC_CFGR_PIXSIZE_24BITS 0 +#define LVDSC_CFGR_DEN_POL_HIGH 0 +#define LVDSC_CFGR_DC_UNBALANCED 0 +#define LVDSC_CFGR_MAPPING_JEIDA BIT(6) + +/*Bitfields in LVDSC_SR */ +#define LVDSC_SR_CS BIT(0) + +/* Bitfields in LVDSC_WPMR (Write Protection Mode Register) */ +#define LVDSC_WPMR_WPKEY_MASK GENMASK(31, 8) +#define LVDSC_WPMR_WPKEY_PSSWD 0x4C5644 + +struct mchp_lvds { + struct device *dev; + void __iomem *regs; + struct clk *pclk; + struct drm_panel *panel; + struct drm_bridge bridge; + struct drm_bridge *panel_bridge; +}; + +static inline struct mchp_lvds *bridge_to_lvds(struct drm_bridge *bridge) +{ + return container_of(bridge, struct mchp_lvds, bridge); +} + +static inline u32 lvds_readl(struct mchp_lvds *lvds, u32 offset) +{ + return readl_relaxed(lvds->regs + offset); +} + +static inline void lvds_writel(struct mchp_lvds *lvds, u32 offset, u32 val) +{ + writel_relaxed(val, lvds->regs + offset); +} + +static void lvds_serialiser_on(struct mchp_lvds *lvds) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(LVDS_POLL_TIMEOUT_MS); + + /* The LVDSC registers can only be written if WPEN is cleared */ + lvds_writel(lvds, LVDSC_WPMR, (LVDSC_WPMR_WPKEY_PSSWD & + LVDSC_WPMR_WPKEY_MASK)); + + /* Wait for the status of configuration registers to be changed */ + while (lvds_readl(lvds, LVDSC_SR) & LVDSC_SR_CS) { + if (time_after(jiffies, timeout)) { + dev_err(lvds->dev, "%s: timeout error\n", __func__); + return; + } + usleep_range(1000, 2000); + } + + /* Configure the LVDSC */ + lvds_writel(lvds, LVDSC_CFGR, (LVDSC_CFGR_MAPPING_JEIDA | + LVDSC_CFGR_DC_UNBALANCED | + LVDSC_CFGR_DEN_POL_HIGH | + LVDSC_CFGR_PIXSIZE_24BITS)); + + /* Enable the LVDS serializer */ + lvds_writel(lvds, LVDSC_CR, LVDSC_CR_SER_EN); +} + +static int mchp_lvds_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct mchp_lvds *lvds = bridge_to_lvds(bridge); + + return drm_bridge_attach(bridge->encoder, lvds->panel_bridge, + bridge, flags); +} + +static void mchp_lvds_enable(struct drm_bridge *bridge) +{ + struct mchp_lvds *lvds = bridge_to_lvds(bridge); + int ret; + + ret = clk_prepare_enable(lvds->pclk); + if (ret < 0) { + dev_err(lvds->dev, "failed to enable lvds pclk %d\n", ret); + return; + } + + ret = pm_runtime_get_sync(lvds->dev); + if (ret < 0) { + dev_err(lvds->dev, "failed to get pm runtime: %d\n", ret); + return; + } + + lvds_serialiser_on(lvds); +} + +static void mchp_lvds_disable(struct drm_bridge *bridge) +{ + struct mchp_lvds *lvds = bridge_to_lvds(bridge); + + pm_runtime_put(lvds->dev); + clk_disable_unprepare(lvds->pclk); +} + +static const struct drm_bridge_funcs mchp_lvds_bridge_funcs = { + .attach = mchp_lvds_attach, + .enable = mchp_lvds_enable, + .disable = mchp_lvds_disable, +}; + +static int mchp_lvds_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mchp_lvds *lvds; + struct device_node *port; + int ret; + + if (!dev->of_node) + return -ENODEV; + + lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); + if (!lvds) + return -ENOMEM; + + lvds->dev = dev; + + lvds->regs = devm_ioremap_resource(lvds->dev, + platform_get_resource(pdev, IORESOURCE_MEM, 0)); + if (IS_ERR(lvds->regs)) + return PTR_ERR(lvds->regs); + + lvds->pclk = devm_clk_get(lvds->dev, "pclk"); + if (IS_ERR(lvds->pclk)) + return dev_err_probe(lvds->dev, PTR_ERR(lvds->pclk), + "could not get pclk_lvds\n"); + + port = of_graph_get_remote_node(dev->of_node, 1, 0); + if (!port) { + dev_err(dev, + "can't find port point, please init lvds panel port!\n"); + return -ENODEV; + } + + lvds->panel = of_drm_find_panel(port); + of_node_put(port); + + if (IS_ERR(lvds->panel)) + return -EPROBE_DEFER; + + lvds->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); + + if (IS_ERR(lvds->panel_bridge)) + return PTR_ERR(lvds->panel_bridge); + + lvds->bridge.of_node = dev->of_node; + lvds->bridge.type = DRM_MODE_CONNECTOR_LVDS; + lvds->bridge.funcs = &mchp_lvds_bridge_funcs; + + dev_set_drvdata(dev, lvds); + ret = devm_pm_runtime_enable(dev); + if (ret < 0) { + dev_err(lvds->dev, "failed to enable pm runtime: %d\n", ret); + return ret; + } + + drm_bridge_add(&lvds->bridge); + + return 0; +} + +static const struct of_device_id mchp_lvds_dt_ids[] = { + { + .compatible = "microchip,sam9x75-lvds", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, mchp_lvds_dt_ids); + +static struct platform_driver mchp_lvds_driver = { + .probe = mchp_lvds_probe, + .driver = { + .name = "microchip-lvds", + .of_match_table = mchp_lvds_dt_ids, + }, +}; +module_platform_driver(mchp_lvds_driver); + +MODULE_AUTHOR("Manikandan Muralidharan "); +MODULE_AUTHOR("Dharma Balasubiramani "); +MODULE_DESCRIPTION("Low Voltage Differential Signaling Controller Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 7f41525f7a6e..32506524d9a2 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -4,6 +4,8 @@ * Copyright (C) 2017 Broadcom */ +#include + #include #include #include diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index deccb3995022..3d3d135b4348 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -401,7 +401,6 @@ static struct mipi_dsi_driver tc358764_driver = { .remove = tc358764_remove, .driver = { .name = "tc358764", - .owner = THIS_MODULE, .of_match_table = tc358764_of_match, }, }; diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 90a89d70d832..3b7cc3be2ccd 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,7 @@ #define RDPKTLN 0x0404 /* Command Read Packet Length */ #define VPCTRL 0x0450 /* Video Path Control */ +#define EVTMODE BIT(5) /* Video event mode enable, tc35876x only */ #define HTIM1 0x0454 /* Horizontal Timing Control 1 */ #define HTIM2 0x0458 /* Horizontal Timing Control 2 */ #define VTIM1 0x045C /* Vertical Timing Control 1 */ @@ -254,6 +256,11 @@ enum tc358775_ports { TC358775_LVDS_OUT1, }; +enum tc3587x5_type { + TC358765 = 0x65, + TC358775 = 0x75, +}; + struct tc_data { struct i2c_client *i2c; struct device *dev; @@ -271,6 +278,8 @@ struct tc_data { struct gpio_desc *stby_gpio; u8 lvds_link; /* single-link or dual-link */ u8 bpc; + + enum tc3587x5_type type; }; static inline struct tc_data *bridge_to_tc(struct drm_bridge *b) @@ -424,10 +433,16 @@ static void tc_bridge_enable(struct drm_bridge *bridge) d2l_write(tc->i2c, PPI_STARTPPI, PPI_START_FUNCTION); d2l_write(tc->i2c, DSI_STARTDSI, DSI_RX_START); + /* Video event mode vs pulse mode bit, does not exist for tc358775 */ + if (tc->type == TC358765) + val = EVTMODE; + else + val = 0; + if (tc->bpc == 8) - val = TC358775_VPCTRL_OPXLFMT(1); + val |= TC358775_VPCTRL_OPXLFMT(1); else /* bpc = 6; */ - val = TC358775_VPCTRL_MSF(1); + val |= TC358775_VPCTRL_MSF(1); dsiclk = mode->crtc_clock * 3 * tc->bpc / tc->num_dsi_lanes / 1000; clkdiv = dsiclk / (tc->lvds_link == DUAL_LINK ? DIVIDE_BY_6 : DIVIDE_BY_3); @@ -454,10 +469,6 @@ static void tc_bridge_enable(struct drm_bridge *bridge) dev_dbg(tc->dev, "bus_formats %04x bpc %d\n", connector->display_info.bus_formats[0], tc->bpc); - /* - * Default hardware register settings of tc358775 configured - * with MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA jeida-24 format - */ if (connector->display_info.bus_formats[0] == MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) { /* VESA-24 */ @@ -468,14 +479,15 @@ static void tc_bridge_enable(struct drm_bridge *bridge) d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2)); d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6)); - } else { /* MEDIA_BUS_FMT_RGB666_1X7X3_SPWG - JEIDA-18 */ - d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3)); - d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_L0, LVI_R5, LVI_G0)); - d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_L0, LVI_L0)); - d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0)); - d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_L0, LVI_L0, LVI_B1, LVI_B2)); - d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0)); - d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_L0)); + } else { + /* JEIDA-18 and JEIDA-24 */ + d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5)); + d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2)); + d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1)); + d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2)); + d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4)); + d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0)); + d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0)); } d2l_write(tc->i2c, VFUEN, VFUEN_EN); @@ -528,27 +540,24 @@ tc_mode_valid(struct drm_bridge *bridge, static int tc358775_parse_dt(struct device_node *np, struct tc_data *tc) { struct device_node *endpoint; - struct device_node *parent; struct device_node *remote; int dsi_lanes = -1; - /* - * To get the data-lanes of dsi, we need to access the dsi0_out of port1 - * of dsi0 endpoint from bridge port0 of d2l_in - */ endpoint = of_graph_get_endpoint_by_regs(tc->dev->of_node, TC358775_DSI_IN, -1); - if (endpoint) { - /* dsi0_out node */ - parent = of_graph_get_remote_port_parent(endpoint); - of_node_put(endpoint); - if (parent) { - /* dsi0 port 1 */ - dsi_lanes = drm_of_get_data_lanes_count_ep(parent, 1, -1, 1, 4); - of_node_put(parent); - } + dsi_lanes = drm_of_get_data_lanes_count(endpoint, 1, 4); + + /* Quirk old dtb: Use data lanes from the DSI host side instead of bridge */ + if (dsi_lanes == -EINVAL || dsi_lanes == -ENODEV) { + remote = of_graph_get_remote_endpoint(endpoint); + dsi_lanes = drm_of_get_data_lanes_count(remote, 1, 4); + of_node_put(remote); + if (dsi_lanes >= 1) + dev_warn(tc->dev, "no dsi-lanes for the bridge, using host lanes\n"); } + of_node_put(endpoint); + if (dsi_lanes < 0) return dsi_lanes; @@ -610,10 +619,8 @@ static int tc_attach_host(struct tc_data *tc) }; host = of_find_mipi_dsi_host_by_node(tc->host_node); - if (!host) { - dev_err(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dsi = devm_mipi_dsi_device_register_full(dev, host, &info); if (IS_ERR(dsi)) { @@ -625,7 +632,21 @@ static int tc_attach_host(struct tc_data *tc) dsi->lanes = tc->num_dsi_lanes; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_LPM; + + /* + * The hs_rate and lp_rate are data rate values. The HS mode is + * differential, while the LP mode is single ended. As the HS mode + * uses DDR, the DSI clock frequency is half the hs_rate. The 10 Mbs + * data rate for LP mode is not specified in the bridge data sheet, + * but seems to be part of the MIPI DSI spec. + */ + if (tc->type == TC358765) + dsi->hs_rate = 800000000; + else + dsi->hs_rate = 1000000000; + dsi->lp_rate = 10000000; ret = devm_mipi_dsi_attach(dev, dsi); if (ret < 0) { @@ -648,6 +669,7 @@ static int tc_probe(struct i2c_client *client) tc->dev = dev; tc->i2c = client; + tc->type = (enum tc3587x5_type)(unsigned long)of_device_get_match_data(dev); tc->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, TC358775_LVDS_OUT0, 0); @@ -672,12 +694,9 @@ static int tc_probe(struct i2c_client *client) return ret; } - tc->stby_gpio = devm_gpiod_get(dev, "stby", GPIOD_OUT_HIGH); - if (IS_ERR(tc->stby_gpio)) { - ret = PTR_ERR(tc->stby_gpio); - dev_err(dev, "cannot get stby-gpio %d\n", ret); - return ret; - } + tc->stby_gpio = devm_gpiod_get_optional(dev, "stby", GPIOD_OUT_HIGH); + if (IS_ERR(tc->stby_gpio)) + return PTR_ERR(tc->stby_gpio); tc->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(tc->reset_gpio)) { @@ -688,6 +707,7 @@ static int tc_probe(struct i2c_client *client) tc->bridge.funcs = &tc_bridge_funcs; tc->bridge.of_node = dev->of_node; + tc->bridge.pre_enable_prev_first = true; drm_bridge_add(&tc->bridge); i2c_set_clientdata(client, tc); @@ -711,13 +731,15 @@ static void tc_remove(struct i2c_client *client) } static const struct i2c_device_id tc358775_i2c_ids[] = { - { "tc358775", 0 }, + { "tc358765", TC358765, }, + { "tc358775", TC358775, }, { } }; MODULE_DEVICE_TABLE(i2c, tc358775_i2c_ids); static const struct of_device_id tc358775_of_ids[] = { - { .compatible = "toshiba,tc358775", }, + { .compatible = "toshiba,tc358765", .data = (void *)TC358765, }, + { .compatible = "toshiba,tc358775", .data = (void *)TC358775, }, { } }; MODULE_DEVICE_TABLE(of, tc358775_of_ids); diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c index ca3348109bcd..6b559e071301 100644 --- a/drivers/gpu/drm/bridge/ti-dlpc3433.c +++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c @@ -319,12 +319,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) .channel = 0, .node = NULL, }; + int ret; host = of_find_mipi_dsi_host_by_node(dlpc->host_node); - if (!host) { - DRM_DEV_ERROR(dev, "failed to find dsi host\n"); - return -EPROBE_DEFER; - } + if (!host) + return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"); dlpc->dsi = mipi_dsi_device_register_full(host, &info); if (IS_ERR(dlpc->dsi)) { @@ -336,7 +335,11 @@ static int dlpc_host_attach(struct dlpc *dlpc) dlpc->dsi->format = MIPI_DSI_FMT_RGB565; dlpc->dsi->lanes = dlpc->dsi_lanes; - return devm_mipi_dsi_attach(dev, dlpc->dsi); + ret = devm_mipi_dsi_attach(dev, dlpc->dsi); + if (ret) + DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); + + return ret; } static int dlpc3433_probe(struct i2c_client *client) @@ -367,10 +370,8 @@ static int dlpc3433_probe(struct i2c_client *client) drm_bridge_add(&dlpc->bridge); ret = dlpc_host_attach(dlpc); - if (ret) { - DRM_DEV_ERROR(dev, "failed to attach dsi host\n"); + if (ret) goto err_remove_bridge; - } return 0; diff --git a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c index bd61e20770a5..14a2a8473682 100644 --- a/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/display/drm_dp_dual_mode_helper.c @@ -52,7 +52,7 @@ * @adapter: I2C adapter for the DDC bus * @offset: register offset * @buffer: buffer for return data - * @size: sizo of the buffer + * @size: size of the buffer * * Reads @size bytes from the DP dual mode adaptor registers * starting at @offset. @@ -116,7 +116,7 @@ EXPORT_SYMBOL(drm_dp_dual_mode_read); * @adapter: I2C adapter for the DDC bus * @offset: register offset * @buffer: buffer for write data - * @size: sizo of the buffer + * @size: size of the buffer * * Writes @size bytes to the DP dual mode adaptor registers * starting at @offset. diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index 88dca26189b9..79a615667aab 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -2281,6 +2281,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = { { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) }, /* Synaptics DP1.4 MST hubs require DSC for some modes on which it applies HBLANK expansion. */ { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) }, + /* MediaTek panels (at least in U3224KBA) require DSC for modes with a short HBLANK on UHBR links. */ + { OUI(0x00, 0x0C, 0xE7), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC) }, /* Apple MacBookPro 2017 15 inch eDP Retina panel reports too low DP_MAX_LINK_RATE */ { OUI(0x00, 0x10, 0xfa), DEVICE_ID(101, 68, 21, 101, 98, 97), false, BIT(DP_DPCD_QUIRK_CAN_DO_MAX_LINK_RATE_3_24_GBPS) }, }; @@ -2948,6 +2950,43 @@ void drm_dp_vsc_sdp_log(struct drm_printer *p, const struct drm_dp_vsc_sdp *vsc) } EXPORT_SYMBOL(drm_dp_vsc_sdp_log); +void drm_dp_as_sdp_log(struct drm_printer *p, const struct drm_dp_as_sdp *as_sdp) +{ + drm_printf(p, "DP SDP: AS_SDP, revision %u, length %u\n", + as_sdp->revision, as_sdp->length); + drm_printf(p, " vtotal: %d\n", as_sdp->vtotal); + drm_printf(p, " target_rr: %d\n", as_sdp->target_rr); + drm_printf(p, " duration_incr_ms: %d\n", as_sdp->duration_incr_ms); + drm_printf(p, " duration_decr_ms: %d\n", as_sdp->duration_decr_ms); + drm_printf(p, " operation_mode: %d\n", as_sdp->mode); +} +EXPORT_SYMBOL(drm_dp_as_sdp_log); + +/** + * drm_dp_as_sdp_supported() - check if adaptive sync sdp is supported + * @aux: DisplayPort AUX channel + * @dpcd: DisplayPort configuration data + * + * Returns true if adaptive sync sdp is supported, else returns false + */ +bool drm_dp_as_sdp_supported(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 rx_feature; + + if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_13) + return false; + + if (drm_dp_dpcd_readb(aux, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, + &rx_feature) != 1) { + drm_dbg_dp(aux->drm_dev, + "Failed to read DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1\n"); + return false; + } + + return (rx_feature & DP_ADAPTIVE_SYNC_SDP_SUPPORTED); +} +EXPORT_SYMBOL(drm_dp_as_sdp_supported); + /** * drm_dp_vsc_sdp_supported() - check if vsc sdp is supported * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index 03d528209426..3577786b5db2 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -2274,7 +2274,7 @@ drm_dp_mst_port_add_connector(struct drm_dp_mst_branch *mstb, if (port->pdt != DP_PEER_DEVICE_NONE && drm_dp_mst_is_end_device(port->pdt, port->mcs) && - port->port_num >= DP_MST_LOGICAL_PORT_0) + drm_dp_mst_port_is_logical(port)) port->cached_edid = drm_edid_read_ddc(port->connector, &port->aux.ddc); @@ -3608,24 +3608,30 @@ fixed20_12 drm_dp_get_vc_payload_bw(const struct drm_dp_mst_topology_mgr *mgr, EXPORT_SYMBOL(drm_dp_get_vc_payload_bw); /** - * drm_dp_read_mst_cap() - check whether or not a sink supports MST + * drm_dp_read_mst_cap() - Read the sink's MST mode capability * @aux: The DP AUX channel to use * @dpcd: A cached copy of the DPCD capabilities for this sink * - * Returns: %True if the sink supports MST, %false otherwise + * Returns: enum drm_dp_mst_mode to indicate MST mode capability */ -bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, - const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +enum drm_dp_mst_mode drm_dp_read_mst_cap(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { u8 mstm_cap; if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) - return false; + return DRM_DP_SST; if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1) - return false; + return DRM_DP_SST; - return mstm_cap & DP_MST_CAP; + if (mstm_cap & DP_MST_CAP) + return DRM_DP_MST; + + if (mstm_cap & DP_SINGLE_STREAM_SIDEBAND_MSG) + return DRM_DP_SST_SIDEBAND_MSG; + + return DRM_DP_SST; } EXPORT_SYMBOL(drm_dp_read_mst_cap); @@ -4213,7 +4219,7 @@ drm_dp_mst_detect_port(struct drm_connector *connector, case DP_PEER_DEVICE_SST_SINK: ret = connector_status_connected; /* for logical ports - cache the EDID */ - if (port->port_num >= DP_MST_LOGICAL_PORT_0 && !port->cached_edid) + if (drm_dp_mst_port_is_logical(port) && !port->cached_edid) port->cached_edid = drm_edid_read_ddc(connector, &port->aux.ddc); break; case DP_PEER_DEVICE_DP_LEGACY_CONV: @@ -5977,7 +5983,7 @@ static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port) return false; /* Virtual DP Sink (Internal Display Panel) */ - if (port->port_num >= 8) + if (drm_dp_mst_port_is_logical(port)) return true; /* DP-to-HDMI Protocol Converter */ @@ -6004,6 +6010,22 @@ static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port) return false; } +/** + * drm_dp_mst_aux_for_parent() - Get the AUX device for an MST port's parent + * @port: MST port whose parent's AUX device is returned + * + * Return the AUX device for @port's parent or NULL if port's parent is the + * root port. + */ +struct drm_dp_aux *drm_dp_mst_aux_for_parent(struct drm_dp_mst_port *port) +{ + if (!port->parent || !port->parent->port_parent) + return NULL; + + return &port->parent->port_parent->aux; +} +EXPORT_SYMBOL(drm_dp_mst_aux_for_parent); + /** * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC * @port: The port to check. A leaf of the MST tree with an attached display. diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c index 2a91e9b11d03..48b2df120086 100644 --- a/drivers/gpu/drm/display/drm_dp_tunnel.c +++ b/drivers/gpu/drm/display/drm_dp_tunnel.c @@ -436,8 +436,8 @@ EXPORT_SYMBOL(drm_dp_tunnel_get); /** * drm_dp_tunnel_put - Put a reference for a DP tunnel - * @tunnel - Tunnel object - * @tracker - Debug tracker for the reference + * @tunnel: Tunnel object + * @tracker: Debug tracker for the reference * * Put a reference for @tunnel along with its debug *@tracker, which * was obtained with drm_dp_tunnel_get(). @@ -1170,7 +1170,7 @@ int drm_dp_tunnel_alloc_bw(struct drm_dp_tunnel *tunnel, int bw) EXPORT_SYMBOL(drm_dp_tunnel_alloc_bw); /** - * drm_dp_tunnel_atomic_get_allocated_bw - Get the BW allocated for a DP tunnel + * drm_dp_tunnel_get_allocated_bw - Get the BW allocated for a DP tunnel * @tunnel: Tunnel object * * Get the current BW allocated for @tunnel. After the tunnel is created / @@ -1892,6 +1892,7 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr) /** * drm_dp_tunnel_mgr_create - Create a DP tunnel manager * @dev: DRM device object + * @max_group_count: Maximum number of tunnel groups * * Creates a DP tunnel manager for @dev. * diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 39ef0a6addeb..fb97b51b38f1 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -3016,6 +3017,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state, bool stall) { int i, ret; + unsigned long flags; struct drm_connector *connector; struct drm_connector_state *old_conn_state, *new_conn_state; struct drm_crtc *crtc; @@ -3099,6 +3101,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state, } } + drm_panic_lock(state->dev, flags); for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) { WARN_ON(plane->state != old_plane_state); @@ -3108,6 +3111,7 @@ int drm_atomic_helper_swap_state(struct drm_atomic_state *state, state->planes[i].state = old_plane_state; plane->state = new_plane_state; } + drm_panic_unlock(state->dev, flags); for_each_oldnew_private_obj_in_state(state, obj, old_obj_state, new_obj_state, i) { WARN_ON(obj->state != old_obj_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 29d4940188d4..fc16fddee5c5 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -145,10 +145,10 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state, &state->mode, blob->data); if (ret) { drm_dbg_atomic(crtc->dev, - "[CRTC:%d:%s] invalid mode (ret=%d, status=%s):\n", + "[CRTC:%d:%s] invalid mode (%s, %pe): " DRM_MODE_FMT "\n", crtc->base.id, crtc->name, - ret, drm_get_mode_status_name(state->mode.status)); - drm_mode_debug_printmodeline(&state->mode); + drm_get_mode_status_name(state->mode.status), + ERR_PTR(ret), DRM_MODE_ARG(&state->mode)); return -EINVAL; } diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 5ebdd6f8f36e..284ebae71cc4 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -57,6 +57,16 @@ static void list_insert_sorted(struct drm_buddy *mm, __list_add(&block->link, node->link.prev, &node->link); } +static void clear_reset(struct drm_buddy_block *block) +{ + block->header &= ~DRM_BUDDY_HEADER_CLEAR; +} + +static void mark_cleared(struct drm_buddy_block *block) +{ + block->header |= DRM_BUDDY_HEADER_CLEAR; +} + static void mark_allocated(struct drm_buddy_block *block) { block->header &= ~DRM_BUDDY_HEADER_STATE; @@ -82,6 +92,133 @@ static void mark_split(struct drm_buddy_block *block) list_del(&block->link); } +static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) +{ + return s1 <= e2 && e1 >= s2; +} + +static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) +{ + return s1 <= s2 && e1 >= e2; +} + +static struct drm_buddy_block * +__get_buddy(struct drm_buddy_block *block) +{ + struct drm_buddy_block *parent; + + parent = block->parent; + if (!parent) + return NULL; + + if (parent->left == block) + return parent->right; + + return parent->left; +} + +static unsigned int __drm_buddy_free(struct drm_buddy *mm, + struct drm_buddy_block *block, + bool force_merge) +{ + struct drm_buddy_block *parent; + unsigned int order; + + while ((parent = block->parent)) { + struct drm_buddy_block *buddy; + + buddy = __get_buddy(block); + + if (!drm_buddy_block_is_free(buddy)) + break; + + if (!force_merge) { + /* + * Check the block and its buddy clear state and exit + * the loop if they both have the dissimilar state. + */ + if (drm_buddy_block_is_clear(block) != + drm_buddy_block_is_clear(buddy)) + break; + + if (drm_buddy_block_is_clear(block)) + mark_cleared(parent); + } + + list_del(&buddy->link); + if (force_merge && drm_buddy_block_is_clear(buddy)) + mm->clear_avail -= drm_buddy_block_size(mm, buddy); + + drm_block_free(mm, block); + drm_block_free(mm, buddy); + + block = parent; + } + + order = drm_buddy_block_order(block); + mark_free(mm, block); + + return order; +} + +static int __force_merge(struct drm_buddy *mm, + u64 start, + u64 end, + unsigned int min_order) +{ + unsigned int order; + int i; + + if (!min_order) + return -ENOMEM; + + if (min_order > mm->max_order) + return -EINVAL; + + for (i = min_order - 1; i >= 0; i--) { + struct drm_buddy_block *block, *prev; + + list_for_each_entry_safe_reverse(block, prev, &mm->free_list[i], link) { + struct drm_buddy_block *buddy; + u64 block_start, block_end; + + if (!block->parent) + continue; + + block_start = drm_buddy_block_offset(block); + block_end = block_start + drm_buddy_block_size(mm, block) - 1; + + if (!contains(start, end, block_start, block_end)) + continue; + + buddy = __get_buddy(block); + if (!drm_buddy_block_is_free(buddy)) + continue; + + WARN_ON(drm_buddy_block_is_clear(block) == + drm_buddy_block_is_clear(buddy)); + + /* + * If the prev block is same as buddy, don't access the + * block in the next iteration as we would free the + * buddy block as part of the free function. + */ + if (prev == buddy) + prev = list_prev_entry(prev, link); + + list_del(&block->link); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail -= drm_buddy_block_size(mm, block); + + order = __drm_buddy_free(mm, block, true); + if (order >= min_order) + return 0; + } + } + + return -ENOMEM; +} + /** * drm_buddy_init - init memory manager * @@ -186,11 +323,21 @@ EXPORT_SYMBOL(drm_buddy_init); */ void drm_buddy_fini(struct drm_buddy *mm) { + u64 root_size, size; + unsigned int order; int i; + size = mm->size; + for (i = 0; i < mm->n_roots; ++i) { + order = ilog2(size) - ilog2(mm->chunk_size); + __force_merge(mm, 0, size, order); + WARN_ON(!drm_buddy_block_is_free(mm->roots[i])); drm_block_free(mm, mm->roots[i]); + + root_size = mm->chunk_size << order; + size -= root_size; } WARN_ON(mm->avail != mm->size); @@ -223,26 +370,17 @@ static int split_block(struct drm_buddy *mm, mark_free(mm, block->left); mark_free(mm, block->right); + if (drm_buddy_block_is_clear(block)) { + mark_cleared(block->left); + mark_cleared(block->right); + clear_reset(block); + } + mark_split(block); return 0; } -static struct drm_buddy_block * -__get_buddy(struct drm_buddy_block *block) -{ - struct drm_buddy_block *parent; - - parent = block->parent; - if (!parent) - return NULL; - - if (parent->left == block) - return parent->right; - - return parent->left; -} - /** * drm_get_buddy - get buddy address * @@ -260,30 +398,6 @@ drm_get_buddy(struct drm_buddy_block *block) } EXPORT_SYMBOL(drm_get_buddy); -static void __drm_buddy_free(struct drm_buddy *mm, - struct drm_buddy_block *block) -{ - struct drm_buddy_block *parent; - - while ((parent = block->parent)) { - struct drm_buddy_block *buddy; - - buddy = __get_buddy(block); - - if (!drm_buddy_block_is_free(buddy)) - break; - - list_del(&buddy->link); - - drm_block_free(mm, block); - drm_block_free(mm, buddy); - - block = parent; - } - - mark_free(mm, block); -} - /** * drm_buddy_free_block - free a block * @@ -295,42 +409,74 @@ void drm_buddy_free_block(struct drm_buddy *mm, { BUG_ON(!drm_buddy_block_is_allocated(block)); mm->avail += drm_buddy_block_size(mm, block); - __drm_buddy_free(mm, block); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail += drm_buddy_block_size(mm, block); + + __drm_buddy_free(mm, block, false); } EXPORT_SYMBOL(drm_buddy_free_block); +static void __drm_buddy_free_list(struct drm_buddy *mm, + struct list_head *objects, + bool mark_clear, + bool mark_dirty) +{ + struct drm_buddy_block *block, *on; + + WARN_ON(mark_dirty && mark_clear); + + list_for_each_entry_safe(block, on, objects, link) { + if (mark_clear) + mark_cleared(block); + else if (mark_dirty) + clear_reset(block); + drm_buddy_free_block(mm, block); + cond_resched(); + } + INIT_LIST_HEAD(objects); +} + +static void drm_buddy_free_list_internal(struct drm_buddy *mm, + struct list_head *objects) +{ + /* + * Don't touch the clear/dirty bit, since allocation is still internal + * at this point. For example we might have just failed part of the + * allocation. + */ + __drm_buddy_free_list(mm, objects, false, false); +} + /** * drm_buddy_free_list - free blocks * * @mm: DRM buddy manager * @objects: input list head to free blocks + * @flags: optional flags like DRM_BUDDY_CLEARED */ -void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects) +void drm_buddy_free_list(struct drm_buddy *mm, + struct list_head *objects, + unsigned int flags) { - struct drm_buddy_block *block, *on; + bool mark_clear = flags & DRM_BUDDY_CLEARED; - list_for_each_entry_safe(block, on, objects, link) { - drm_buddy_free_block(mm, block); - cond_resched(); - } - INIT_LIST_HEAD(objects); + __drm_buddy_free_list(mm, objects, mark_clear, !mark_clear); } EXPORT_SYMBOL(drm_buddy_free_list); -static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) +static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags) { - return s1 <= e2 && e1 >= s2; -} + bool needs_clear = flags & DRM_BUDDY_CLEAR_ALLOCATION; -static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) -{ - return s1 <= s2 && e1 >= e2; + return needs_clear != drm_buddy_block_is_clear(block); } static struct drm_buddy_block * -alloc_range_bias(struct drm_buddy *mm, - u64 start, u64 end, - unsigned int order) +__alloc_range_bias(struct drm_buddy *mm, + u64 start, u64 end, + unsigned int order, + unsigned long flags, + bool fallback) { u64 req_size = mm->chunk_size << order; struct drm_buddy_block *block; @@ -379,6 +525,9 @@ alloc_range_bias(struct drm_buddy *mm, if (contains(start, end, block_start, block_end) && order == drm_buddy_block_order(block)) { + if (!fallback && block_incompatible(block, flags)) + continue; + /* * Find the free block within the range. */ @@ -410,30 +559,57 @@ alloc_range_bias(struct drm_buddy *mm, if (buddy && (drm_buddy_block_is_free(block) && drm_buddy_block_is_free(buddy))) - __drm_buddy_free(mm, block); + __drm_buddy_free(mm, block, false); return ERR_PTR(err); } static struct drm_buddy_block * -get_maxblock(struct drm_buddy *mm, unsigned int order) +__drm_buddy_alloc_range_bias(struct drm_buddy *mm, + u64 start, u64 end, + unsigned int order, + unsigned long flags) { - struct drm_buddy_block *max_block = NULL, *node; + struct drm_buddy_block *block; + bool fallback = false; + + block = __alloc_range_bias(mm, start, end, order, + flags, fallback); + if (IS_ERR(block) && mm->clear_avail) + return __alloc_range_bias(mm, start, end, order, + flags, !fallback); + + return block; +} + +static struct drm_buddy_block * +get_maxblock(struct drm_buddy *mm, unsigned int order, + unsigned long flags) +{ + struct drm_buddy_block *max_block = NULL, *block = NULL; unsigned int i; for (i = order; i <= mm->max_order; ++i) { - if (!list_empty(&mm->free_list[i])) { - node = list_last_entry(&mm->free_list[i], - struct drm_buddy_block, - link); - if (!max_block) { - max_block = node; - continue; - } + struct drm_buddy_block *tmp_block; - if (drm_buddy_block_offset(node) > - drm_buddy_block_offset(max_block)) { - max_block = node; - } + list_for_each_entry_reverse(tmp_block, &mm->free_list[i], link) { + if (block_incompatible(tmp_block, flags)) + continue; + + block = tmp_block; + break; + } + + if (!block) + continue; + + if (!max_block) { + max_block = block; + continue; + } + + if (drm_buddy_block_offset(block) > + drm_buddy_block_offset(max_block)) { + max_block = block; } } @@ -450,11 +626,29 @@ alloc_from_freelist(struct drm_buddy *mm, int err; if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) { - block = get_maxblock(mm, order); + block = get_maxblock(mm, order, flags); if (block) /* Store the obtained block order */ tmp = drm_buddy_block_order(block); } else { + for (tmp = order; tmp <= mm->max_order; ++tmp) { + struct drm_buddy_block *tmp_block; + + list_for_each_entry_reverse(tmp_block, &mm->free_list[tmp], link) { + if (block_incompatible(tmp_block, flags)) + continue; + + block = tmp_block; + break; + } + + if (block) + break; + } + } + + if (!block) { + /* Fallback method */ for (tmp = order; tmp <= mm->max_order; ++tmp) { if (!list_empty(&mm->free_list[tmp])) { block = list_last_entry(&mm->free_list[tmp], @@ -464,10 +658,10 @@ alloc_from_freelist(struct drm_buddy *mm, break; } } - } - if (!block) - return ERR_PTR(-ENOSPC); + if (!block) + return ERR_PTR(-ENOSPC); + } BUG_ON(!drm_buddy_block_is_free(block)); @@ -483,7 +677,7 @@ alloc_from_freelist(struct drm_buddy *mm, err_undo: if (tmp != order) - __drm_buddy_free(mm, block); + __drm_buddy_free(mm, block, false); return ERR_PTR(err); } @@ -526,16 +720,18 @@ static int __alloc_range(struct drm_buddy *mm, } if (contains(start, end, block_start, block_end)) { - if (!drm_buddy_block_is_free(block)) { + if (drm_buddy_block_is_free(block)) { + mark_allocated(block); + total_allocated += drm_buddy_block_size(mm, block); + mm->avail -= drm_buddy_block_size(mm, block); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail -= drm_buddy_block_size(mm, block); + list_add_tail(&block->link, &allocated); + continue; + } else if (!mm->clear_avail) { err = -ENOSPC; goto err_free; } - - mark_allocated(block); - total_allocated += drm_buddy_block_size(mm, block); - mm->avail -= drm_buddy_block_size(mm, block); - list_add_tail(&block->link, &allocated); - continue; } if (!drm_buddy_block_is_split(block)) { @@ -567,14 +763,14 @@ static int __alloc_range(struct drm_buddy *mm, if (buddy && (drm_buddy_block_is_free(block) && drm_buddy_block_is_free(buddy))) - __drm_buddy_free(mm, block); + __drm_buddy_free(mm, block, false); err_free: if (err == -ENOSPC && total_allocated_on_err) { list_splice_tail(&allocated, blocks); *total_allocated_on_err = total_allocated; } else { - drm_buddy_free_list(mm, &allocated); + drm_buddy_free_list_internal(mm, &allocated); } return err; @@ -640,11 +836,11 @@ static int __alloc_contig_try_harder(struct drm_buddy *mm, list_splice(&blocks_lhs, blocks); return 0; } else if (err != -ENOSPC) { - drm_buddy_free_list(mm, blocks); + drm_buddy_free_list_internal(mm, blocks); return err; } /* Free blocks for the next iteration */ - drm_buddy_free_list(mm, blocks); + drm_buddy_free_list_internal(mm, blocks); } return -ENOSPC; @@ -700,6 +896,8 @@ int drm_buddy_block_trim(struct drm_buddy *mm, list_del(&block->link); mark_free(mm, block); mm->avail += drm_buddy_block_size(mm, block); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail += drm_buddy_block_size(mm, block); /* Prevent recursively freeing this node */ parent = block->parent; @@ -711,6 +909,8 @@ int drm_buddy_block_trim(struct drm_buddy *mm, if (err) { mark_allocated(block); mm->avail -= drm_buddy_block_size(mm, block); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail -= drm_buddy_block_size(mm, block); list_add(&block->link, blocks); } @@ -719,13 +919,28 @@ int drm_buddy_block_trim(struct drm_buddy *mm, } EXPORT_SYMBOL(drm_buddy_block_trim); +static struct drm_buddy_block * +__drm_buddy_alloc_blocks(struct drm_buddy *mm, + u64 start, u64 end, + unsigned int order, + unsigned long flags) +{ + if (flags & DRM_BUDDY_RANGE_ALLOCATION) + /* Allocate traversing within the range */ + return __drm_buddy_alloc_range_bias(mm, start, end, + order, flags); + else + /* Allocate from freelist */ + return alloc_from_freelist(mm, order, flags); +} + /** * drm_buddy_alloc_blocks - allocate power-of-two blocks * * @mm: DRM buddy manager to allocate from * @start: start of the allowed range for this block * @end: end of the allowed range for this block - * @size: size of the allocation + * @size: size of the allocation in bytes * @min_block_size: alignment of the allocation * @blocks: output list head to add allocated blocks * @flags: DRM_BUDDY_*_ALLOCATION flags @@ -800,23 +1015,33 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, BUG_ON(order < min_order); do { - if (flags & DRM_BUDDY_RANGE_ALLOCATION) - /* Allocate traversing within the range */ - block = alloc_range_bias(mm, start, end, order); - else - /* Allocate from freelist */ - block = alloc_from_freelist(mm, order, flags); - + block = __drm_buddy_alloc_blocks(mm, start, + end, + order, + flags); if (!IS_ERR(block)) break; if (order-- == min_order) { + /* Try allocation through force merge method */ + if (mm->clear_avail && + !__force_merge(mm, start, end, min_order)) { + block = __drm_buddy_alloc_blocks(mm, start, + end, + min_order, + flags); + if (!IS_ERR(block)) { + order = min_order; + break; + } + } + + /* + * Try contiguous block allocation through + * try harder method. + */ if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION && !(flags & DRM_BUDDY_RANGE_ALLOCATION)) - /* - * Try contiguous block allocation through - * try harder method - */ return __alloc_contig_try_harder(mm, original_size, original_min_size, @@ -828,6 +1053,8 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, mark_allocated(block); mm->avail -= drm_buddy_block_size(mm, block); + if (drm_buddy_block_is_clear(block)) + mm->clear_avail -= drm_buddy_block_size(mm, block); kmemleak_update_trace(block); list_add_tail(&block->link, &allocated); @@ -866,7 +1093,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, return 0; err_free: - drm_buddy_free_list(mm, &allocated); + drm_buddy_free_list_internal(mm, &allocated); return err; } EXPORT_SYMBOL(drm_buddy_alloc_blocks); @@ -899,8 +1126,8 @@ void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p) { int order; - drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB\n", - mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20); + drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n", + mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20); for (order = mm->max_order; order >= 0; order--) { struct drm_buddy_block *block; diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 871e4e2129d6..31af5cf37a09 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -242,8 +242,10 @@ static void drm_client_connectors_enabled(struct drm_connector **connectors, for (i = 0; i < connector_count; i++) { connector = connectors[i]; enabled[i] = drm_connector_enabled(connector, true); - DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, - connector->display_info.non_desktop ? "non desktop" : str_yes_no(enabled[i])); + drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] enabled? %s\n", + connector->base.id, connector->name, + connector->display_info.non_desktop ? + "non desktop" : str_yes_no(enabled[i])); any_enabled |= enabled[i]; } @@ -303,7 +305,7 @@ static bool drm_client_target_cloned(struct drm_device *dev, } if (can_clone) { - DRM_DEBUG_KMS("can clone using command line\n"); + drm_dbg_kms(dev, "can clone using command line\n"); return true; } @@ -332,15 +334,16 @@ static bool drm_client_target_cloned(struct drm_device *dev, kfree(dmt_mode); if (can_clone) { - DRM_DEBUG_KMS("can clone using 1024x768\n"); + drm_dbg_kms(dev, "can clone using 1024x768\n"); return true; } fail: - DRM_INFO("kms: can't enable cloning when we probably wanted to.\n"); + drm_info(dev, "kms: can't enable cloning when we probably wanted to.\n"); return false; } -static int drm_client_get_tile_offsets(struct drm_connector **connectors, +static int drm_client_get_tile_offsets(struct drm_device *dev, + struct drm_connector **connectors, unsigned int connector_count, struct drm_display_mode **modes, struct drm_client_offset *offsets, @@ -357,8 +360,9 @@ static int drm_client_get_tile_offsets(struct drm_connector **connectors, continue; if (!modes[i] && (h_idx || v_idx)) { - DRM_DEBUG_KMS("no modes for connector tiled %d %d\n", i, - connector->base.id); + drm_dbg_kms(dev, + "[CONNECTOR:%d:%s] no modes for connector tiled %d\n", + connector->base.id, connector->name, i); continue; } if (connector->tile_h_loc < h_idx) @@ -369,11 +373,12 @@ static int drm_client_get_tile_offsets(struct drm_connector **connectors, } offsets[idx].x = hoffset; offsets[idx].y = voffset; - DRM_DEBUG_KMS("returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); + drm_dbg_kms(dev, "returned %d %d for %d %d\n", hoffset, voffset, h_idx, v_idx); return 0; } -static bool drm_client_target_preferred(struct drm_connector **connectors, +static bool drm_client_target_preferred(struct drm_device *dev, + struct drm_connector **connectors, unsigned int connector_count, struct drm_display_mode **modes, struct drm_client_offset *offsets, @@ -423,17 +428,19 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, * find the tile offsets for this pass - need to find * all tiles left and above */ - drm_client_get_tile_offsets(connectors, connector_count, modes, offsets, i, + drm_client_get_tile_offsets(dev, connectors, connector_count, + modes, offsets, i, connector->tile_h_loc, connector->tile_v_loc); } - DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n", - connector->base.id); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] looking for cmdline mode\n", + connector->base.id, connector->name); /* got for command line mode first */ modes[i] = drm_connector_pick_cmdline_mode(connector); if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %d %d\n", - connector->base.id, connector->tile_group ? connector->tile_group->id : 0); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] looking for preferred mode, tile %d\n", + connector->base.id, connector->name, + connector->tile_group ? connector->tile_group->id : 0); modes[i] = drm_connector_has_preferred_mode(connector, width, height); } /* No preferred modes, pick one off the list */ @@ -455,16 +462,18 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, (connector->tile_h_loc == 0 && connector->tile_v_loc == 0 && !drm_connector_get_tiled_mode(connector))) { - DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", - connector->base.id); + drm_dbg_kms(dev, + "[CONNECTOR:%d:%s] Falling back to non-tiled mode\n", + connector->base.id, connector->name); modes[i] = drm_connector_fallback_non_tiled_mode(connector); } else { modes[i] = drm_connector_get_tiled_mode(connector); } } - DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : - "none"); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Found mode %s\n", + connector->base.id, connector->name, + modes[i] ? modes[i]->name : "none"); conn_configured |= BIT_ULL(i); } @@ -585,7 +594,7 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, if (!drm_drv_uses_atomic_modeset(dev)) return false; - if (WARN_ON(count <= 0)) + if (drm_WARN_ON(dev, count <= 0)) return false; save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL); @@ -624,26 +633,26 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, num_connectors_detected++; if (!enabled[i]) { - DRM_DEBUG_KMS("connector %s not enabled, skipping\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] not enabled, skipping\n", + connector->base.id, connector->name); conn_configured |= BIT(i); continue; } if (connector->force == DRM_FORCE_OFF) { - DRM_DEBUG_KMS("connector %s is disabled by user, skipping\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] disabled by user, skipping\n", + connector->base.id, connector->name); enabled[i] = false; continue; } encoder = connector->state->best_encoder; - if (!encoder || WARN_ON(!connector->state->crtc)) { + if (!encoder || drm_WARN_ON(dev, !connector->state->crtc)) { if (connector->force > DRM_FORCE_OFF) goto bail; - DRM_DEBUG_KMS("connector %s has no encoder or crtc, skipping\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] has no encoder or crtc, skipping\n", + connector->base.id, connector->name); enabled[i] = false; conn_configured |= BIT(i); continue; @@ -660,28 +669,30 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, */ for (j = 0; j < count; j++) { if (crtcs[j] == new_crtc) { - DRM_DEBUG_KMS("fallback: cloned configuration\n"); + drm_dbg_kms(dev, "fallback: cloned configuration\n"); goto bail; } } - DRM_DEBUG_KMS("looking for cmdline mode on connector %s\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] looking for cmdline mode\n", + connector->base.id, connector->name); /* go for command line mode first */ modes[i] = drm_connector_pick_cmdline_mode(connector); /* try for preferred next */ if (!modes[i]) { - DRM_DEBUG_KMS("looking for preferred mode on connector %s %d\n", - connector->name, connector->has_tile); + drm_dbg_kms(dev, + "[CONNECTOR:%d:%s] looking for preferred mode, has tile: %s\n", + connector->base.id, connector->name, + str_yes_no(connector->has_tile)); modes[i] = drm_connector_has_preferred_mode(connector, width, height); } /* No preferred mode marked by the EDID? Are there any modes? */ if (!modes[i] && !list_empty(&connector->modes)) { - DRM_DEBUG_KMS("using first mode listed on connector %s\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] using first listed mode\n", + connector->base.id, connector->name); modes[i] = list_first_entry(&connector->modes, struct drm_display_mode, head); @@ -700,8 +711,8 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, * This is crtc->mode and not crtc->state->mode for the * fastboot check to work correctly. */ - DRM_DEBUG_KMS("looking for current mode on connector %s\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] looking for current mode\n", + connector->base.id, connector->name); modes[i] = &connector->state->crtc->mode; } /* @@ -710,18 +721,18 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, */ if (connector->has_tile && num_tiled_conns < connector->num_h_tile * connector->num_v_tile) { - DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", - connector->base.id); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Falling back to non-tiled mode\n", + connector->base.id, connector->name); modes[i] = drm_connector_fallback_non_tiled_mode(connector); } crtcs[i] = new_crtc; - DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", - connector->name, - connector->state->crtc->base.id, - connector->state->crtc->name, - modes[i]->hdisplay, modes[i]->vdisplay, - modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] on [CRTC:%d:%s]: %dx%d%s\n", + connector->base.id, connector->name, + connector->state->crtc->base.id, + connector->state->crtc->name, + modes[i]->hdisplay, modes[i]->vdisplay, + modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" : ""); fallback = false; conn_configured |= BIT(i); @@ -737,15 +748,15 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, */ if (num_connectors_enabled != num_connectors_detected && num_connectors_enabled < dev->mode_config.num_crtc) { - DRM_DEBUG_KMS("fallback: Not all outputs enabled\n"); - DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled, - num_connectors_detected); + drm_dbg_kms(dev, "fallback: Not all outputs enabled\n"); + drm_dbg_kms(dev, "Enabled: %i, detected: %i\n", + num_connectors_enabled, num_connectors_detected); fallback = true; } if (fallback) { bail: - DRM_DEBUG_KMS("Not using firmware configuration\n"); + drm_dbg_kms(dev, "Not using firmware configuration\n"); memcpy(enabled, save_enabled, count); ret = false; } @@ -777,12 +788,13 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int total_modes_count = 0; struct drm_client_offset *offsets; unsigned int connector_count = 0; + /* points to modes protected by mode_config.mutex */ struct drm_display_mode **modes; struct drm_crtc **crtcs; int i, ret = 0; bool *enabled; - DRM_DEBUG_KMS("\n"); + drm_dbg_kms(dev, "\n"); if (!width) width = dev->mode_config.max_width; @@ -813,7 +825,6 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, offsets = kcalloc(connector_count, sizeof(*offsets), GFP_KERNEL); enabled = kcalloc(connector_count, sizeof(bool), GFP_KERNEL); if (!crtcs || !modes || !enabled || !offsets) { - DRM_ERROR("Memory allocation failed\n"); ret = -ENOMEM; goto out; } @@ -824,7 +835,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, for (i = 0; i < connector_count; i++) total_modes_count += connectors[i]->funcs->fill_modes(connectors[i], width, height); if (!total_modes_count) - DRM_DEBUG_KMS("No connectors reported connected with modes\n"); + drm_dbg_kms(dev, "No connectors reported connected with modes\n"); drm_client_connectors_enabled(connectors, connector_count, enabled); if (!drm_client_firmware_config(client, connectors, connector_count, crtcs, @@ -835,17 +846,16 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, if (!drm_client_target_cloned(dev, connectors, connector_count, modes, offsets, enabled, width, height) && - !drm_client_target_preferred(connectors, connector_count, modes, + !drm_client_target_preferred(dev, connectors, connector_count, modes, offsets, enabled, width, height)) - DRM_ERROR("Unable to find initial modes\n"); + drm_err(dev, "Unable to find initial modes\n"); - DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", - width, height); + drm_dbg_kms(dev, "picking CRTCs for %dx%d config\n", + width, height); drm_client_pick_crtcs(client, connectors, connector_count, crtcs, modes, 0, width, height); } - mutex_unlock(&dev->mode_config.mutex); drm_client_modeset_release(client); @@ -858,11 +868,12 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc); struct drm_connector *connector = connectors[i]; - DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n", - mode->name, crtc->base.id, offset->x, offset->y); + drm_dbg_kms(dev, "[CRTC:%d:%s] desired mode %s set (%d,%d)\n", + crtc->base.id, crtc->name, + mode->name, offset->x, offset->y); - if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || - (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) { + if (drm_WARN_ON_ONCE(dev, modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS || + (dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1))) { ret = -EINVAL; break; } @@ -875,6 +886,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, modeset->y = offset->y; } } + mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&client->modeset_mutex); out: diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 82c665d3e74b..483969b84a30 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -716,10 +716,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id); if (!crtc) { - DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); + drm_dbg_kms(dev, "Unknown CRTC ID %d\n", crtc_req->crtc_id); return -ENOENT; } - DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); + drm_dbg_kms(dev, "[CRTC:%d:%s]\n", crtc->base.id, crtc->name); plane = crtc->primary; @@ -742,7 +742,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, old_fb = plane->fb; if (!old_fb) { - DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); + drm_dbg_kms(dev, "CRTC doesn't have current FB\n"); ret = -EINVAL; goto out; } @@ -753,8 +753,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } else { fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id); if (!fb) { - DRM_DEBUG_KMS("Unknown FB ID%d\n", - crtc_req->fb_id); + drm_dbg_kms(dev, "Unknown FB ID%d\n", + crtc_req->fb_id); ret = -ENOENT; goto out; } @@ -767,7 +767,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } if (!file_priv->aspect_ratio_allowed && (crtc_req->mode.flags & DRM_MODE_FLAG_PIC_AR_MASK) != DRM_MODE_FLAG_PIC_AR_NONE) { - DRM_DEBUG_KMS("Unexpected aspect-ratio flag bits\n"); + drm_dbg_kms(dev, "Unexpected aspect-ratio flag bits\n"); ret = -EINVAL; goto out; } @@ -775,9 +775,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ret = drm_mode_convert_umode(dev, mode, &crtc_req->mode); if (ret) { - DRM_DEBUG_KMS("Invalid mode (ret=%d, status=%s)\n", - ret, drm_get_mode_status_name(mode->status)); - drm_mode_debug_printmodeline(mode); + drm_dbg_kms(dev, "Invalid mode (%s, %pe): " DRM_MODE_FMT "\n", + drm_get_mode_status_name(mode->status), + ERR_PTR(ret), DRM_MODE_ARG(mode)); goto out; } @@ -793,9 +793,8 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, fb->format->format, fb->modifier); if (ret) { - DRM_DEBUG_KMS("Invalid pixel format %p4cc, modifier 0x%llx\n", - &fb->format->format, - fb->modifier); + drm_dbg_kms(dev, "Invalid pixel format %p4cc, modifier 0x%llx\n", + &fb->format->format, fb->modifier); goto out; } } @@ -808,14 +807,14 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, } if (crtc_req->count_connectors == 0 && mode) { - DRM_DEBUG_KMS("Count connectors is 0 but mode set\n"); + drm_dbg_kms(dev, "Count connectors is 0 but mode set\n"); ret = -EINVAL; goto out; } if (crtc_req->count_connectors > 0 && (!mode || !fb)) { - DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n", - crtc_req->count_connectors); + drm_dbg_kms(dev, "Count connectors is %d but no mode or fb set\n", + crtc_req->count_connectors); ret = -EINVAL; goto out; } @@ -847,14 +846,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, connector = drm_connector_lookup(dev, file_priv, out_id); if (!connector) { - DRM_DEBUG_KMS("Connector id %d unknown\n", - out_id); + drm_dbg_kms(dev, "Connector id %d unknown\n", + out_id); ret = -ENOENT; goto out; } - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", - connector->base.id, - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); connector_set[i] = connector; num_connectors++; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 2dafc39a27cb..0955f1c385dd 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -110,15 +110,15 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder) struct drm_connector_list_iter conn_iter; struct drm_device *dev = encoder->dev; - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); /* * We can expect this mutex to be locked if we are not panicking. * Locking is currently fubar in the panic handler. */ if (!oops_in_progress) { - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); - WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex)); + drm_WARN_ON(dev, !drm_modeset_is_locked(&dev->mode_config.connection_mutex)); } @@ -150,14 +150,14 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) struct drm_encoder *encoder; struct drm_device *dev = crtc->dev; - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); /* * We can expect this mutex to be locked if we are not panicking. * Locking is currently fubar in the panic handler. */ if (!oops_in_progress) - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); + drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex)); drm_for_each_encoder(encoder, dev) if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) @@ -230,7 +230,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev) */ void drm_helper_disable_unused_functions(struct drm_device *dev) { - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); drm_modeset_lock_all(dev); __drm_helper_disable_unused_functions(dev); @@ -294,7 +294,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_encoder *encoder; bool ret = true; - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); drm_warn_on_modeset_not_all_locked(dev); @@ -338,7 +338,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (encoder_funcs->mode_fixup) { if (!(ret = encoder_funcs->mode_fixup(encoder, mode, adjusted_mode))) { - DRM_DEBUG_KMS("Encoder fixup failed\n"); + drm_dbg_kms(dev, "[ENCODER:%d:%s] mode fixup failed\n", + encoder->base.id, encoder->name); goto done; } } @@ -347,11 +348,12 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (crtc_funcs->mode_fixup) { if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { - DRM_DEBUG_KMS("CRTC fixup failed\n"); + drm_dbg_kms(dev, "[CRTC:%d:%s] mode fixup failed\n", + crtc->base.id, crtc->name); goto done; } } - DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); + drm_dbg_kms(dev, "[CRTC:%d:%s]\n", crtc->base.id, crtc->name); drm_mode_copy(&crtc->hwmode, adjusted_mode); @@ -390,8 +392,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, if (!encoder_funcs) continue; - DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%s]\n", - encoder->base.id, encoder->name, mode->name); + drm_dbg_kms(dev, "[ENCODER:%d:%s] set [MODE:%s]\n", + encoder->base.id, encoder->name, mode->name); if (encoder_funcs->mode_set) encoder_funcs->mode_set(encoder, mode, adjusted_mode); } @@ -503,7 +505,7 @@ drm_connector_get_single_encoder(struct drm_connector *connector) { struct drm_encoder *encoder; - WARN_ON(hweight32(connector->possible_encoders) > 1); + drm_WARN_ON(connector->dev, hweight32(connector->possible_encoders) > 1); drm_connector_for_each_possible_encoder(connector, encoder) return encoder; @@ -564,8 +566,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, int ret; int i; - DRM_DEBUG_KMS("\n"); - BUG_ON(!set); BUG_ON(!set->crtc); BUG_ON(!set->crtc->helper_private); @@ -577,19 +577,22 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, crtc_funcs = set->crtc->helper_private; dev = set->crtc->dev; - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + + drm_dbg_kms(dev, "\n"); + + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); if (!set->mode) set->fb = NULL; if (set->fb) { - DRM_DEBUG_KMS("[CRTC:%d:%s] [FB:%d] #connectors=%d (x y) (%i %i)\n", - set->crtc->base.id, set->crtc->name, - set->fb->base.id, - (int)set->num_connectors, set->x, set->y); + drm_dbg_kms(dev, "[CRTC:%d:%s] [FB:%d] #connectors=%d (x y) (%i %i)\n", + set->crtc->base.id, set->crtc->name, + set->fb->base.id, + (int)set->num_connectors, set->x, set->y); } else { - DRM_DEBUG_KMS("[CRTC:%d:%s] [NOFB]\n", - set->crtc->base.id, set->crtc->name); + drm_dbg_kms(dev, "[CRTC:%d:%s] [NOFB]\n", + set->crtc->base.id, set->crtc->name); drm_crtc_helper_disable(set->crtc); return 0; } @@ -639,7 +642,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, if (set->crtc->primary->fb != set->fb) { /* If we have no fb then treat it as a full mode set */ if (set->crtc->primary->fb == NULL) { - DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); + drm_dbg_kms(dev, "[CRTC:%d:%s] no fb, full mode set\n", + set->crtc->base.id, set->crtc->name); mode_changed = true; } else if (set->fb->format != set->crtc->primary->fb->format) { mode_changed = true; @@ -651,9 +655,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, fb_changed = true; if (!drm_mode_equal(set->mode, &set->crtc->mode)) { - DRM_DEBUG_KMS("modes are different, full mode set\n"); - drm_mode_debug_printmodeline(&set->crtc->mode); - drm_mode_debug_printmodeline(set->mode); + drm_dbg_kms(dev, "[CRTC:%d:%s] modes are different, full mode set:\n", + set->crtc->base.id, set->crtc->name); + drm_dbg_kms(dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(&set->crtc->mode)); + drm_dbg_kms(dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(set->mode)); mode_changed = true; } @@ -687,7 +692,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, fail = 1; if (connector->dpms != DRM_MODE_DPMS_ON) { - DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] DPMS not on, full mode switch\n", + connector->base.id, connector->name); mode_changed = true; } @@ -696,7 +702,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, } if (new_encoder != connector->encoder) { - DRM_DEBUG_KMS("encoder changed, full mode switch\n"); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] encoder changed, full mode switch\n", + connector->base.id, connector->name); mode_changed = true; /* If the encoder is reused for another connector, then * the appropriate crtc will be set later. @@ -737,17 +744,18 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, goto fail; } if (new_crtc != connector->encoder->crtc) { - DRM_DEBUG_KMS("crtc changed, full mode switch\n"); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] CRTC changed, full mode switch\n", + connector->base.id, connector->name); mode_changed = true; connector->encoder->crtc = new_crtc; } if (new_crtc) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n", - connector->base.id, connector->name, - new_crtc->base.id, new_crtc->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] to [CRTC:%d:%s]\n", + connector->base.id, connector->name, + new_crtc->base.id, new_crtc->name); } else { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", - connector->base.id, connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] to [NOCRTC]\n", + connector->base.id, connector->name); } } drm_connector_list_iter_end(&conn_iter); @@ -758,23 +766,23 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, if (mode_changed) { if (drm_helper_crtc_in_use(set->crtc)) { - DRM_DEBUG_KMS("attempting to set mode from" - " userspace\n"); - drm_mode_debug_printmodeline(set->mode); + drm_dbg_kms(dev, "[CRTC:%d:%s] attempting to set mode from userspace: " DRM_MODE_FMT "\n", + set->crtc->base.id, set->crtc->name, DRM_MODE_ARG(set->mode)); set->crtc->primary->fb = set->fb; if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x, set->y, save_set.fb)) { - DRM_ERROR("failed to set mode on [CRTC:%d:%s]\n", - set->crtc->base.id, set->crtc->name); + drm_err(dev, "[CRTC:%d:%s] failed to set mode\n", + set->crtc->base.id, set->crtc->name); set->crtc->primary->fb = save_set.fb; ret = -EINVAL; goto fail; } - DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); + drm_dbg_kms(dev, "[CRTC:%d:%s] Setting connector DPMS state to on\n", + set->crtc->base.id, set->crtc->name); for (i = 0; i < set->num_connectors; i++) { - DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, - set->connectors[i]->name); + drm_dbg_kms(dev, "\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, + set->connectors[i]->name); set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); } } @@ -823,7 +831,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set, if (mode_changed && !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x, save_set.y, save_set.fb)) - DRM_ERROR("failed to restore config after modeset failure\n"); + drm_err(dev, "failed to restore config after modeset failure\n"); kfree(save_connector_encoders); kfree(save_encoder_crtcs); @@ -905,7 +913,7 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode) struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; int old_dpms, encoder_dpms = DRM_MODE_DPMS_OFF; - WARN_ON(drm_drv_uses_atomic_modeset(connector->dev)); + drm_WARN_ON(connector->dev, drm_drv_uses_atomic_modeset(connector->dev)); if (mode == connector->dpms) return 0; @@ -980,7 +988,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) int encoder_dpms; bool ret; - WARN_ON(drm_drv_uses_atomic_modeset(dev)); + drm_WARN_ON(dev, drm_drv_uses_atomic_modeset(dev)); drm_modeset_lock_all(dev); drm_for_each_crtc(crtc, dev) { @@ -993,7 +1001,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev) /* Restoring the old config should never fail! */ if (ret == false) - DRM_ERROR("failed to set mode on crtc %p\n", crtc); + drm_err(dev, "failed to set mode on crtc %p\n", crtc); /* Turn off outputs that were already powered off */ if (drm_helper_choose_crtc_dpms(crtc)) { diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index 0c693229a1c9..25aaae937ceb 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -43,12 +43,14 @@ enum drm_color_range; enum drm_connector_force; enum drm_mode_status; +struct cea_sad; struct drm_atomic_state; struct drm_bridge; struct drm_connector; struct drm_crtc; struct drm_device; struct drm_display_mode; +struct drm_edid; struct drm_file; struct drm_framebuffer; struct drm_mode_create_dumb; @@ -297,6 +299,10 @@ void drm_mode_fixup_1366x768(struct drm_display_mode *mode); int drm_edid_override_show(struct drm_connector *connector, struct seq_file *m); int drm_edid_override_set(struct drm_connector *connector, const void *edid, size_t size); int drm_edid_override_reset(struct drm_connector *connector); +const u8 *drm_edid_find_extension(const struct drm_edid *drm_edid, + int ext_id, int *ext_index); +void drm_edid_cta_sad_get(const struct cea_sad *cta_sad, u8 *sad); +void drm_edid_cta_sad_set(struct cea_sad *cta_sad, const u8 *sad); /* drm_edid_load.c */ #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE diff --git a/drivers/gpu/drm/drm_displayid.c b/drivers/gpu/drm/drm_displayid.c index 9edc111be7ee..9d01d762801f 100644 --- a/drivers/gpu/drm/drm_displayid.c +++ b/drivers/gpu/drm/drm_displayid.c @@ -3,10 +3,12 @@ * Copyright © 2021 Intel Corporation */ -#include #include #include +#include "drm_crtc_internal.h" +#include "drm_displayid_internal.h" + static const struct displayid_header * displayid_get_header(const u8 *displayid, int length, int index) { @@ -53,9 +55,10 @@ static const u8 *drm_find_displayid_extension(const struct drm_edid *drm_edid, int *length, int *idx, int *ext_index) { - const u8 *displayid = drm_find_edid_extension(drm_edid, DISPLAYID_EXT, ext_index); const struct displayid_header *base; + const u8 *displayid; + displayid = drm_edid_find_extension(drm_edid, DISPLAYID_EXT, ext_index); if (!displayid) return NULL; diff --git a/include/drm/drm_displayid.h b/drivers/gpu/drm/drm_displayid_internal.h similarity index 98% rename from include/drm/drm_displayid.h rename to drivers/gpu/drm/drm_displayid_internal.h index 566497eeb3b8..aee1b86a73c1 100644 --- a/include/drm/drm_displayid.h +++ b/drivers/gpu/drm/drm_displayid_internal.h @@ -19,8 +19,9 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef DRM_DISPLAYID_H -#define DRM_DISPLAYID_H + +#ifndef __DRM_DISPLAYID_INTERNAL_H__ +#define __DRM_DISPLAYID_INTERNAL_H__ #include #include @@ -30,7 +31,6 @@ struct drm_edid; #define VESA_IEEE_OUI 0x3a0292 /* DisplayID Structure versions */ -#define DISPLAY_ID_STRUCTURE_VER_12 0x12 #define DISPLAY_ID_STRUCTURE_VER_20 0x20 /* DisplayID Structure v1r2 Data Blocks */ diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 243cacb3575c..535b624d4c9d 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -638,6 +639,7 @@ static int drm_dev_init(struct drm_device *dev, mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); + raw_spin_lock_init(&dev->mode_config.panic_lock); ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL); if (ret) @@ -943,6 +945,7 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (ret) goto err_unload; } + drm_panic_register(dev); DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver->name, driver->major, driver->minor, @@ -987,6 +990,8 @@ void drm_dev_unregister(struct drm_device *dev) { dev->registered = false; + drm_panic_unregister(dev); + drm_client_dev_unregister(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ea77577a3786..4f54c91b31b2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -29,16 +29,17 @@ */ #include +#include #include #include #include #include #include #include +#include #include #include -#include #include #include #include @@ -46,6 +47,7 @@ #include #include "drm_crtc_internal.h" +#include "drm_displayid_internal.h" #include "drm_internal.h" static int oui(u8 first, u8 second, u8 third) @@ -1818,36 +1820,25 @@ static bool edid_block_is_zero(const void *edid) return !memchr_inv(edid, 0, EDID_LENGTH); } -/** - * drm_edid_are_equal - compare two edid blobs. - * @edid1: pointer to first blob - * @edid2: pointer to second blob - * This helper can be used during probing to determine if - * edid had changed. - */ -bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2) +static bool drm_edid_eq(const struct drm_edid *drm_edid, + const void *raw_edid, size_t raw_edid_size) { - int edid1_len, edid2_len; - bool edid1_present = edid1 != NULL; - bool edid2_present = edid2 != NULL; + bool edid1_present = drm_edid && drm_edid->edid && drm_edid->size; + bool edid2_present = raw_edid && raw_edid_size; if (edid1_present != edid2_present) return false; - if (edid1) { - edid1_len = edid_size(edid1); - edid2_len = edid_size(edid2); - - if (edid1_len != edid2_len) + if (edid1_present) { + if (drm_edid->size != raw_edid_size) return false; - if (memcmp(edid1, edid2, edid1_len)) + if (memcmp(drm_edid->edid, raw_edid, drm_edid->size)) return false; } return true; } -EXPORT_SYMBOL(drm_edid_are_equal); enum edid_block_status { EDID_BLOCK_OK = 0, @@ -2756,6 +2747,63 @@ const struct drm_edid *drm_edid_read(struct drm_connector *connector) } EXPORT_SYMBOL(drm_edid_read); +/** + * drm_edid_get_product_id - Get the vendor and product identification + * @drm_edid: EDID + * @id: Where to place the product id + */ +void drm_edid_get_product_id(const struct drm_edid *drm_edid, + struct drm_edid_product_id *id) +{ + if (drm_edid && drm_edid->edid && drm_edid->size >= EDID_LENGTH) + memcpy(id, &drm_edid->edid->product_id, sizeof(*id)); + else + memset(id, 0, sizeof(*id)); +} +EXPORT_SYMBOL(drm_edid_get_product_id); + +static void decode_date(struct seq_buf *s, const struct drm_edid_product_id *id) +{ + int week = id->week_of_manufacture; + int year = id->year_of_manufacture + 1990; + + if (week == 0xff) + seq_buf_printf(s, "model year: %d", year); + else if (!week) + seq_buf_printf(s, "year of manufacture: %d", year); + else + seq_buf_printf(s, "week/year of manufacture: %d/%d", week, year); +} + +/** + * drm_edid_print_product_id - Print decoded product id to printer + * @p: drm printer + * @id: EDID product id + * @raw: If true, also print the raw hex + * + * See VESA E-EDID 1.4 section 3.4. + */ +void drm_edid_print_product_id(struct drm_printer *p, + const struct drm_edid_product_id *id, bool raw) +{ + DECLARE_SEQ_BUF(date, 40); + char vend[4]; + + drm_edid_decode_mfg_id(be16_to_cpu(id->manufacturer_name), vend); + + decode_date(&date, id); + + drm_printf(p, "manufacturer name: %s, product code: %u, serial number: %u, %s\n", + vend, le16_to_cpu(id->product_code), + le32_to_cpu(id->serial_number), seq_buf_str(&date)); + + if (raw) + drm_printf(p, "raw product id: %*ph\n", (int)sizeof(*id), id); + + WARN_ON(seq_buf_has_overflowed(&date)); +} +EXPORT_SYMBOL(drm_edid_print_product_id); + /** * drm_edid_get_panel_id - Get a panel's ID from EDID * @drm_edid: EDID that contains panel ID. @@ -4141,7 +4189,7 @@ static int add_detailed_modes(struct drm_connector *connector, * * FIXME: Prefer not returning pointers to raw EDID data. */ -const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid, +const u8 *drm_edid_find_extension(const struct drm_edid *drm_edid, int ext_id, int *ext_index) { const u8 *edid_ext = NULL; @@ -4171,11 +4219,21 @@ static bool drm_edid_has_cta_extension(const struct drm_edid *drm_edid) { const struct displayid_block *block; struct displayid_iter iter; - int ext_index = 0; + struct drm_edid_iter edid_iter; + const u8 *ext; bool found = false; /* Look for a top level CEA extension block */ - if (drm_find_edid_extension(drm_edid, CEA_EXT, &ext_index)) + drm_edid_iter_begin(drm_edid, &edid_iter); + drm_edid_iter_for_each(ext, &edid_iter) { + if (ext[0] == CEA_EXT) { + found = true; + break; + } + } + drm_edid_iter_end(&edid_iter); + + if (found) return true; /* CEA blocks can also be found embedded in a DisplayID block */ @@ -6868,15 +6926,14 @@ static int _drm_edid_connector_property_update(struct drm_connector *connector, int ret; if (connector->edid_blob_ptr) { - const struct edid *old_edid = connector->edid_blob_ptr->data; + const void *old_edid = connector->edid_blob_ptr->data; + size_t old_edid_size = connector->edid_blob_ptr->length; - if (old_edid) { - if (!drm_edid_are_equal(drm_edid ? drm_edid->edid : NULL, old_edid)) { - connector->epoch_counter++; - drm_dbg_kms(dev, "[CONNECTOR:%d:%s] EDID changed, epoch counter %llu\n", - connector->base.id, connector->name, - connector->epoch_counter); - } + if (old_edid && !drm_edid_eq(drm_edid, old_edid, old_edid_size)) { + connector->epoch_counter++; + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] EDID changed, epoch counter %llu\n", + connector->base.id, connector->name, + connector->epoch_counter); } } @@ -7405,7 +7462,7 @@ static void drm_parse_tiled_block(struct drm_connector *connector, static bool displayid_is_tiled_block(const struct displayid_iter *iter, const struct displayid_block *block) { - return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && + return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 && block->tag == DATA_BLOCK_TILED_DISPLAY) || (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY); diff --git a/drivers/gpu/drm/drm_eld.c b/drivers/gpu/drm/drm_eld.c index 5177991aa272..c0428d07de53 100644 --- a/drivers/gpu/drm/drm_eld.c +++ b/drivers/gpu/drm/drm_eld.c @@ -3,10 +3,12 @@ * Copyright © 2023 Intel Corporation */ +#include + #include #include -#include "drm_internal.h" +#include "drm_crtc_internal.h" /** * drm_eld_sad_get - get SAD from ELD to struct cea_sad diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index 3b535ad1b07c..96e5ab960f12 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -148,3 +149,44 @@ void drm_fb_dma_sync_non_coherent(struct drm_device *drm, } } EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent); + +/** + * drm_fb_dma_get_scanout_buffer - Provide a scanout buffer in case of panic + * @plane: DRM primary plane + * @sb: scanout buffer for the panic handler + * Returns: 0 or negative error code + * + * Generic get_scanout_buffer() implementation, for drivers that uses the + * drm_fb_dma_helper. It won't call vmap in the panic context, so the driver + * should make sure the primary plane is vmapped, otherwise the panic screen + * won't get displayed. + */ +int drm_fb_dma_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb) +{ + struct drm_gem_dma_object *dma_obj; + struct drm_framebuffer *fb; + + fb = plane->state->fb; + /* Only support linear modifier */ + if (fb->modifier != DRM_FORMAT_MOD_LINEAR) + return -ENODEV; + + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + + /* Buffer should be accessible from the CPU */ + if (dma_obj->base.import_attach) + return -ENODEV; + + /* Buffer should be already mapped to CPU */ + if (!dma_obj->vaddr) + return -ENODEV; + + iosys_map_set_vaddr(&sb->map[0], dma_obj->vaddr); + sb->format = fb->format; + sb->height = fb->height; + sb->width = fb->width; + sb->pitch[0] = fb->pitches[0]; + return 0; +} +EXPORT_SYMBOL(drm_fb_dma_get_scanout_buffer); diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index e440f458b663..93337543aac3 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -224,8 +224,8 @@ __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane, __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base); - drm_format_conv_state_copy(&shadow_plane_state->fmtcnv_state, - &new_shadow_plane_state->fmtcnv_state); + drm_format_conv_state_copy(&new_shadow_plane_state->fmtcnv_state, + &shadow_plane_state->fmtcnv_state); } EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state); diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 2215baef9a3e..690505a1f7a5 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -35,7 +35,6 @@ #define DRM_IF_VERSION(maj, min) (maj << 16 | min) -struct cea_sad; struct dentry; struct dma_buf; struct iosys_map; @@ -278,8 +277,4 @@ void drm_framebuffer_print_info(struct drm_printer *p, unsigned int indent, const struct drm_framebuffer *fb); void drm_framebuffer_debugfs_init(struct drm_device *dev); -/* drm_edid.c */ -void drm_edid_cta_sad_get(const struct cea_sad *cta_sad, u8 *sad); -void drm_edid_cta_sad_set(struct cea_sad *cta_sad, const u8 *sad); - #endif /* __DRM_INTERNAL_H__ */ diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index ef6e416522f8..795001bb7ff1 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -644,6 +644,43 @@ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, } EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); +/** + * mipi_dsi_compression_mode_ext() - enable/disable DSC on the peripheral + * @dsi: DSI peripheral device + * @enable: Whether to enable or disable the DSC + * @algo: Selected compression algorithm + * @pps_selector: Select PPS from the table of pre-stored or uploaded PPS entries + * + * Enable or disable Display Stream Compression on the peripheral. + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_compression_mode_ext(struct mipi_dsi_device *dsi, bool enable, + enum mipi_dsi_compression_algo algo, + unsigned int pps_selector) +{ + u8 tx[2] = { }; + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_COMPRESSION_MODE, + .tx_len = sizeof(tx), + .tx_buf = tx, + }; + int ret; + + if (algo > 3 || pps_selector > 3) + return -EINVAL; + + tx[0] = (enable << 0) | + (algo << 1) | + (pps_selector << 4); + + ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} +EXPORT_SYMBOL(mipi_dsi_compression_mode_ext); + /** * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral * @dsi: DSI peripheral device @@ -654,19 +691,9 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size); * * Return: 0 on success or a negative error code on failure. */ -ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) +int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable) { - /* Note: Needs updating for non-default PPS or algorithm */ - u8 tx[2] = { enable << 0, 0 }; - struct mipi_dsi_msg msg = { - .channel = dsi->channel, - .type = MIPI_DSI_COMPRESSION_MODE, - .tx_len = sizeof(tx), - .tx_buf = tx, - }; - int ret = mipi_dsi_device_transfer(dsi, &msg); - - return (ret < 0) ? ret : 0; + return mipi_dsi_compression_mode_ext(dsi, enable, MIPI_DSI_COMPRESSION_DSC, 0); } EXPORT_SYMBOL(mipi_dsi_compression_mode); @@ -679,8 +706,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode); * * Return: 0 on success or a negative error code on failure. */ -ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, - const struct drm_dsc_picture_parameter_set *pps) +int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi, + const struct drm_dsc_picture_parameter_set *pps) { struct mipi_dsi_msg msg = { .channel = dsi->channel, diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 48fd2d67f352..568972258222 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -372,6 +372,13 @@ static int drm_mode_create_standard_properties(struct drm_device *dev) return -ENOMEM; dev->mode_config.modifiers_property = prop; + prop = drm_property_create(dev, + DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB, + "SIZE_HINTS", 0); + if (!prop) + return -ENOMEM; + dev->mode_config.size_hints_property = prop; + return 0; } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index c4f88c3a93b7..2d8b0371619d 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -373,8 +373,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hact_duration_ns < params->hact_ns.min || hact_duration_ns > params->hact_ns.max)) { - DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n", - hact_duration_ns, params->hact_ns.min, params->hact_ns.max); + drm_err(dev, "Invalid horizontal active area duration: %uns (min: %u, max %u)\n", + hact_duration_ns, params->hact_ns.min, params->hact_ns.max); return -EINVAL; } @@ -385,8 +385,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hblk_duration_ns < params->hblk_ns.min || hblk_duration_ns > params->hblk_ns.max)) { - DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n", - hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max); + drm_err(dev, "Invalid horizontal blanking duration: %uns (min: %u, max %u)\n", + hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max); return -EINVAL; } @@ -397,8 +397,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hslen_duration_ns < params->hslen_ns.min || hslen_duration_ns > params->hslen_ns.max)) { - DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n", - hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max); + drm_err(dev, "Invalid horizontal sync duration: %uns (min: %u, max %u)\n", + hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max); return -EINVAL; } @@ -409,7 +409,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) || porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) { - DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns); + drm_err(dev, "Invalid horizontal porches duration: %uns\n", + porches_duration_ns); return -EINVAL; } @@ -431,8 +432,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hfp_duration_ns < params->hfp_ns.min || hfp_duration_ns > params->hfp_ns.max)) { - DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n", - hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max); + drm_err(dev, "Invalid horizontal front porch duration: %uns (min: %u, max %u)\n", + hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max); return -EINVAL; } @@ -443,8 +444,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hbp_duration_ns < params->hbp_ns.min || hbp_duration_ns > params->hbp_ns.max)) { - DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n", - hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max); + drm_err(dev, "Invalid horizontal back porch duration: %uns (min: %u, max %u)\n", + hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max); return -EINVAL; } @@ -495,8 +496,8 @@ static int fill_analog_mode(struct drm_device *dev, vtotal = vactive + vfp + vslen + vbp; if (params->num_lines != vtotal) { - DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n", - vtotal, params->num_lines); + drm_err(dev, "Invalid vertical total: %upx (expected %upx)\n", + vtotal, params->num_lines); return -EINVAL; } @@ -1200,9 +1201,8 @@ int of_get_drm_display_mode(struct device_node *np, if (bus_flags) drm_bus_flags_from_videomode(&vm, bus_flags); - pr_debug("%pOF: got %dx%d display mode\n", - np, vm.hactive, vm.vactive); - drm_mode_debug_printmodeline(dmode); + pr_debug("%pOF: got %dx%d display mode: " DRM_MODE_FMT "\n", + np, vm.hactive, vm.vactive, DRM_MODE_ARG(dmode)); return 0; } @@ -1250,7 +1250,7 @@ int of_get_drm_panel_display_mode(struct device_node *np, dmode->width_mm = width_mm; dmode->height_mm = height_mm; - drm_mode_debug_printmodeline(dmode); + pr_debug(DRM_MODE_FMT "\n", DRM_MODE_ARG(dmode)); return 0; } @@ -1812,10 +1812,8 @@ void drm_mode_prune_invalid(struct drm_device *dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); } if (verbose) { - drm_mode_debug_printmodeline(mode); - DRM_DEBUG_KMS("Not using %s mode: %s\n", - mode->name, - drm_get_mode_status_name(mode->status)); + drm_dbg_kms(dev, "Rejected mode: " DRM_MODE_FMT " (%s)\n", + DRM_MODE_ARG(mode), drm_get_mode_status_name(mode->status)); } drm_mode_destroy(dev, mode); } diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c new file mode 100644 index 000000000000..7ece67086cec --- /dev/null +++ b/drivers/gpu/drm/drm_panic.c @@ -0,0 +1,585 @@ +// SPDX-License-Identifier: GPL-2.0 or MIT +/* + * Copyright (c) 2023 Red Hat. + * Author: Jocelyn Falempe + * inspired by the drm_log driver from David Herrmann + * Tux Ascii art taken from cowsay written by Tony Monroe + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Jocelyn Falempe"); +MODULE_DESCRIPTION("DRM panic handler"); +MODULE_LICENSE("GPL"); + +/** + * DOC: overview + * + * To enable DRM panic for a driver, the primary plane must implement a + * &drm_plane_helper_funcs.get_scanout_buffer helper function. It is then + * automatically registered to the drm panic handler. + * When a panic occurs, the &drm_plane_helper_funcs.get_scanout_buffer will be + * called, and the driver can provide a framebuffer so the panic handler can + * draw the panic screen on it. Currently only linear buffer and a few color + * formats are supported. + * Optionally the driver can also provide a &drm_plane_helper_funcs.panic_flush + * callback, that will be called after that, to send additional commands to the + * hardware to make the scanout buffer visible. + */ + +/* + * This module displays a user friendly message on screen when a kernel panic + * occurs. This is conflicting with fbcon, so you can only enable it when fbcon + * is disabled. + * It's intended for end-user, so have minimal technical/debug information. + * + * Implementation details: + * + * It is a panic handler, so it can't take lock, allocate memory, run tasks/irq, + * or attempt to sleep. It's a best effort, and it may not be able to display + * the message in all situations (like if the panic occurs in the middle of a + * modesetting). + * It will display only one static frame, so performance optimizations are low + * priority as the machine is already in an unusable state. + */ + +struct drm_panic_line { + u32 len; + const char *txt; +}; + +#define PANIC_LINE(s) {.len = sizeof(s) - 1, .txt = s} + +static struct drm_panic_line panic_msg[] = { + PANIC_LINE("KERNEL PANIC !"), + PANIC_LINE(""), + PANIC_LINE("Please reboot your computer."), +}; + +static const struct drm_panic_line logo[] = { + PANIC_LINE(" .--. _"), + PANIC_LINE(" |o_o | | |"), + PANIC_LINE(" |:_/ | | |"), + PANIC_LINE(" // \\ \\ |_|"), + PANIC_LINE(" (| | ) _"), + PANIC_LINE(" /'\\_ _/`\\ (_)"), + PANIC_LINE(" \\___)=(___/"), +}; + +/* + * Color conversion + */ + +static u16 convert_xrgb8888_to_rgb565(u32 pix) +{ + return ((pix & 0x00F80000) >> 8) | + ((pix & 0x0000FC00) >> 5) | + ((pix & 0x000000F8) >> 3); +} + +static u16 convert_xrgb8888_to_rgba5551(u32 pix) +{ + return ((pix & 0x00f80000) >> 8) | + ((pix & 0x0000f800) >> 5) | + ((pix & 0x000000f8) >> 2) | + BIT(0); /* set alpha bit */ +} + +static u16 convert_xrgb8888_to_xrgb1555(u32 pix) +{ + return ((pix & 0x00f80000) >> 9) | + ((pix & 0x0000f800) >> 6) | + ((pix & 0x000000f8) >> 3); +} + +static u16 convert_xrgb8888_to_argb1555(u32 pix) +{ + return BIT(15) | /* set alpha bit */ + ((pix & 0x00f80000) >> 9) | + ((pix & 0x0000f800) >> 6) | + ((pix & 0x000000f8) >> 3); +} + +static u32 convert_xrgb8888_to_argb8888(u32 pix) +{ + return pix | GENMASK(31, 24); /* fill alpha bits */ +} + +static u32 convert_xrgb8888_to_xbgr8888(u32 pix) +{ + return ((pix & 0x00ff0000) >> 16) << 0 | + ((pix & 0x0000ff00) >> 8) << 8 | + ((pix & 0x000000ff) >> 0) << 16 | + ((pix & 0xff000000) >> 24) << 24; +} + +static u32 convert_xrgb8888_to_abgr8888(u32 pix) +{ + return ((pix & 0x00ff0000) >> 16) << 0 | + ((pix & 0x0000ff00) >> 8) << 8 | + ((pix & 0x000000ff) >> 0) << 16 | + GENMASK(31, 24); /* fill alpha bits */ +} + +static u32 convert_xrgb8888_to_xrgb2101010(u32 pix) +{ + pix = ((pix & 0x000000FF) << 2) | + ((pix & 0x0000FF00) << 4) | + ((pix & 0x00FF0000) << 6); + return pix | ((pix >> 8) & 0x00300C03); +} + +static u32 convert_xrgb8888_to_argb2101010(u32 pix) +{ + pix = ((pix & 0x000000FF) << 2) | + ((pix & 0x0000FF00) << 4) | + ((pix & 0x00FF0000) << 6); + return GENMASK(31, 30) /* set alpha bits */ | pix | ((pix >> 8) & 0x00300C03); +} + +/* + * convert_from_xrgb8888 - convert one pixel from xrgb8888 to the desired format + * @color: input color, in xrgb8888 format + * @format: output format + * + * Returns: + * Color in the format specified, casted to u32. + * Or 0 if the format is not supported. + */ +static u32 convert_from_xrgb8888(u32 color, u32 format) +{ + switch (format) { + case DRM_FORMAT_RGB565: + return convert_xrgb8888_to_rgb565(color); + case DRM_FORMAT_RGBA5551: + return convert_xrgb8888_to_rgba5551(color); + case DRM_FORMAT_XRGB1555: + return convert_xrgb8888_to_xrgb1555(color); + case DRM_FORMAT_ARGB1555: + return convert_xrgb8888_to_argb1555(color); + case DRM_FORMAT_RGB888: + case DRM_FORMAT_XRGB8888: + return color; + case DRM_FORMAT_ARGB8888: + return convert_xrgb8888_to_argb8888(color); + case DRM_FORMAT_XBGR8888: + return convert_xrgb8888_to_xbgr8888(color); + case DRM_FORMAT_ABGR8888: + return convert_xrgb8888_to_abgr8888(color); + case DRM_FORMAT_XRGB2101010: + return convert_xrgb8888_to_xrgb2101010(color); + case DRM_FORMAT_ARGB2101010: + return convert_xrgb8888_to_argb2101010(color); + default: + WARN_ONCE(1, "Can't convert to %p4cc\n", &format); + return 0; + } +} + +/* + * Blit & Fill + */ +static void drm_panic_blit16(struct iosys_map *dmap, unsigned int dpitch, + const u8 *sbuf8, unsigned int spitch, + unsigned int height, unsigned int width, + u16 fg16, u16 bg16) +{ + unsigned int y, x; + u16 val16; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + val16 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg16 : bg16; + iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, val16); + } + } +} + +static void drm_panic_blit24(struct iosys_map *dmap, unsigned int dpitch, + const u8 *sbuf8, unsigned int spitch, + unsigned int height, unsigned int width, + u32 fg32, u32 bg32) +{ + unsigned int y, x; + u32 val32; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + u32 off = y * dpitch + x * 3; + + val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32; + + /* write blue-green-red to output in little endianness */ + iosys_map_wr(dmap, off, u8, (val32 & 0x000000FF) >> 0); + iosys_map_wr(dmap, off + 1, u8, (val32 & 0x0000FF00) >> 8); + iosys_map_wr(dmap, off + 2, u8, (val32 & 0x00FF0000) >> 16); + } + } +} + +static void drm_panic_blit32(struct iosys_map *dmap, unsigned int dpitch, + const u8 *sbuf8, unsigned int spitch, + unsigned int height, unsigned int width, + u32 fg32, u32 bg32) +{ + unsigned int y, x; + u32 val32; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + val32 = (sbuf8[(y * spitch) + x / 8] & (0x80 >> (x % 8))) ? fg32 : bg32; + iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, val32); + } + } +} + +/* + * drm_panic_blit - convert a monochrome image to a linear framebuffer + * @dmap: destination iosys_map + * @dpitch: destination pitch in bytes + * @sbuf8: source buffer, in monochrome format, 8 pixels per byte. + * @spitch: source pitch in bytes + * @height: height of the image to copy, in pixels + * @width: width of the image to copy, in pixels + * @fg_color: foreground color, in destination format + * @bg_color: background color, in destination format + * @pixel_width: pixel width in bytes. + * + * This can be used to draw a font character, which is a monochrome image, to a + * framebuffer in other supported format. + */ +static void drm_panic_blit(struct iosys_map *dmap, unsigned int dpitch, + const u8 *sbuf8, unsigned int spitch, + unsigned int height, unsigned int width, + u32 fg_color, u32 bg_color, + unsigned int pixel_width) +{ + switch (pixel_width) { + case 2: + drm_panic_blit16(dmap, dpitch, sbuf8, spitch, + height, width, fg_color, bg_color); + break; + case 3: + drm_panic_blit24(dmap, dpitch, sbuf8, spitch, + height, width, fg_color, bg_color); + break; + case 4: + drm_panic_blit32(dmap, dpitch, sbuf8, spitch, + height, width, fg_color, bg_color); + break; + default: + WARN_ONCE(1, "Can't blit with pixel width %d\n", pixel_width); + } +} + +static void drm_panic_fill16(struct iosys_map *dmap, unsigned int dpitch, + unsigned int height, unsigned int width, + u16 color) +{ + unsigned int y, x; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + iosys_map_wr(dmap, y * dpitch + x * sizeof(u16), u16, color); +} + +static void drm_panic_fill24(struct iosys_map *dmap, unsigned int dpitch, + unsigned int height, unsigned int width, + u32 color) +{ + unsigned int y, x; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + unsigned int off = y * dpitch + x * 3; + + /* write blue-green-red to output in little endianness */ + iosys_map_wr(dmap, off, u8, (color & 0x000000FF) >> 0); + iosys_map_wr(dmap, off + 1, u8, (color & 0x0000FF00) >> 8); + iosys_map_wr(dmap, off + 2, u8, (color & 0x00FF0000) >> 16); + } + } +} + +static void drm_panic_fill32(struct iosys_map *dmap, unsigned int dpitch, + unsigned int height, unsigned int width, + u32 color) +{ + unsigned int y, x; + + for (y = 0; y < height; y++) + for (x = 0; x < width; x++) + iosys_map_wr(dmap, y * dpitch + x * sizeof(u32), u32, color); +} + +/* + * drm_panic_fill - Fill a rectangle with a color + * @dmap: destination iosys_map, pointing to the top left corner of the rectangle + * @dpitch: destination pitch in bytes + * @height: height of the rectangle, in pixels + * @width: width of the rectangle, in pixels + * @color: color to fill the rectangle. + * @pixel_width: pixel width in bytes + * + * Fill a rectangle with a color, in a linear framebuffer. + */ +static void drm_panic_fill(struct iosys_map *dmap, unsigned int dpitch, + unsigned int height, unsigned int width, + u32 color, unsigned int pixel_width) +{ + switch (pixel_width) { + case 2: + drm_panic_fill16(dmap, dpitch, height, width, color); + break; + case 3: + drm_panic_fill24(dmap, dpitch, height, width, color); + break; + case 4: + drm_panic_fill32(dmap, dpitch, height, width, color); + break; + default: + WARN_ONCE(1, "Can't fill with pixel width %d\n", pixel_width); + } +} + +static const u8 *get_char_bitmap(const struct font_desc *font, char c, size_t font_pitch) +{ + return font->data + (c * font->height) * font_pitch; +} + +static unsigned int get_max_line_len(const struct drm_panic_line *lines, int len) +{ + int i; + unsigned int max = 0; + + for (i = 0; i < len; i++) + max = max(lines[i].len, max); + return max; +} + +/* + * Draw a text in a rectangle on a framebuffer. The text is truncated if it overflows the rectangle + */ +static void draw_txt_rectangle(struct drm_scanout_buffer *sb, + const struct font_desc *font, + const struct drm_panic_line *msg, + unsigned int msg_lines, + bool centered, + struct drm_rect *clip, + u32 fg_color, + u32 bg_color) +{ + int i, j; + const u8 *src; + size_t font_pitch = DIV_ROUND_UP(font->width, 8); + struct iosys_map dst; + unsigned int px_width = sb->format->cpp[0]; + int left = 0; + + msg_lines = min(msg_lines, drm_rect_height(clip) / font->height); + for (i = 0; i < msg_lines; i++) { + size_t line_len = min(msg[i].len, drm_rect_width(clip) / font->width); + + if (centered) + left = (drm_rect_width(clip) - (line_len * font->width)) / 2; + + dst = sb->map[0]; + iosys_map_incr(&dst, (clip->y1 + i * font->height) * sb->pitch[0] + + (clip->x1 + left) * px_width); + for (j = 0; j < line_len; j++) { + src = get_char_bitmap(font, msg[i].txt[j], font_pitch); + drm_panic_blit(&dst, sb->pitch[0], src, font_pitch, + font->height, font->width, + fg_color, bg_color, px_width); + iosys_map_incr(&dst, font->width * px_width); + } + } +} + +/* + * Draw the panic message at the center of the screen + */ +static void draw_panic_static(struct drm_scanout_buffer *sb) +{ + size_t msg_lines = ARRAY_SIZE(panic_msg); + size_t logo_lines = ARRAY_SIZE(logo); + u32 fg_color = CONFIG_DRM_PANIC_FOREGROUND_COLOR; + u32 bg_color = CONFIG_DRM_PANIC_BACKGROUND_COLOR; + const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); + struct drm_rect r_logo, r_msg; + + if (!font) + return; + + fg_color = convert_from_xrgb8888(fg_color, sb->format->format); + bg_color = convert_from_xrgb8888(bg_color, sb->format->format); + + r_logo = DRM_RECT_INIT(0, 0, + get_max_line_len(logo, logo_lines) * font->width, + logo_lines * font->height); + r_msg = DRM_RECT_INIT(0, 0, + min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width), + min(msg_lines * font->height, sb->height)); + + /* Center the panic message */ + drm_rect_translate(&r_msg, (sb->width - r_msg.x2) / 2, (sb->height - r_msg.y2) / 2); + + /* Fill with the background color, and draw text on top */ + drm_panic_fill(&sb->map[0], sb->pitch[0], sb->height, sb->width, + bg_color, sb->format->cpp[0]); + + if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && + drm_rect_width(&r_logo) < sb->width && drm_rect_height(&r_logo) < sb->height) { + draw_txt_rectangle(sb, font, logo, logo_lines, false, &r_logo, fg_color, bg_color); + } + draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color, bg_color); +} + +/* + * drm_panic_is_format_supported() + * @format: a fourcc color code + * Returns: true if supported, false otherwise. + * + * Check if drm_panic will be able to use this color format. + */ +static bool drm_panic_is_format_supported(const struct drm_format_info *format) +{ + if (format->num_planes != 1) + return false; + return convert_from_xrgb8888(0xffffff, format->format) != 0; +} + +static void draw_panic_plane(struct drm_plane *plane) +{ + struct drm_scanout_buffer sb; + int ret; + unsigned long flags; + + if (!drm_panic_trylock(plane->dev, flags)) + return; + + ret = plane->helper_private->get_scanout_buffer(plane, &sb); + + if (!ret && drm_panic_is_format_supported(sb.format)) { + draw_panic_static(&sb); + if (plane->helper_private->panic_flush) + plane->helper_private->panic_flush(plane); + } + drm_panic_unlock(plane->dev, flags); +} + +static struct drm_plane *to_drm_plane(struct kmsg_dumper *kd) +{ + return container_of(kd, struct drm_plane, kmsg_panic); +} + +static void drm_panic(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason) +{ + struct drm_plane *plane = to_drm_plane(dumper); + + if (reason == KMSG_DUMP_PANIC) + draw_panic_plane(plane); +} + + +/* + * DEBUG FS, This is currently unsafe. + * Create one file per plane, so it's possible to debug one plane at a time. + * TODO: It would be better to emulate an NMI context. + */ +#ifdef CONFIG_DRM_PANIC_DEBUG +#include + +static ssize_t debugfs_trigger_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + bool run; + + if (kstrtobool_from_user(user_buf, count, &run) == 0 && run) { + struct drm_plane *plane = file->private_data; + + draw_panic_plane(plane); + } + return count; +} + +static const struct file_operations dbg_drm_panic_ops = { + .owner = THIS_MODULE, + .write = debugfs_trigger_write, + .open = simple_open, +}; + +static void debugfs_register_plane(struct drm_plane *plane, int index) +{ + char fname[32]; + + snprintf(fname, 32, "drm_panic_plane_%d", index); + debugfs_create_file(fname, 0200, plane->dev->debugfs_root, + plane, &dbg_drm_panic_ops); +} +#else +static void debugfs_register_plane(struct drm_plane *plane, int index) {} +#endif /* CONFIG_DRM_PANIC_DEBUG */ + +/** + * drm_panic_register() - Initialize DRM panic for a device + * @dev: the drm device on which the panic screen will be displayed. + */ +void drm_panic_register(struct drm_device *dev) +{ + struct drm_plane *plane; + int registered_plane = 0; + + if (!dev->mode_config.num_total_plane) + return; + + drm_for_each_plane(plane, dev) { + if (!plane->helper_private || !plane->helper_private->get_scanout_buffer) + continue; + plane->kmsg_panic.dump = drm_panic; + plane->kmsg_panic.max_reason = KMSG_DUMP_PANIC; + if (kmsg_dump_register(&plane->kmsg_panic)) + drm_warn(dev, "Failed to register panic handler\n"); + else { + debugfs_register_plane(plane, registered_plane); + registered_plane++; + } + } + if (registered_plane) + drm_info(dev, "Registered %d planes with drm panic\n", registered_plane); +} +EXPORT_SYMBOL(drm_panic_register); + +/** + * drm_panic_unregister() + * @dev: the drm device previously registered. + */ +void drm_panic_unregister(struct drm_device *dev) +{ + struct drm_plane *plane; + + if (!dev->mode_config.num_total_plane) + return; + + drm_for_each_plane(plane, dev) { + if (!plane->helper_private || !plane->helper_private->get_scanout_buffer) + continue; + kmsg_dump_unregister(&plane->kmsg_panic); + } +} +EXPORT_SYMBOL(drm_panic_unregister); diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 672c655c7a8e..57662a1fd345 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -140,6 +140,25 @@ * DRM_FORMAT_MOD_LINEAR. Before linux kernel release v5.1 there have been * various bugs in this area with inconsistencies between the capability * flag and per-plane properties. + * + * SIZE_HINTS: + * Blob property which contains the set of recommended plane size + * which can used for simple "cursor like" use cases (eg. no scaling). + * Using these hints frees userspace from extensive probing of + * supported plane sizes through atomic/setcursor ioctls. + * + * The blob contains an array of struct drm_plane_size_hint, in + * order of preference. For optimal usage userspace should pick + * the first size that satisfies its own requirements. + * + * Drivers should only attach this property to planes that + * support a very limited set of sizes. + * + * Note that property value 0 (ie. no blob) is reserved for potential + * future use. Current userspace is expected to ignore the property + * if the value is 0, and fall back to some other means (eg. + * &DRM_CAP_CURSOR_WIDTH and &DRM_CAP_CURSOR_HEIGHT) to determine + * the appropriate plane size to use. */ static unsigned int drm_num_planes(struct drm_device *dev) @@ -1729,3 +1748,40 @@ int drm_plane_create_scaling_filter_property(struct drm_plane *plane, return 0; } EXPORT_SYMBOL(drm_plane_create_scaling_filter_property); + +/** + * drm_plane_add_size_hints_property - create a size hints property + * + * @plane: drm plane + * @hints: size hints + * @num_hints: number of size hints + * + * Create a size hints property for the plane. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_plane_add_size_hints_property(struct drm_plane *plane, + const struct drm_plane_size_hint *hints, + int num_hints) +{ + struct drm_device *dev = plane->dev; + struct drm_mode_config *config = &dev->mode_config; + struct drm_property_blob *blob; + + /* extending to other plane types needs actual thought */ + if (drm_WARN_ON(dev, plane->type != DRM_PLANE_TYPE_CURSOR)) + return -EINVAL; + + blob = drm_property_create_blob(dev, + array_size(sizeof(hints[0]), num_hints), + hints); + if (IS_ERR(blob)) + return PTR_ERR(blob); + + drm_object_attach_property(&plane->base, config->size_hints_property, + blob->base.id); + + return 0; +} +EXPORT_SYMBOL(drm_plane_add_size_hints_property); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 7352bde299d5..03bd3c7bd0dc 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -582,7 +582,12 @@ int drm_gem_map_attach(struct dma_buf *dma_buf, { struct drm_gem_object *obj = dma_buf->priv; - if (!obj->funcs->get_sg_table) + /* + * drm_gem_map_dma_buf() requires obj->get_sg_table(), but drivers + * that implement their own ->map_dma_buf() do not. + */ + if (dma_buf->ops->map_dma_buf == drm_gem_map_dma_buf && + !obj->funcs->get_sg_table) return -ENOSYS; return drm_gem_pin(obj); diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 699b7dbffd7b..cf2efb44722c 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -23,13 +23,13 @@ * Rob Clark */ -#include - +#include +#include #include #include #include #include -#include +#include #include #include diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 968a3ee66b1e..4f75a1cfd820 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -567,8 +567,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_modeset_acquire_init(&ctx, 0); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s]\n", connector->base.id, + connector->name); retry: ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); @@ -611,11 +611,10 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, * check here, and if anything changed start the hotplug code. */ if (old_status != connector->status) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", - connector->base.id, - connector->name, - drm_get_connector_status_name(old_status), - drm_get_connector_status_name(connector->status)); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, connector->name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status)); /* * The hotplug event code might call into the fb @@ -638,8 +637,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_kms_helper_poll_enable(dev); if (connector->status == connector_status_disconnected) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", - connector->base.id, connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] disconnected\n", + connector->base.id, connector->name); drm_connector_update_edid_property(connector, NULL); drm_mode_prune_invalid(dev, &connector->modes, false); goto exit; @@ -697,11 +696,13 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, drm_mode_sort(&connector->modes); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] probed modes:\n", + connector->base.id, connector->name); + list_for_each_entry(mode, &connector->modes, head) { drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(mode); + drm_dbg_kms(dev, "Probed mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(mode)); } return count; @@ -834,14 +835,12 @@ static void output_poll_execute(struct work_struct *work) old = drm_get_connector_status_name(old_status); new = drm_get_connector_status_name(connector->status); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " - "status updated from %s to %s\n", - connector->base.id, - connector->name, - old, new); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] epoch counter %llu -> %llu\n", - connector->base.id, connector->name, - old_epoch_counter, connector->epoch_counter); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, connector->name, + old, new); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] epoch counter %llu -> %llu\n", + connector->base.id, connector->name, + old_epoch_counter, connector->epoch_counter); changed = true; } diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index a953f69a34b6..bd9b8ab4f82b 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -209,10 +209,9 @@ static ssize_t status_store(struct device *device, ret = -EINVAL; if (old_force != connector->force || !connector->force) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n", - connector->base.id, - connector->name, - old_force, connector->force); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n", + connector->base.id, connector->name, + old_force, connector->force); connector->funcs->fill_modes(connector, dev->mode_config.max_width, @@ -383,8 +382,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector) if (r) goto err_free; - DRM_DEBUG("adding \"%s\" to sysfs\n", - connector->name); + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] adding connector to sysfs\n", + connector->base.id, connector->name); r = device_add(kdev); if (r) { @@ -430,8 +429,9 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) if (dev_fwnode(connector->kdev)) component_del(connector->kdev, &typec_connector_ops); - DRM_DEBUG("removing \"%s\" from sysfs\n", - connector->name); + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s] removing connector from sysfs\n", + connector->base.id, connector->name); device_unregister(connector->kdev); connector->kdev = NULL; @@ -442,7 +442,7 @@ void drm_sysfs_lease_event(struct drm_device *dev) char *event_string = "LEASE=1"; char *envp[] = { event_string, NULL }; - DRM_DEBUG("generating lease event\n"); + drm_dbg_lease(dev, "generating lease event\n"); kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); } @@ -463,7 +463,7 @@ void drm_sysfs_hotplug_event(struct drm_device *dev) char *event_string = "HOTPLUG=1"; char *envp[] = { event_string, NULL }; - DRM_DEBUG("generating hotplug event\n"); + drm_dbg_kms(dev, "generating hotplug event\n"); kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); } diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 702a12bc93bd..cc3571e25a9a 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -166,11 +166,24 @@ module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600) MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); +static struct drm_vblank_crtc * +drm_vblank_crtc(struct drm_device *dev, unsigned int pipe) +{ + return &dev->vblank[pipe]; +} + +struct drm_vblank_crtc * +drm_crtc_vblank_crtc(struct drm_crtc *crtc) +{ + return drm_vblank_crtc(crtc->dev, drm_crtc_index(crtc)); +} +EXPORT_SYMBOL(drm_crtc_vblank_crtc); + static void store_vblank(struct drm_device *dev, unsigned int pipe, u32 vblank_count_inc, ktime_t t_vblank, u32 last) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); assert_spin_locked(&dev->vblank_time_lock); @@ -184,7 +197,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); return vblank->max_vblank_count ?: dev->max_vblank_count; } @@ -273,7 +286,7 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, bool in_vblank_irq) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); u32 cur_vblank, diff; bool rc; ktime_t t_vblank; @@ -364,7 +377,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); u64 count; if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) @@ -438,7 +451,7 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe) */ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); unsigned long irqflags; assert_spin_locked(&dev->vbl_lock); @@ -600,7 +613,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); int linedur_ns = 0, framedur_ns = 0; int dotclock = mode->crtc_clock; @@ -930,7 +943,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_count); static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, ktime_t *vblanktime) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); u64 vblank_count; unsigned int seq; @@ -985,7 +998,6 @@ EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); */ int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime) { - unsigned int pipe = drm_crtc_index(crtc); struct drm_vblank_crtc *vblank; struct drm_display_mode *mode; u64 vblank_start; @@ -993,7 +1005,7 @@ int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime) if (!drm_dev_has_vblank(crtc->dev)) return -EINVAL; - vblank = &crtc->dev->vblank[pipe]; + vblank = drm_crtc_vblank_crtc(crtc); mode = &vblank->hwmode; if (!vblank->framedur_ns || !vblank->linedur_ns) @@ -1147,7 +1159,7 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe) static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); int ret = 0; assert_spin_locked(&dev->vbl_lock); @@ -1185,7 +1197,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) int drm_vblank_get(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); unsigned long irqflags; int ret = 0; @@ -1228,7 +1240,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_get); void drm_vblank_put(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) return; @@ -1274,7 +1286,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); */ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); int ret; u64 last; @@ -1327,7 +1339,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct drm_pending_vblank_event *e, *t; ktime_t now; u64 seq; @@ -1405,8 +1417,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); void drm_crtc_vblank_reset(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); spin_lock_irq(&dev->vbl_lock); /* @@ -1445,8 +1456,7 @@ void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc, u32 max_vblank_count) { struct drm_device *dev = crtc->dev; - unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); drm_WARN_ON(dev, dev->max_vblank_count); drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset)); @@ -1469,7 +1479,7 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = drm_crtc_index(crtc); - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) return; @@ -1512,7 +1522,7 @@ static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe) assert_spin_locked(&dev->vbl_lock); assert_spin_locked(&dev->vblank_time_lock); - vblank = &dev->vblank[pipe]; + vblank = drm_vblank_crtc(dev, pipe); drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns, "Cannot compute missed vblanks without frame duration\n"); @@ -1564,7 +1574,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, union drm_wait_vblank *vblwait, struct drm_file *file_priv) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); struct drm_pending_vblank_event *e; ktime_t now; u64 seq; @@ -1872,7 +1882,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) */ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) { - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe); unsigned long irqflags; bool disable_irq; @@ -1981,7 +1991,7 @@ int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data, pipe = drm_crtc_index(crtc); - vblank = &dev->vblank[pipe]; + vblank = drm_crtc_vblank_crtc(crtc); vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled); if (!vblank_enabled) { @@ -2046,7 +2056,7 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data, pipe = drm_crtc_index(crtc); - vblank = &dev->vblank[pipe]; + vblank = drm_crtc_vblank_crtc(crtc); e = kzalloc(sizeof(*e), GFP_KERNEL); if (e == NULL) diff --git a/drivers/gpu/drm/drm_vblank_work.c b/drivers/gpu/drm/drm_vblank_work.c index 43cd5c0f4f6f..4fe9b1d3b00f 100644 --- a/drivers/gpu/drm/drm_vblank_work.c +++ b/drivers/gpu/drm/drm_vblank_work.c @@ -245,7 +245,7 @@ void drm_vblank_work_init(struct drm_vblank_work *work, struct drm_crtc *crtc, { kthread_init_work(&work->base, func); INIT_LIST_HEAD(&work->node); - work->vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; + work->vblank = drm_crtc_vblank_crtc(crtc); } EXPORT_SYMBOL(drm_vblank_work_init); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 734412aae94d..a9bf426f69b3 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -164,26 +164,6 @@ int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value) *value = gpu->identity.eco_id; break; - case ETNAVIV_PARAM_GPU_NN_CORE_COUNT: - *value = gpu->identity.nn_core_count; - break; - - case ETNAVIV_PARAM_GPU_NN_MAD_PER_CORE: - *value = gpu->identity.nn_mad_per_core; - break; - - case ETNAVIV_PARAM_GPU_TP_CORE_COUNT: - *value = gpu->identity.tp_core_count; - break; - - case ETNAVIV_PARAM_GPU_ON_CHIP_SRAM_SIZE: - *value = gpu->identity.on_chip_sram_size; - break; - - case ETNAVIV_PARAM_GPU_AXI_SRAM_SIZE: - *value = gpu->identity.axi_sram_size; - break; - default: DBG("%s: invalid param: %u", dev_name(gpu->dev), param); return -EINVAL; @@ -663,8 +643,8 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu) /* Disable TX clock gating on affected core revisions. */ if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) || etnaviv_is_model_rev(gpu, GC2000, 0x5108) || - etnaviv_is_model_rev(gpu, GC2000, 0x6202) || - etnaviv_is_model_rev(gpu, GC2000, 0x6203)) + etnaviv_is_model_rev(gpu, GC7000, 0x6202) || + etnaviv_is_model_rev(gpu, GC7000, 0x6203)) pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX; /* Disable SE and RA clock gating on affected core revisions. */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 7d5e9158e13c..197e0037732e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -54,18 +54,6 @@ struct etnaviv_chip_identity { /* Number of Neural Network cores. */ u32 nn_core_count; - /* Number of MAD units per Neural Network core. */ - u32 nn_mad_per_core; - - /* Number of Tensor Processing cores. */ - u32 tp_core_count; - - /* Size in bytes of the SRAM inside the NPU. */ - u32 on_chip_sram_size; - - /* Size in bytes of the SRAM across the AXI bus. */ - u32 axi_sram_size; - /* Size of the vertex cache. */ u32 vertex_cache_size; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index d8e7334de8ce..8665f2658d51 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -17,10 +17,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 128, .shader_core_count = 1, .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 8, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -52,11 +48,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 256, .shader_core_count = 1, - .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 8, .vertex_output_buffer_size = 512, .pixel_pipes = 1, @@ -89,10 +80,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 512, .shader_core_count = 2, .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -125,10 +112,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 512, .shader_core_count = 2, .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -160,11 +143,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .register_max = 64, .thread_count = 512, .shader_core_count = 2, - .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -197,10 +175,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 1024, .shader_core_count = 4, .nn_core_count = 0, - .nn_mad_per_core = 0, - .tp_core_count = 0, - .on_chip_sram_size = 0, - .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 2, @@ -233,10 +207,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 256, .shader_core_count = 1, .nn_core_count = 8, - .nn_mad_per_core = 64, - .tp_core_count = 4, - .on_chip_sram_size = 524288, - .axi_sram_size = 1048576, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, @@ -269,10 +239,6 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { .thread_count = 256, .shader_core_count = 1, .nn_core_count = 6, - .nn_mad_per_core = 64, - .tp_core_count = 3, - .on_chip_sram_size = 262144, - .axi_sram_size = 0, .vertex_cache_size = 16, .vertex_output_buffer_size = 1024, .pixel_pipes = 1, diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 2fe0e5f3f638..bf16deaae68b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -184,7 +184,6 @@ struct platform_driver dsi_driver = { .remove_new = samsung_dsim_remove, .driver = { .name = "exynos-dsi", - .owner = THIS_MODULE, .pm = &samsung_dsim_pm_ops, .of_match_table = exynos_dsi_of_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c index e81a576de398..142184c8c3bc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c @@ -1412,7 +1412,6 @@ struct platform_driver fimc_driver = { .driver = { .of_match_table = fimc_of_match, .name = "exynos-drm-fimc", - .owner = THIS_MODULE, .pm = pm_ptr(&fimc_pm_ops), }, }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index f2145227a1e0..f57df8c48139 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -1326,7 +1326,6 @@ struct platform_driver fimd_driver = { .remove_new = fimd_remove, .driver = { .name = "exynos4-fb", - .owner = THIS_MODULE, .pm = pm_ptr(&exynos_fimd_pm_ops), .of_match_table = fimd_driver_dt_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index f3138423612e..3a3b2c00e400 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1610,7 +1610,6 @@ struct platform_driver g2d_driver = { .remove_new = g2d_remove, .driver = { .name = "exynos-drm-g2d", - .owner = THIS_MODULE, .pm = pm_ptr(&g2d_pm_ops), .of_match_table = exynos_g2d_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 180507a47700..1b111e2c3347 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -1423,7 +1423,6 @@ struct platform_driver gsc_driver = { .remove_new = gsc_remove, .driver = { .name = "exynos-drm-gsc", - .owner = THIS_MODULE, .pm = &gsc_pm_ops, .of_match_table = exynos_drm_gsc_of_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index e2920960180f..d61ec451807c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -464,7 +464,6 @@ struct platform_driver mic_driver = { .driver = { .name = "exynos-mic", .pm = pm_ptr(&exynos_mic_pm_ops), - .owner = THIS_MODULE, .of_match_table = exynos_mic_of_match, }, }; diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index 5f7516655b08..2eb0b701672f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c @@ -454,7 +454,6 @@ struct platform_driver rotator_driver = { .remove_new = rotator_remove, .driver = { .name = "exynos-rotator", - .owner = THIS_MODULE, .pm = pm_ptr(&rotator_pm_ops), .of_match_table = exynos_rotator_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c index 392f721f13ab..a9d469896824 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c +++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c @@ -722,7 +722,6 @@ struct platform_driver scaler_driver = { .remove_new = scaler_remove, .driver = { .name = "exynos-scaler", - .owner = THIS_MODULE, .pm = pm_ptr(&scaler_pm_ops), .of_match_table = exynos_scaler_match, }, diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index f5bbba9ad225..fab135308b70 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -479,7 +479,6 @@ struct platform_driver vidi_driver = { .remove_new = vidi_remove, .driver = { .name = "exynos-drm-vidi", - .owner = THIS_MODULE, .dev_groups = vidi_groups, }, }; diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index b1d02dec3774..e968824a4c72 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -1919,10 +1919,9 @@ static int hdmi_get_ddc_adapter(struct hdmi_context *hdata) static int hdmi_get_phy_io(struct hdmi_context *hdata) { const char *compatible_str = "samsung,exynos4212-hdmiphy"; - struct device_node *np; - int ret = 0; + struct device_node *np __free(device_node) = + of_find_compatible_node(NULL, NULL, compatible_str); - np = of_find_compatible_node(NULL, NULL, compatible_str); if (!np) { np = of_parse_phandle(hdata->dev->of_node, "phy", 0); if (!np) { @@ -1937,21 +1936,17 @@ static int hdmi_get_phy_io(struct hdmi_context *hdata) if (!hdata->regs_hdmiphy) { DRM_DEV_ERROR(hdata->dev, "failed to ioremap hdmi phy\n"); - ret = -ENOMEM; - goto out; + return -ENOMEM; } } else { hdata->hdmiphy_port = of_find_i2c_device_by_node(np); if (!hdata->hdmiphy_port) { DRM_INFO("Failed to get hdmi phy i2c client\n"); - ret = -EPROBE_DEFER; - goto out; + return -EPROBE_DEFER; } } -out: - of_node_put(np); - return ret; + return 0; } static int hdmi_probe(struct platform_device *pdev) @@ -2126,7 +2121,6 @@ struct platform_driver hdmi_driver = { .remove_new = hdmi_remove, .driver = { .name = "exynos-hdmi", - .owner = THIS_MODULE, .pm = &exynos_hdmi_pm_ops, .of_match_table = hdmi_match_types, }, diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 6822333fd0e6..1db955f00044 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1331,7 +1331,6 @@ static const struct dev_pm_ops exynos_mixer_pm_ops = { struct platform_driver mixer_driver = { .driver = { .name = "exynos-mixer", - .owner = THIS_MODULE, .pm = &exynos_mixer_pm_ops, .of_match_table = mixer_match_types, }, diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile index 4f302cd5e1a6..58fed80c7392 100644 --- a/drivers/gpu/drm/gma500/Makefile +++ b/drivers/gpu/drm/gma500/Makefile @@ -34,7 +34,6 @@ gma500_gfx-y += \ psb_intel_lvds.o \ psb_intel_modes.o \ psb_intel_sdvo.o \ - psb_lid.o \ psb_irq.o gma500_gfx-$(CONFIG_ACPI) += opregion.o diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index dcfcd7b89d4a..6dece8f0e380 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -73,8 +73,7 @@ static int psb_backlight_setup(struct drm_device *dev) } psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS); - /* This must occur after the backlight is properly initialised */ - psb_lid_timer_init(dev_priv); + return 0; } @@ -259,8 +258,6 @@ static int psb_chip_setup(struct drm_device *dev) static void psb_chip_teardown(struct drm_device *dev) { - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - psb_lid_timer_takedown(dev_priv); gma_intel_teardown_gmbus(dev); } diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index c5edfa4aa4cc..83c17689c454 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -162,7 +162,6 @@ #define PSB_NUM_VBLANKS 2 #define PSB_WATCHDOG_DELAY (HZ * 2) -#define PSB_LID_DELAY (HZ / 10) #define PSB_MAX_BRIGHTNESS 100 @@ -491,11 +490,7 @@ struct drm_psb_private { /* Hotplug handling */ struct work_struct hotplug_work; - /* LID-Switch */ - spinlock_t lid_lock; - struct timer_list lid_timer; struct psb_intel_opregion opregion; - u32 lid_last_state; /* Watchdog */ uint32_t apm_reg; @@ -591,10 +586,6 @@ struct psb_ops { int i2c_bus; /* I2C bus identifier for Moorestown */ }; -/* psb_lid.c */ -extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); -extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); - /* modesetting */ extern void psb_modeset_init(struct drm_device *dev); extern void psb_modeset_cleanup(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c deleted file mode 100644 index 58a7fe392636..000000000000 --- a/drivers/gpu/drm/gma500/psb_lid.c +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/************************************************************************** - * Copyright (c) 2007, Intel Corporation. - * - * Authors: Thomas Hellstrom - **************************************************************************/ - -#include - -#include "psb_drv.h" -#include "psb_intel_reg.h" -#include "psb_reg.h" - -static void psb_lid_timer_func(struct timer_list *t) -{ - struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer); - struct drm_device *dev = (struct drm_device *)&dev_priv->dev; - struct timer_list *lid_timer = &dev_priv->lid_timer; - unsigned long irq_flags; - u32 __iomem *lid_state = dev_priv->opregion.lid_state; - u32 pp_status; - - if (readl(lid_state) == dev_priv->lid_last_state) - goto lid_timer_schedule; - - if ((readl(lid_state)) & 0x01) { - /*lid state is open*/ - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0 && - (pp_status & PP_SEQUENCE_MASK) != 0); - - if (REG_READ(PP_STATUS) & PP_ON) { - /*FIXME: should be backlight level before*/ - psb_intel_lvds_set_brightness(dev, 100); - } else { - DRM_DEBUG("LVDS panel never powered up"); - return; - } - } else { - psb_intel_lvds_set_brightness(dev, 0); - - REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); - do { - pp_status = REG_READ(PP_STATUS); - } while ((pp_status & PP_ON) == 0); - } - dev_priv->lid_last_state = readl(lid_state); - -lid_timer_schedule: - spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); - if (!timer_pending(lid_timer)) { - lid_timer->expires = jiffies + PSB_LID_DELAY; - add_timer(lid_timer); - } - spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_init(struct drm_psb_private *dev_priv) -{ - struct timer_list *lid_timer = &dev_priv->lid_timer; - unsigned long irq_flags; - - spin_lock_init(&dev_priv->lid_lock); - spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); - - timer_setup(lid_timer, psb_lid_timer_func, 0); - - lid_timer->expires = jiffies + PSB_LID_DELAY; - - add_timer(lid_timer); - spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); -} - -void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) -{ - del_timer_sync(&dev_priv->lid_timer); -} - diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c index 034e78360d4f..0f07d77c5d52 100644 --- a/drivers/gpu/drm/gud/gud_connector.c +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -221,7 +221,7 @@ static int gud_connector_get_modes(struct drm_connector *connector) struct gud_display_mode_req *reqmodes = NULL; struct gud_connector_get_edid_ctx edid_ctx; unsigned int i, num_modes = 0; - struct edid *edid = NULL; + const struct drm_edid *drm_edid = NULL; int idx, ret; if (!drm_dev_enter(connector->dev, &idx)) @@ -238,13 +238,13 @@ static int gud_connector_get_modes(struct drm_connector *connector) gud_conn_err(connector, "Invalid EDID size", ret); } else if (ret > 0) { edid_ctx.len = ret; - edid = drm_do_get_edid(connector, gud_connector_get_edid_block, &edid_ctx); + drm_edid = drm_edid_read_custom(connector, gud_connector_get_edid_block, &edid_ctx); } kfree(edid_ctx.buf); - drm_connector_update_edid_property(connector, edid); + drm_edid_connector_update(connector, drm_edid); - if (edid && edid_ctx.edid_override) + if (drm_edid && edid_ctx.edid_override) goto out; reqmodes = kmalloc_array(GUD_CONNECTOR_MAX_NUM_MODES, sizeof(*reqmodes), GFP_KERNEL); @@ -276,10 +276,10 @@ static int gud_connector_get_modes(struct drm_connector *connector) } out: if (!num_modes) - num_modes = drm_add_edid_modes(connector, edid); + num_modes = drm_edid_connector_add_modes(connector); kfree(reqmodes); - kfree(edid); + drm_edid_free(drm_edid); drm_dev_exit(idx); return num_modes; diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 4c2f85632391..7cad944b825c 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -32,11 +32,6 @@ endif # Enable -Werror in CI and development subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror -# Fine grained warnings disable -CFLAGS_i915_pci.o = -Wno-override-init -CFLAGS_display/intel_display_device.o = -Wno-override-init -CFLAGS_display/intel_fbdev.o = -Wno-override-init - # Support compiling the display code separately for both i915 and xe # drivers. Define I915 when building i915. subdir-ccflags-y += -DI915 @@ -118,6 +113,7 @@ gt-y += \ gt/intel_ggtt_fencing.o \ gt/intel_gt.o \ gt/intel_gt_buffer_pool.o \ + gt/intel_gt_ccs_mode.o \ gt/intel_gt_clock_utils.o \ gt/intel_gt_debugfs.o \ gt/intel_gt_engines_debugfs.o \ @@ -270,6 +266,7 @@ i915-y += \ display/intel_display_rps.o \ display/intel_display_wa.o \ display/intel_dmc.o \ + display/intel_dmc_wl.o \ display/intel_dpio_phy.o \ display/intel_dpll.o \ display/intel_dpll_mgr.o \ diff --git a/drivers/gpu/drm/i915/display/bxt_dpio_phy_regs.h b/drivers/gpu/drm/i915/display/bxt_dpio_phy_regs.h new file mode 100644 index 000000000000..275f4d9c3fb0 --- /dev/null +++ b/drivers/gpu/drm/i915/display/bxt_dpio_phy_regs.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __BXT_DPIO_PHY_REGS_H__ +#define __BXT_DPIO_PHY_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* BXT PHY registers */ +#define _BXT_PHY0_BASE 0x6C000 +#define _BXT_PHY1_BASE 0x162000 +#define _BXT_PHY2_BASE 0x163000 +#define BXT_PHY_BASE(phy) \ + _PICK_EVEN_2RANGES(phy, 1, \ + _BXT_PHY0_BASE, _BXT_PHY0_BASE, \ + _BXT_PHY1_BASE, _BXT_PHY2_BASE) + +#define _BXT_PHY(phy, reg) \ + _MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg)) + +#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ + (BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE, \ + (reg_ch1) - _BXT_PHY0_BASE)) +#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ + _MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1)) +#define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ + ((lane) & 1) * 0x80) +#define _MMIO_BXT_PHY_CH_LN(phy, ch, lane, reg_ch0, reg_ch1) \ + _MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) + _BXT_LANE_OFFSET(lane)) + +/* BXT PHY PLL registers */ +#define _PORT_PLL_A 0x46074 +#define _PORT_PLL_B 0x46078 +#define _PORT_PLL_C 0x4607c +#define PORT_PLL_ENABLE REG_BIT(31) +#define PORT_PLL_LOCK REG_BIT(30) +#define PORT_PLL_REF_SEL REG_BIT(27) +#define PORT_PLL_POWER_ENABLE REG_BIT(26) +#define PORT_PLL_POWER_STATE REG_BIT(25) +#define BXT_PORT_PLL_ENABLE(port) _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B) + +#define _PORT_PLL_EBB_0_A 0x162034 +#define _PORT_PLL_EBB_0_B 0x6C034 +#define _PORT_PLL_EBB_0_C 0x6C340 +#define PORT_PLL_P1_MASK REG_GENMASK(15, 13) +#define PORT_PLL_P1(p1) REG_FIELD_PREP(PORT_PLL_P1_MASK, (p1)) +#define PORT_PLL_P2_MASK REG_GENMASK(12, 8) +#define PORT_PLL_P2(p2) REG_FIELD_PREP(PORT_PLL_P2_MASK, (p2)) +#define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PLL_EBB_0_B, \ + _PORT_PLL_EBB_0_C) + +#define _PORT_PLL_EBB_4_A 0x162038 +#define _PORT_PLL_EBB_4_B 0x6C038 +#define _PORT_PLL_EBB_4_C 0x6C344 +#define PORT_PLL_RECALIBRATE REG_BIT(14) +#define PORT_PLL_10BIT_CLK_ENABLE REG_BIT(13) +#define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PLL_EBB_4_B, \ + _PORT_PLL_EBB_4_C) + +#define _PORT_PLL_0_A 0x162100 +#define _PORT_PLL_0_B 0x6C100 +#define _PORT_PLL_0_C 0x6C380 +/* PORT_PLL_0_A */ +#define PORT_PLL_M2_INT_MASK REG_GENMASK(7, 0) +#define PORT_PLL_M2_INT(m2_int) REG_FIELD_PREP(PORT_PLL_M2_INT_MASK, (m2_int)) +/* PORT_PLL_1_A */ +#define PORT_PLL_N_MASK REG_GENMASK(11, 8) +#define PORT_PLL_N(n) REG_FIELD_PREP(PORT_PLL_N_MASK, (n)) +/* PORT_PLL_2_A */ +#define PORT_PLL_M2_FRAC_MASK REG_GENMASK(21, 0) +#define PORT_PLL_M2_FRAC(m2_frac) REG_FIELD_PREP(PORT_PLL_M2_FRAC_MASK, (m2_frac)) +/* PORT_PLL_3_A */ +#define PORT_PLL_M2_FRAC_ENABLE REG_BIT(16) +/* PORT_PLL_6_A */ +#define PORT_PLL_GAIN_CTL_MASK REG_GENMASK(18, 16) +#define PORT_PLL_GAIN_CTL(x) REG_FIELD_PREP(PORT_PLL_GAIN_CTL_MASK, (x)) +#define PORT_PLL_INT_COEFF_MASK REG_GENMASK(12, 8) +#define PORT_PLL_INT_COEFF(x) REG_FIELD_PREP(PORT_PLL_INT_COEFF_MASK, (x)) +#define PORT_PLL_PROP_COEFF_MASK REG_GENMASK(3, 0) +#define PORT_PLL_PROP_COEFF(x) REG_FIELD_PREP(PORT_PLL_PROP_COEFF_MASK, (x)) +/* PORT_PLL_8_A */ +#define PORT_PLL_TARGET_CNT_MASK REG_GENMASK(9, 0) +#define PORT_PLL_TARGET_CNT(x) REG_FIELD_PREP(PORT_PLL_TARGET_CNT_MASK, (x)) +/* PORT_PLL_9_A */ +#define PORT_PLL_LOCK_THRESHOLD_MASK REG_GENMASK(3, 1) +#define PORT_PLL_LOCK_THRESHOLD(x) REG_FIELD_PREP(PORT_PLL_LOCK_THRESHOLD_MASK, (x)) +/* PORT_PLL_10_A */ +#define PORT_PLL_DCO_AMP_OVR_EN_H REG_BIT(27) +#define PORT_PLL_DCO_AMP_MASK REG_GENMASK(13, 10) +#define PORT_PLL_DCO_AMP(x) REG_FIELD_PREP(PORT_PLL_DCO_AMP_MASK, (x)) +#define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \ + _PORT_PLL_0_B, \ + _PORT_PLL_0_C) +#define BXT_PORT_PLL(phy, ch, idx) _MMIO(_PORT_PLL_BASE(phy, ch) + \ + (idx) * 4) + +/* BXT PHY common lane registers */ +#define _PORT_CL1CM_DW0_A 0x162000 +#define _PORT_CL1CM_DW0_BC 0x6C000 +#define PHY_POWER_GOOD REG_BIT(16) +#define PHY_RESERVED REG_BIT(7) +#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC) + +#define _PORT_CL1CM_DW9_A 0x162024 +#define _PORT_CL1CM_DW9_BC 0x6C024 +#define IREF0RC_OFFSET_MASK REG_GENMASK(15, 8) +#define IREF0RC_OFFSET(x) REG_FIELD_PREP(IREF0RC_OFFSET_MASK, (x)) +#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC) + +#define _PORT_CL1CM_DW10_A 0x162028 +#define _PORT_CL1CM_DW10_BC 0x6C028 +#define IREF1RC_OFFSET_MASK REG_GENMASK(15, 8) +#define IREF1RC_OFFSET(x) REG_FIELD_PREP(IREF1RC_OFFSET_MASK, (x)) +#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC) + +#define _PORT_CL1CM_DW28_A 0x162070 +#define _PORT_CL1CM_DW28_BC 0x6C070 +#define OCL1_POWER_DOWN_EN REG_BIT(23) +#define DW28_OLDO_DYN_PWR_DOWN_EN REG_BIT(22) +#define SUS_CLK_CONFIG REG_GENMASK(1, 0) +#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC) + +#define _PORT_CL1CM_DW30_A 0x162078 +#define _PORT_CL1CM_DW30_BC 0x6C078 +#define OCL2_LDOFUSE_PWR_DIS REG_BIT(6) +#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC) + +/* The spec defines this only for BXT PHY0, but lets assume that this + * would exist for PHY1 too if it had a second channel. + */ +#define _PORT_CL2CM_DW6_A 0x162358 +#define _PORT_CL2CM_DW6_BC 0x6C358 +#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC) +#define DW6_OLDO_DYN_PWR_DOWN_EN REG_BIT(28) + +/* BXT PHY Ref registers */ +#define _PORT_REF_DW3_A 0x16218C +#define _PORT_REF_DW3_BC 0x6C18C +#define GRC_DONE REG_BIT(22) +#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC) + +#define _PORT_REF_DW6_A 0x162198 +#define _PORT_REF_DW6_BC 0x6C198 +#define GRC_CODE_MASK REG_GENMASK(31, 24) +#define GRC_CODE(x) REG_FIELD_PREP(GRC_CODE_MASK, (x)) +#define GRC_CODE_FAST_MASK REG_GENMASK(23, 16) +#define GRC_CODE_FAST(x) REG_FIELD_PREP(GRC_CODE_FAST_MASK, (x)) +#define GRC_CODE_SLOW_MASK REG_GENMASK(15, 8) +#define GRC_CODE_SLOW(x) REG_FIELD_PREP(GRC_CODE_SLOW_MASK, (x)) +#define GRC_CODE_NOM_MASK REG_GENMASK(7, 0) +#define GRC_CODE_NOM(x) REG_FIELD_PREP(GRC_CODE_NOM_MASK, (x)) +#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC) + +#define _PORT_REF_DW8_A 0x1621A0 +#define _PORT_REF_DW8_BC 0x6C1A0 +#define GRC_DIS REG_BIT(15) +#define GRC_RDY_OVRD REG_BIT(1) +#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC) + +/* BXT PHY PCS registers */ +#define _PORT_PCS_DW10_LN01_A 0x162428 +#define _PORT_PCS_DW10_LN01_B 0x6C428 +#define _PORT_PCS_DW10_LN01_C 0x6C828 +#define _PORT_PCS_DW10_GRP_A 0x162C28 +#define _PORT_PCS_DW10_GRP_B 0x6CC28 +#define _PORT_PCS_DW10_GRP_C 0x6CE28 +#define BXT_PORT_PCS_DW10_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW10_LN01_B, \ + _PORT_PCS_DW10_LN01_C) +#define BXT_PORT_PCS_DW10_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW10_GRP_B, \ + _PORT_PCS_DW10_GRP_C) + +#define TX2_SWING_CALC_INIT REG_BIT(31) +#define TX1_SWING_CALC_INIT REG_BIT(30) + +#define _PORT_PCS_DW12_LN01_A 0x162430 +#define _PORT_PCS_DW12_LN01_B 0x6C430 +#define _PORT_PCS_DW12_LN01_C 0x6C830 +#define _PORT_PCS_DW12_LN23_A 0x162630 +#define _PORT_PCS_DW12_LN23_B 0x6C630 +#define _PORT_PCS_DW12_LN23_C 0x6CA30 +#define _PORT_PCS_DW12_GRP_A 0x162c30 +#define _PORT_PCS_DW12_GRP_B 0x6CC30 +#define _PORT_PCS_DW12_GRP_C 0x6CE30 +#define LANESTAGGER_STRAP_OVRD REG_BIT(6) +#define LANE_STAGGER_MASK REG_GENMASK(4, 0) +#define BXT_PORT_PCS_DW12_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_LN01_B, \ + _PORT_PCS_DW12_LN01_C) +#define BXT_PORT_PCS_DW12_LN23(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_LN23_B, \ + _PORT_PCS_DW12_LN23_C) +#define BXT_PORT_PCS_DW12_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_PCS_DW12_GRP_B, \ + _PORT_PCS_DW12_GRP_C) + +/* BXT PHY TX registers */ +#define _PORT_TX_DW2_LN0_A 0x162508 +#define _PORT_TX_DW2_LN0_B 0x6C508 +#define _PORT_TX_DW2_LN0_C 0x6C908 +#define _PORT_TX_DW2_GRP_A 0x162D08 +#define _PORT_TX_DW2_GRP_B 0x6CD08 +#define _PORT_TX_DW2_GRP_C 0x6CF08 +#define BXT_PORT_TX_DW2_LN(phy, ch, lane) _MMIO_BXT_PHY_CH_LN(phy, ch, lane, \ + _PORT_TX_DW2_LN0_B, \ + _PORT_TX_DW2_LN0_C) +#define BXT_PORT_TX_DW2_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW2_GRP_B, \ + _PORT_TX_DW2_GRP_C) +#define MARGIN_000_MASK REG_GENMASK(23, 16) +#define MARGIN_000(x) REG_FIELD_PREP(MARGIN_000_MASK, (x)) +#define UNIQ_TRANS_SCALE_MASK REG_GENMASK(15, 8) +#define UNIQ_TRANS_SCALE(x) REG_FIELD_PREP(UNIQ_TRANS_SCALE_MASK, (x)) + +#define _PORT_TX_DW3_LN0_A 0x16250C +#define _PORT_TX_DW3_LN0_B 0x6C50C +#define _PORT_TX_DW3_LN0_C 0x6C90C +#define _PORT_TX_DW3_GRP_A 0x162D0C +#define _PORT_TX_DW3_GRP_B 0x6CD0C +#define _PORT_TX_DW3_GRP_C 0x6CF0C +#define BXT_PORT_TX_DW3_LN(phy, ch, lane) _MMIO_BXT_PHY_CH_LN(phy, ch, lane, \ + _PORT_TX_DW3_LN0_B, \ + _PORT_TX_DW3_LN0_C) +#define BXT_PORT_TX_DW3_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW3_GRP_B, \ + _PORT_TX_DW3_GRP_C) +#define SCALE_DCOMP_METHOD REG_BIT(26) +#define UNIQUE_TRANGE_EN_METHOD REG_BIT(27) + +#define _PORT_TX_DW4_LN0_A 0x162510 +#define _PORT_TX_DW4_LN0_B 0x6C510 +#define _PORT_TX_DW4_LN0_C 0x6C910 +#define _PORT_TX_DW4_GRP_A 0x162D10 +#define _PORT_TX_DW4_GRP_B 0x6CD10 +#define _PORT_TX_DW4_GRP_C 0x6CF10 +#define BXT_PORT_TX_DW4_LN(phy, ch, lane) _MMIO_BXT_PHY_CH_LN(phy, ch, lane, \ + _PORT_TX_DW4_LN0_B, \ + _PORT_TX_DW4_LN0_C) +#define BXT_PORT_TX_DW4_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW4_GRP_B, \ + _PORT_TX_DW4_GRP_C) +#define DE_EMPHASIS_MASK REG_GENMASK(31, 24) +#define DE_EMPHASIS(x) REG_FIELD_PREP(DE_EMPHASIS_MASK, (x)) + +#define _PORT_TX_DW5_LN0_A 0x162514 +#define _PORT_TX_DW5_LN0_B 0x6C514 +#define _PORT_TX_DW5_LN0_C 0x6C914 +#define _PORT_TX_DW5_GRP_A 0x162D14 +#define _PORT_TX_DW5_GRP_B 0x6CD14 +#define _PORT_TX_DW5_GRP_C 0x6CF14 +#define BXT_PORT_TX_DW5_LN(phy, ch, lane) _MMIO_BXT_PHY_CH_LN(phy, ch, lane, \ + _PORT_TX_DW5_LN0_B, \ + _PORT_TX_DW5_LN0_C) +#define BXT_PORT_TX_DW5_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ + _PORT_TX_DW5_GRP_B, \ + _PORT_TX_DW5_GRP_C) +#define DCC_DELAY_RANGE_1 REG_BIT(9) +#define DCC_DELAY_RANGE_2 REG_BIT(8) + +#define _PORT_TX_DW14_LN0_A 0x162538 +#define _PORT_TX_DW14_LN0_B 0x6C538 +#define _PORT_TX_DW14_LN0_C 0x6C938 +#define LATENCY_OPTIM REG_BIT(30) +#define BXT_PORT_TX_DW14_LN(phy, ch, lane) _MMIO_BXT_PHY_CH_LN(phy, ch, lane, \ + _PORT_TX_DW14_LN0_B, \ + _PORT_TX_DW14_LN0_C) + +#endif /* __BXT_DPIO_PHY_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index ac456a2275db..79ecfc339430 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1616,8 +1616,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, - base); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct intel_connector *intel_connector = intel_dsi->attached_connector; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 2bb270f82932..7a77ae3dc394 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -62,7 +62,7 @@ int intel_digital_connector_atomic_get_property(struct drm_connector *connector, { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_digital_connector_state *intel_conn_state = + const struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(state); if (property == dev_priv->display.properties.force_audio) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 1946d7fb3c2e..071668bfe5d1 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -83,16 +83,16 @@ static u32 scale_hw_to_user(struct intel_connector *connector, u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 val) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_WARN_ON(&i915->drm, panel->backlight.pwm_level_max == 0); + drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0); - if (i915->display.params.invert_brightness < 0) + if (display->params.invert_brightness < 0) return val; - if (i915->display.params.invert_brightness > 0 || - intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS)) { + if (display->params.invert_brightness > 0 || + intel_has_quirk(display, QUIRK_INVERT_BRIGHTNESS)) { return panel->backlight.pwm_level_max - val + panel->backlight.pwm_level_min; } @@ -126,15 +126,15 @@ u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val) u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; - drm_WARN_ON_ONCE(&i915->drm, + drm_WARN_ON_ONCE(display->drm, panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0); - if (i915->display.params.invert_brightness > 0 || - (i915->display.params.invert_brightness == 0 && - intel_has_quirk(i915, QUIRK_INVERT_BRIGHTNESS))) + if (display->params.invert_brightness > 0 || + (display->params.invert_brightness == 0 && + intel_has_quirk(display, QUIRK_INVERT_BRIGHTNESS))) val = panel->backlight.pwm_level_max - (val - panel->backlight.pwm_level_min); return scale(val, panel->backlight.pwm_level_min, panel->backlight.pwm_level_max, @@ -761,8 +761,8 @@ static void __intel_backlight_enable(const struct intel_crtc_state *crtc_state, WARN_ON(panel->backlight.max == 0); - if (panel->backlight.level <= panel->backlight.min) { - panel->backlight.level = panel->backlight.max; + if (panel->backlight.level < panel->backlight.min) { + panel->backlight.level = panel->backlight.min; if (panel->backlight.device) panel->backlight.device->props.brightness = scale_hw_to_user(connector, @@ -949,7 +949,7 @@ int intel_backlight_device_register(struct intel_connector *connector) else props.power = FB_BLANK_POWERDOWN; - name = kstrdup("intel_backlight", GFP_KERNEL); + name = kstrdup_const("intel_backlight", GFP_KERNEL); if (!name) return -ENOMEM; @@ -963,7 +963,7 @@ int intel_backlight_device_register(struct intel_connector *connector) * compatibility. Use unique names for subsequent backlight devices as a * fallback when the default name already exists. */ - kfree(name); + kfree_const(name); name = kasprintf(GFP_KERNEL, "card%d-%s-backlight", i915->drm.primary->index, connector->base.name); if (!name) @@ -987,7 +987,7 @@ int intel_backlight_device_register(struct intel_connector *connector) connector->base.base.id, connector->base.name, name); out: - kfree(name); + kfree_const(name); return ret; } @@ -1642,17 +1642,17 @@ void intel_backlight_update(struct intel_atomic_state *state, int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_display *display = to_intel_display(connector); struct intel_panel *panel = &connector->panel; int ret; if (!connector->panel.vbt.backlight.present) { - if (intel_has_quirk(i915, QUIRK_BACKLIGHT_PRESENT)) { - drm_dbg_kms(&i915->drm, + if (intel_has_quirk(display, QUIRK_BACKLIGHT_PRESENT)) { + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] no backlight present per VBT, but present per quirk\n", connector->base.base.id, connector->base.name); } else { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] no backlight present per VBT\n", connector->base.base.id, connector->base.name); return 0; @@ -1660,16 +1660,16 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) } /* ensure intel_panel has been initialized first */ - if (drm_WARN_ON(&i915->drm, !panel->backlight.funcs)) + if (drm_WARN_ON(display->drm, !panel->backlight.funcs)) return -ENODEV; /* set level and max in panel struct */ - mutex_lock(&i915->display.backlight.lock); + mutex_lock(&display->backlight.lock); ret = panel->backlight.funcs->setup(connector, pipe); - mutex_unlock(&i915->display.backlight.lock); + mutex_unlock(&display->backlight.lock); if (ret) { - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] failed to setup backlight\n", connector->base.base.id, connector->base.name); return ret; @@ -1677,7 +1677,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) panel->backlight.present = true; - drm_dbg_kms(&i915->drm, + drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] backlight initialized, %s, brightness %u/%u\n", connector->base.base.id, connector->base.name, str_enabled_disabled(panel->backlight.enabled), @@ -1821,7 +1821,7 @@ void intel_backlight_init_funcs(struct intel_panel *panel) if (intel_dp_aux_init_backlight_funcs(connector) == 0) return; - if (!intel_has_quirk(i915, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) + if (!intel_has_quirk(&i915->display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) connector->panel.backlight.power = intel_pps_backlight_power; } diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 52bd3576835b..661842a3c2e6 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -25,6 +25,8 @@ * */ +#include + #include #include #include @@ -593,11 +595,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data, return (const void *)data + ptrs->ptr[index].fp_timing.offset; } -static const struct lvds_pnp_id * +static const struct drm_edid_product_id * get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data, const struct bdb_lvds_lfp_data_ptrs *ptrs, int index) { + /* These two are supposed to have the same layout in memory. */ + BUILD_BUG_ON(sizeof(struct lvds_pnp_id) != sizeof(struct drm_edid_product_id)); + return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset; } @@ -611,19 +616,6 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data, return NULL; } -static void dump_pnp_id(struct drm_i915_private *i915, - const struct lvds_pnp_id *pnp_id, - const char *name) -{ - u16 mfg_name = be16_to_cpu((__force __be16)pnp_id->mfg_name); - char vend[4]; - - drm_dbg_kms(&i915->drm, "%s PNPID mfg: %s (0x%x), prod: %u, serial: %u, week: %d, year: %d\n", - name, drm_edid_decode_mfg_id(mfg_name, vend), - pnp_id->mfg_name, pnp_id->product_code, pnp_id->serial, - pnp_id->mfg_week, pnp_id->mfg_year + 1990); -} - static int opregion_get_panel_type(struct drm_i915_private *i915, const struct intel_bios_encoder_data *devdata, const struct drm_edid *drm_edid, bool use_fallback) @@ -662,21 +654,21 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, { const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_ptrs *ptrs; - const struct lvds_pnp_id *edid_id; - struct lvds_pnp_id edid_id_nodate; - const struct edid *edid = drm_edid_raw(drm_edid); /* FIXME */ + struct drm_edid_product_id product_id, product_id_nodate; + struct drm_printer p; int i, best = -1; - if (!edid) + if (!drm_edid) return -1; - edid_id = (const void *)&edid->mfg_id[0]; + drm_edid_get_product_id(drm_edid, &product_id); - edid_id_nodate = *edid_id; - edid_id_nodate.mfg_week = 0; - edid_id_nodate.mfg_year = 0; + product_id_nodate = product_id; + product_id_nodate.week_of_manufacture = 0; + product_id_nodate.year_of_manufacture = 0; - dump_pnp_id(i915, edid_id, "EDID"); + p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, "EDID"); + drm_edid_print_product_id(&p, &product_id, true); ptrs = bdb_find_section(i915, BDB_LVDS_LFP_DATA_PTRS); if (!ptrs) @@ -687,11 +679,11 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, return -1; for (i = 0; i < 16; i++) { - const struct lvds_pnp_id *vbt_id = + const struct drm_edid_product_id *vbt_id = get_lvds_pnp_id(data, ptrs, i); /* full match? */ - if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id))) + if (!memcmp(vbt_id, &product_id, sizeof(*vbt_id))) return i; /* @@ -699,7 +691,7 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915, * and the VBT entry does not specify a date. */ if (best < 0 && - !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id))) + !memcmp(vbt_id, &product_id_nodate, sizeof(*vbt_id))) best = i; } @@ -885,7 +877,8 @@ parse_lfp_data(struct drm_i915_private *i915, const struct bdb_lvds_lfp_data *data; const struct bdb_lvds_lfp_data_tail *tail; const struct bdb_lvds_lfp_data_ptrs *ptrs; - const struct lvds_pnp_id *pnp_id; + const struct drm_edid_product_id *pnp_id; + struct drm_printer p; int panel_type = panel->vbt.panel_type; ptrs = bdb_find_section(i915, BDB_LVDS_LFP_DATA_PTRS); @@ -900,7 +893,9 @@ parse_lfp_data(struct drm_i915_private *i915, parse_lfp_panel_dtd(i915, panel, data, ptrs); pnp_id = get_lvds_pnp_id(data, ptrs, panel_type); - dump_pnp_id(i915, pnp_id, "Panel"); + + p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, "Panel"); + drm_edid_print_product_id(&p, pnp_id, false); tail = get_lfp_data_tail(data, ptrs); if (!tail) @@ -2730,6 +2725,57 @@ static void parse_ddi_ports(struct drm_i915_private *i915) print_ddi_port(devdata); } +static int child_device_expected_size(u16 version) +{ + BUILD_BUG_ON(sizeof(struct child_device_config) < 40); + + if (version > 256) + return -ENOENT; + else if (version >= 256) + return 40; + else if (version >= 216) + return 39; + else if (version >= 196) + return 38; + else if (version >= 195) + return 37; + else if (version >= 111) + return LEGACY_CHILD_DEVICE_CONFIG_SIZE; + else if (version >= 106) + return 27; + else + return 22; +} + +static bool child_device_size_valid(struct drm_i915_private *i915, int size) +{ + int expected_size; + + expected_size = child_device_expected_size(i915->display.vbt.version); + if (expected_size < 0) { + expected_size = sizeof(struct child_device_config); + drm_dbg(&i915->drm, + "Expected child device config size for VBT version %u not known; assuming %d\n", + i915->display.vbt.version, expected_size); + } + + /* Flag an error for unexpected size, but continue anyway. */ + if (size != expected_size) + drm_err(&i915->drm, + "Unexpected child device config size %d (expected %d for VBT version %u)\n", + size, expected_size, i915->display.vbt.version); + + /* The legacy sized child device config is the minimum we need. */ + if (size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) { + drm_dbg_kms(&i915->drm, + "Child device config size %d is too small.\n", + size); + return false; + } + + return true; +} + static void parse_general_definitions(struct drm_i915_private *i915) { @@ -2737,7 +2783,6 @@ parse_general_definitions(struct drm_i915_private *i915) struct intel_bios_encoder_data *devdata; const struct child_device_config *child; int i, child_device_num; - u8 expected_size; u16 block_size; int bus_pin; @@ -2761,39 +2806,8 @@ parse_general_definitions(struct drm_i915_private *i915) if (intel_gmbus_is_valid_pin(i915, bus_pin)) i915->display.vbt.crt_ddc_pin = bus_pin; - if (i915->display.vbt.version < 106) { - expected_size = 22; - } else if (i915->display.vbt.version < 111) { - expected_size = 27; - } else if (i915->display.vbt.version < 195) { - expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE; - } else if (i915->display.vbt.version == 195) { - expected_size = 37; - } else if (i915->display.vbt.version <= 215) { - expected_size = 38; - } else if (i915->display.vbt.version <= 250) { - expected_size = 39; - } else { - expected_size = sizeof(*child); - BUILD_BUG_ON(sizeof(*child) < 39); - drm_dbg(&i915->drm, - "Expected child device config size for VBT version %u not known; assuming %u\n", - i915->display.vbt.version, expected_size); - } - - /* Flag an error for unexpected size, but continue anyway. */ - if (defs->child_dev_size != expected_size) - drm_err(&i915->drm, - "Unexpected child device config size %u (expected %u for VBT version %u)\n", - defs->child_dev_size, expected_size, i915->display.vbt.version); - - /* The legacy sized child device config is the minimum we need. */ - if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) { - drm_dbg_kms(&i915->drm, - "Child device config size %u is too small.\n", - defs->child_dev_size); + if (!child_device_size_valid(i915, defs->child_dev_size)) return; - } /* get the number of child device */ child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; @@ -2869,9 +2883,8 @@ init_vbt_panel_defaults(struct intel_panel *panel) static void init_vbt_missing_defaults(struct drm_i915_private *i915) { + unsigned int ports = DISPLAY_RUNTIME_INFO(i915)->port_mask; enum port port; - int ports = BIT(PORT_A) | BIT(PORT_B) | BIT(PORT_C) | - BIT(PORT_D) | BIT(PORT_E) | BIT(PORT_F); if (!HAS_DDI(i915) && !IS_CHERRYVIEW(i915)) return; @@ -2981,6 +2994,43 @@ bool intel_bios_is_valid_vbt(struct drm_i915_private *i915, return vbt; } +static struct vbt_header *firmware_get_vbt(struct drm_i915_private *i915, + size_t *size) +{ + struct vbt_header *vbt = NULL; + const struct firmware *fw = NULL; + const char *name = i915->display.params.vbt_firmware; + int ret; + + if (!name || !*name) + return NULL; + + ret = request_firmware(&fw, name, i915->drm.dev); + if (ret) { + drm_err(&i915->drm, + "Requesting VBT firmware \"%s\" failed (%d)\n", + name, ret); + return NULL; + } + + if (intel_bios_is_valid_vbt(i915, fw->data, fw->size)) { + vbt = kmemdup(fw->data, fw->size, GFP_KERNEL); + if (vbt) { + drm_dbg_kms(&i915->drm, + "Found valid VBT firmware \"%s\"\n", name); + if (size) + *size = fw->size; + } + } else { + drm_dbg_kms(&i915->drm, "Invalid VBT firmware \"%s\"\n", + name); + } + + release_firmware(fw); + + return vbt; +} + static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset) { intel_uncore_write(uncore, PRIMARY_SPI_ADDRESS, offset); @@ -2988,7 +3038,8 @@ static u32 intel_spi_read(struct intel_uncore *uncore, u32 offset) return intel_uncore_read(uncore, PRIMARY_SPI_TRIGGER); } -static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) +static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915, + size_t *size) { u32 count, data, found, store = 0; u32 static_region, oprom_offset; @@ -3031,6 +3082,9 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "Found valid VBT in SPI flash\n"); + if (size) + *size = vbt_size; + return (struct vbt_header *)vbt; err_free_vbt: @@ -3039,7 +3093,8 @@ static struct vbt_header *spi_oprom_get_vbt(struct drm_i915_private *i915) return NULL; } -static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) +static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915, + size_t *sizep) { struct pci_dev *pdev = to_pci_dev(i915->drm.dev); void __iomem *p = NULL, *oprom; @@ -3088,6 +3143,9 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) pci_unmap_rom(pdev, oprom); + if (sizep) + *sizep = vbt_size; + drm_dbg_kms(&i915->drm, "Found valid VBT in PCI ROM\n"); return vbt; @@ -3100,6 +3158,32 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) return NULL; } +static const struct vbt_header *intel_bios_get_vbt(struct drm_i915_private *i915, + size_t *sizep) +{ + const struct vbt_header *vbt = NULL; + intel_wakeref_t wakeref; + + vbt = firmware_get_vbt(i915, sizep); + + if (!vbt) + vbt = intel_opregion_get_vbt(i915, sizep); + + /* + * If the OpRegion does not have VBT, look in SPI flash + * through MMIO or PCI mapping + */ + if (!vbt && IS_DGFX(i915)) + with_intel_runtime_pm(&i915->runtime_pm, wakeref) + vbt = spi_oprom_get_vbt(i915, sizep); + + if (!vbt) + with_intel_runtime_pm(&i915->runtime_pm, wakeref) + vbt = oprom_get_vbt(i915, sizep); + + return vbt; +} + /** * intel_bios_init - find VBT and initialize settings from the BIOS * @i915: i915 device instance @@ -3111,7 +3195,6 @@ static struct vbt_header *oprom_get_vbt(struct drm_i915_private *i915) void intel_bios_init(struct drm_i915_private *i915) { const struct vbt_header *vbt; - struct vbt_header *oprom_vbt = NULL; const struct bdb_header *bdb; INIT_LIST_HEAD(&i915->display.vbt.display_devices); @@ -3125,21 +3208,7 @@ void intel_bios_init(struct drm_i915_private *i915) init_vbt_defaults(i915); - vbt = intel_opregion_get_vbt(i915, NULL); - - /* - * If the OpRegion does not have VBT, look in SPI flash through MMIO or - * PCI mapping - */ - if (!vbt && IS_DGFX(i915)) { - oprom_vbt = spi_oprom_get_vbt(i915); - vbt = oprom_vbt; - } - - if (!vbt) { - oprom_vbt = oprom_get_vbt(i915); - vbt = oprom_vbt; - } + vbt = intel_bios_get_vbt(i915, NULL); if (!vbt) goto out; @@ -3172,7 +3241,7 @@ void intel_bios_init(struct drm_i915_private *i915) parse_sdvo_device_mapping(i915); parse_ddi_ports(i915); - kfree(oprom_vbt); + kfree(vbt); } static void intel_bios_init_panel(struct drm_i915_private *i915, @@ -3344,8 +3413,7 @@ bool intel_bios_is_lvds_present(struct drm_i915_private *i915, u8 *i2c_pin) * additional data. Trust that if the VBT was written into * the OpRegion then they have validated the LVDS's existence. */ - if (intel_opregion_get_vbt(i915, NULL)) - return true; + return intel_opregion_vbt_present(i915); } return false; @@ -3706,13 +3774,12 @@ static int intel_bios_vbt_show(struct seq_file *m, void *unused) const void *vbt; size_t vbt_size; - /* - * FIXME: VBT might originate from other places than opregion, and then - * this would be incorrect. - */ - vbt = intel_opregion_get_vbt(i915, &vbt_size); - if (vbt) + vbt = intel_bios_get_vbt(i915, &vbt_size); + + if (vbt) { seq_write(m, vbt, vbt_size); + kfree(vbt); + } return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 7f2a50b4f494..972ea887e232 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -162,7 +162,9 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, 1); if (ret < 0) { - drm_err(&dev_priv->drm, "Failed to disable qgv points (%d) points: 0x%x\n", ret, points_mask); + drm_err(&dev_priv->drm, + "Failed to disable qgv points (0x%x) points: 0x%x\n", + ret, points_mask); return ret; } @@ -290,8 +292,10 @@ static int icl_get_qgv_points(struct drm_i915_private *dev_priv, struct intel_qgv_point *sp = &qi->points[i]; ret = intel_read_qgv_point_info(dev_priv, sp, i); - if (ret) + if (ret) { + drm_dbg_kms(&dev_priv->drm, "Could not read QGV %d info\n", i); return ret; + } drm_dbg_kms(&dev_priv->drm, "QGV %d: DCLK=%d tRP=%d tRDPRE=%d tRAS=%d tRCD=%d tRC=%d\n", @@ -659,6 +663,22 @@ static unsigned int adl_psf_bw(struct drm_i915_private *dev_priv, return bi->psf_bw[psf_gv_point]; } +static unsigned int icl_qgv_bw(struct drm_i915_private *i915, + int num_active_planes, int qgv_point) +{ + unsigned int idx; + + if (DISPLAY_VER(i915) >= 12) + idx = tgl_max_bw_index(i915, num_active_planes, qgv_point); + else + idx = icl_max_bw_index(i915, num_active_planes, qgv_point); + + if (idx >= ARRAY_SIZE(i915->display.bw.max)) + return 0; + + return i915->display.bw.max[idx].deratedbw[qgv_point]; +} + void intel_bw_init_hw(struct drm_i915_private *dev_priv) { if (!HAS_DISPLAY(dev_priv)) @@ -735,6 +755,7 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state, intel_bw_crtc_data_rate(crtc_state); bw_state->num_active_planes[crtc->pipe] = intel_bw_crtc_num_active_planes(crtc_state); + bw_state->force_check_qgv = true; drm_dbg_kms(&i915->drm, "pipe %c data rate %u num active planes %u\n", pipe_name(crtc->pipe), @@ -804,6 +825,80 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state) return to_intel_bw_state(bw_state); } +static unsigned int icl_max_bw_qgv_point_mask(struct drm_i915_private *i915, + int num_active_planes) +{ + unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points; + unsigned int max_bw_point = 0; + unsigned int max_bw = 0; + int i; + + for (i = 0; i < num_qgv_points; i++) { + unsigned int max_data_rate = + icl_qgv_bw(i915, num_active_planes, i); + + /* + * We need to know which qgv point gives us + * maximum bandwidth in order to disable SAGV + * if we find that we exceed SAGV block time + * with watermarks. By that moment we already + * have those, as it is calculated earlier in + * intel_atomic_check, + */ + if (max_data_rate > max_bw) { + max_bw_point = BIT(i); + max_bw = max_data_rate; + } + } + + return max_bw_point; +} + +static u16 icl_prepare_qgv_points_mask(struct drm_i915_private *i915, + unsigned int qgv_points, + unsigned int psf_points) +{ + return ~(ICL_PCODE_REQ_QGV_PT(qgv_points) | + ADLS_PCODE_REQ_PSF_PT(psf_points)) & icl_qgv_points_mask(i915); +} + +static unsigned int icl_max_bw_psf_gv_point_mask(struct drm_i915_private *i915) +{ + unsigned int num_psf_gv_points = i915->display.bw.max[0].num_psf_gv_points; + unsigned int max_bw_point_mask = 0; + unsigned int max_bw = 0; + int i; + + for (i = 0; i < num_psf_gv_points; i++) { + unsigned int max_data_rate = adl_psf_bw(i915, i); + + if (max_data_rate > max_bw) { + max_bw_point_mask = BIT(i); + max_bw = max_data_rate; + } else if (max_data_rate == max_bw) { + max_bw_point_mask |= BIT(i); + } + } + + return max_bw_point_mask; +} + +static void icl_force_disable_sagv(struct drm_i915_private *i915, + struct intel_bw_state *bw_state) +{ + unsigned int qgv_points = icl_max_bw_qgv_point_mask(i915, 0); + unsigned int psf_points = icl_max_bw_psf_gv_point_mask(i915); + + bw_state->qgv_points_mask = icl_prepare_qgv_points_mask(i915, + qgv_points, + psf_points); + + drm_dbg_kms(&i915->drm, "Forcing SAGV disable: mask 0x%x\n", + bw_state->qgv_points_mask); + + icl_pcode_restrict_qgv_points(i915, bw_state->qgv_points_mask); +} + static int mtl_find_qgv_points(struct drm_i915_private *i915, unsigned int data_rate, unsigned int num_active_planes, @@ -881,8 +976,6 @@ static int icl_find_qgv_points(struct drm_i915_private *i915, const struct intel_bw_state *old_bw_state, struct intel_bw_state *new_bw_state) { - unsigned int max_bw_point = 0; - unsigned int max_bw = 0; unsigned int num_psf_gv_points = i915->display.bw.max[0].num_psf_gv_points; unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points; u16 psf_points = 0; @@ -895,31 +988,8 @@ static int icl_find_qgv_points(struct drm_i915_private *i915, return ret; for (i = 0; i < num_qgv_points; i++) { - unsigned int idx; - unsigned int max_data_rate; - - if (DISPLAY_VER(i915) >= 12) - idx = tgl_max_bw_index(i915, num_active_planes, i); - else - idx = icl_max_bw_index(i915, num_active_planes, i); - - if (idx >= ARRAY_SIZE(i915->display.bw.max)) - continue; - - max_data_rate = i915->display.bw.max[idx].deratedbw[i]; - - /* - * We need to know which qgv point gives us - * maximum bandwidth in order to disable SAGV - * if we find that we exceed SAGV block time - * with watermarks. By that moment we already - * have those, as it is calculated earlier in - * intel_atomic_check, - */ - if (max_data_rate > max_bw) { - max_bw_point = i; - max_bw = max_data_rate; - } + unsigned int max_data_rate = icl_qgv_bw(i915, + num_active_planes, i); if (max_data_rate >= data_rate) qgv_points |= BIT(i); @@ -963,20 +1033,18 @@ static int icl_find_qgv_points(struct drm_i915_private *i915, * cause. */ if (!intel_can_enable_sagv(i915, new_bw_state)) { - qgv_points = BIT(max_bw_point); - drm_dbg_kms(&i915->drm, "No SAGV, using single QGV point %d\n", - max_bw_point); + qgv_points = icl_max_bw_qgv_point_mask(i915, num_active_planes); + drm_dbg_kms(&i915->drm, "No SAGV, using single QGV point mask 0x%x\n", + qgv_points); } /* * We store the ones which need to be masked as that is what PCode * actually accepts as a parameter. */ - new_bw_state->qgv_points_mask = - ~(ICL_PCODE_REQ_QGV_PT(qgv_points) | - ADLS_PCODE_REQ_PSF_PT(psf_points)) & - icl_qgv_points_mask(i915); - + new_bw_state->qgv_points_mask = icl_prepare_qgv_points_mask(i915, + qgv_points, + psf_points); /* * If the actual mask had changed we need to make sure that * the commits are serialized(in case this is a nomodeset, nonblocking) @@ -1272,8 +1340,9 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) new_bw_state = intel_atomic_get_new_bw_state(state); if (new_bw_state && - intel_can_enable_sagv(i915, old_bw_state) != - intel_can_enable_sagv(i915, new_bw_state)) + (intel_can_enable_sagv(i915, old_bw_state) != + intel_can_enable_sagv(i915, new_bw_state) || + new_bw_state->force_check_qgv)) changed = true; /* @@ -1287,6 +1356,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) if (ret) return ret; + new_bw_state->force_check_qgv = false; + return 0; } @@ -1313,7 +1384,7 @@ static const struct intel_global_state_funcs intel_bw_funcs = { .atomic_destroy_state = intel_bw_destroy_state, }; -int intel_bw_init(struct drm_i915_private *dev_priv) +int intel_bw_init(struct drm_i915_private *i915) { struct intel_bw_state *state; @@ -1321,8 +1392,15 @@ int intel_bw_init(struct drm_i915_private *dev_priv) if (!state) return -ENOMEM; - intel_atomic_global_obj_init(dev_priv, &dev_priv->display.bw.obj, + intel_atomic_global_obj_init(i915, &i915->display.bw.obj, &state->base, &intel_bw_funcs); + /* + * Limit this only if we have SAGV. And for Display version 14 onwards + * sagv is handled though pmdemand requests + */ + if (intel_has_sagv(i915) && IS_DISPLAY_VER(i915, 11, 13)) + icl_force_disable_sagv(i915, state); + return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index 59cb4fc5db76..161813cca473 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -47,12 +47,19 @@ struct intel_bw_state { */ u16 qgv_points_mask; + /* + * Flag to force the QGV comparison in atomic check right after the + * hw state readout + */ + bool force_check_qgv; + int min_cdclk[I915_MAX_PIPES]; unsigned int data_rate[I915_MAX_PIPES]; u8 num_active_planes[I915_MAX_PIPES]; }; -#define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base) +#define to_intel_bw_state(global_state) \ + container_of_const((global_state), struct intel_bw_state, base) struct intel_bw_state * intel_atomic_get_old_bw_state(struct intel_atomic_state *state); diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index ed89b86ea625..7a833b5f2de2 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -39,6 +39,8 @@ #include "intel_pcode.h" #include "intel_psr.h" #include "intel_vdsc.h" +#include "skl_watermark.h" +#include "skl_watermark_regs.h" #include "vlv_sideband.h" /** @@ -63,6 +65,32 @@ * DMC will not change the active CDCLK frequency however, so that part * will still be performed by the driver directly. * + * There are multiple components involved in the generation of the CDCLK + * frequency: + * + * - We have the CDCLK PLL, which generates an output clock based on a + * reference clock and a ratio parameter. + * - The CD2X Divider, which divides the output of the PLL based on a + * divisor selected from a set of pre-defined choices. + * - The CD2X Squasher, which further divides the output based on a + * waveform represented as a sequence of bits where each zero + * "squashes out" a clock cycle. + * - And, finally, a fixed divider that divides the output frequency by 2. + * + * As such, the resulting CDCLK frequency can be calculated with the + * following formula: + * + * cdclk = vco / cd2x_div / (sq_len / sq_div) / 2 + * + * , where vco is the frequency generated by the PLL; cd2x_div + * represents the CD2X Divider; sq_len and sq_div are the bit length + * and the number of high bits for the CD2X Squasher waveform, respectively; + * and 2 represents the fixed divider. + * + * Note that some older platforms do not contain the CD2X Divider + * and/or CD2X Squasher, in which case we can ignore their respective + * factors in the formula above. + * * Several methods exist to change the CDCLK frequency, which ones are * supported depends on the platform: * @@ -993,15 +1021,14 @@ static int skl_cdclk_decimal(int cdclk) return DIV_ROUND_CLOSEST(cdclk - 1000, 500); } -static void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, - int vco) +static void skl_set_preferred_cdclk_vco(struct drm_i915_private *i915, int vco) { - bool changed = dev_priv->skl_preferred_vco_freq != vco; + bool changed = i915->display.cdclk.skl_preferred_vco_freq != vco; - dev_priv->skl_preferred_vco_freq = vco; + i915->display.cdclk.skl_preferred_vco_freq = vco; if (changed) - intel_update_max_cdclk(dev_priv); + intel_update_max_cdclk(i915); } static u32 skl_dpll0_link_rate(struct drm_i915_private *dev_priv, int vco) @@ -1205,7 +1232,7 @@ static void skl_cdclk_init_hw(struct drm_i915_private *dev_priv) * Use the current vco as our initial * guess as to what the preferred vco is. */ - if (dev_priv->skl_preferred_vco_freq == 0) + if (dev_priv->display.cdclk.skl_preferred_vco_freq == 0) skl_set_preferred_cdclk_vco(dev_priv, dev_priv->display.cdclk.hw.vco); return; @@ -1213,7 +1240,7 @@ static void skl_cdclk_init_hw(struct drm_i915_private *dev_priv) cdclk_config = dev_priv->display.cdclk.hw; - cdclk_config.vco = dev_priv->skl_preferred_vco_freq; + cdclk_config.vco = dev_priv->display.cdclk.skl_preferred_vco_freq; if (cdclk_config.vco == 0) cdclk_config.vco = 8100000; cdclk_config.cdclk = skl_calc_cdclk(0, cdclk_config.vco); @@ -1391,7 +1418,7 @@ static const struct intel_cdclk_vals mtl_cdclk_table[] = { {} }; -static const struct intel_cdclk_vals lnl_cdclk_table[] = { +static const struct intel_cdclk_vals xe2lpd_cdclk_table[] = { { .refclk = 38400, .cdclk = 153600, .ratio = 16, .waveform = 0xaaaa }, { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a }, { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 }, @@ -1656,6 +1683,8 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv, } out: + if (DISPLAY_VER(dev_priv) >= 20) + cdclk_config->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN; /* * Can't read this out :( Let's assume it's * at least what the CDCLK frequency requires. @@ -1850,6 +1879,37 @@ static bool cdclk_pll_is_unknown(unsigned int vco) return vco == ~0; } +static bool mdclk_source_is_cdclk_pll(struct drm_i915_private *i915) +{ + return DISPLAY_VER(i915) >= 20; +} + +static u32 xe2lpd_mdclk_source_sel(struct drm_i915_private *i915) +{ + if (mdclk_source_is_cdclk_pll(i915)) + return MDCLK_SOURCE_SEL_CDCLK_PLL; + + return MDCLK_SOURCE_SEL_CD2XCLK; +} + +int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config) +{ + if (mdclk_source_is_cdclk_pll(i915)) + return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk); + + /* Otherwise, source for MDCLK is CD2XCLK. */ + return 2; +} + +static void xe2lpd_mdclk_cdclk_ratio_program(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config) +{ + intel_dbuf_mdclk_cdclk_ratio_update(i915, + intel_mdclk_cdclk_ratio(i915, cdclk_config), + cdclk_config->joined_mbus); +} + static bool cdclk_compute_crawl_and_squash_midpoint(struct drm_i915_private *i915, const struct intel_cdclk_config *old_cdclk_config, const struct intel_cdclk_config *new_cdclk_config, @@ -1954,7 +2014,7 @@ static u32 bxt_cdclk_ctl(struct drm_i915_private *i915, val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; if (DISPLAY_VER(i915) >= 20) - val |= MDCLK_SOURCE_SEL_CDCLK_PLL; + val |= xe2lpd_mdclk_source_sel(i915); else val |= skl_cdclk_decimal(cdclk); @@ -1967,7 +2027,6 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv, { int cdclk = cdclk_config->cdclk; int vco = cdclk_config->vco; - u16 waveform; if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0 && !cdclk_pll_is_unknown(dev_priv->display.cdclk.hw.vco)) { @@ -1982,10 +2041,11 @@ static void _bxt_set_cdclk(struct drm_i915_private *dev_priv, } else bxt_cdclk_pll_update(dev_priv, vco); - waveform = cdclk_squash_waveform(dev_priv, cdclk); + if (HAS_CDCLK_SQUASH(dev_priv)) { + u16 waveform = cdclk_squash_waveform(dev_priv, cdclk); - if (HAS_CDCLK_SQUASH(dev_priv)) dg2_cdclk_squash_program(dev_priv, waveform); + } intel_de_write(dev_priv, CDCLK_CTL, bxt_cdclk_ctl(dev_priv, cdclk_config, pipe)); @@ -2030,6 +2090,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, return; } + if (DISPLAY_VER(dev_priv) >= 20 && cdclk < dev_priv->display.cdclk.hw.cdclk) + xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config); + if (cdclk_compute_crawl_and_squash_midpoint(dev_priv, &dev_priv->display.cdclk.hw, cdclk_config, &mid_cdclk_config)) { _bxt_set_cdclk(dev_priv, &mid_cdclk_config, pipe); @@ -2038,6 +2101,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, _bxt_set_cdclk(dev_priv, cdclk_config, pipe); } + if (DISPLAY_VER(dev_priv) >= 20 && cdclk > dev_priv->display.cdclk.hw.cdclk) + xe2lpd_mdclk_cdclk_ratio_program(dev_priv, cdclk_config); + if (DISPLAY_VER(dev_priv) >= 14) /* * NOOP - No Pcode communication needed for @@ -2260,16 +2326,15 @@ static bool intel_cdclk_can_squash(struct drm_i915_private *dev_priv, } /** - * intel_cdclk_needs_modeset - Determine if changong between the CDCLK - * configurations requires a modeset on all pipes + * intel_cdclk_clock_changed - Check whether the clock changed * @a: first CDCLK configuration * @b: second CDCLK configuration * * Returns: - * True if changing between the two CDCLK configurations - * requires all pipes to be off, false if not. + * True if CDCLK changed in a way that requires re-programming and + * False otherwise. */ -bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a, +bool intel_cdclk_clock_changed(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b) { return a->cdclk != b->cdclk || @@ -2322,7 +2387,7 @@ static bool intel_cdclk_can_cd2x_update(struct drm_i915_private *dev_priv, static bool intel_cdclk_changed(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b) { - return intel_cdclk_needs_modeset(a, b) || + return intel_cdclk_clock_changed(a, b) || a->voltage_level != b->voltage_level; } @@ -2368,18 +2433,9 @@ static void intel_pcode_notify(struct drm_i915_private *i915, ret); } -/** - * intel_set_cdclk - Push the CDCLK configuration to the hardware - * @dev_priv: i915 device - * @cdclk_config: new CDCLK configuration - * @pipe: pipe with which to synchronize the update - * - * Program the hardware based on the passed in CDCLK state, - * if necessary. - */ static void intel_set_cdclk(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *cdclk_config, - enum pipe pipe) + enum pipe pipe, const char *context) { struct intel_encoder *encoder; @@ -2389,7 +2445,7 @@ static void intel_set_cdclk(struct drm_i915_private *dev_priv, if (drm_WARN_ON_ONCE(&dev_priv->drm, !dev_priv->display.funcs.cdclk->set_cdclk)) return; - intel_cdclk_dump_config(dev_priv, cdclk_config, "Changing CDCLK to"); + intel_cdclk_dump_config(dev_priv, cdclk_config, context); for_each_intel_encoder_with_psr(&dev_priv->drm, encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -2519,6 +2575,17 @@ static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state) update_cdclk, update_pipe_count); } +bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state) +{ + const struct intel_cdclk_state *old_cdclk_state = + intel_atomic_get_old_cdclk_state(state); + const struct intel_cdclk_state *new_cdclk_state = + intel_atomic_get_new_cdclk_state(state); + + return new_cdclk_state && !new_cdclk_state->disable_pipes && + new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk; +} + /** * intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware * @state: intel atomic state @@ -2534,7 +2601,8 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - enum pipe pipe = new_cdclk_state->pipe; + struct intel_cdclk_config cdclk_config; + enum pipe pipe; if (!intel_cdclk_changed(&old_cdclk_state->actual, &new_cdclk_state->actual)) @@ -2543,12 +2611,32 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) if (IS_DG2(i915)) intel_cdclk_pcode_pre_notify(state); - if (pipe == INVALID_PIPE || - old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) { - drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + if (new_cdclk_state->disable_pipes) { + cdclk_config = new_cdclk_state->actual; + pipe = INVALID_PIPE; + } else { + if (new_cdclk_state->actual.cdclk >= old_cdclk_state->actual.cdclk) { + cdclk_config = new_cdclk_state->actual; + pipe = new_cdclk_state->pipe; + } else { + cdclk_config = old_cdclk_state->actual; + pipe = INVALID_PIPE; + } - intel_set_cdclk(i915, &new_cdclk_state->actual, pipe); + cdclk_config.voltage_level = max(new_cdclk_state->actual.voltage_level, + old_cdclk_state->actual.voltage_level); } + + /* + * mbus joining will be changed later by + * intel_dbuf_mbus_{pre,post}_ddb_update() + */ + cdclk_config.joined_mbus = old_cdclk_state->actual.joined_mbus; + + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + + intel_set_cdclk(i915, &cdclk_config, pipe, + "Pre changing CDCLK to"); } /** @@ -2566,7 +2654,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - enum pipe pipe = new_cdclk_state->pipe; + enum pipe pipe; if (!intel_cdclk_changed(&old_cdclk_state->actual, &new_cdclk_state->actual)) @@ -2575,12 +2663,16 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) if (IS_DG2(i915)) intel_cdclk_pcode_post_notify(state); - if (pipe != INVALID_PIPE && - old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) { - drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + if (!new_cdclk_state->disable_pipes && + new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk) + pipe = new_cdclk_state->pipe; + else + pipe = INVALID_PIPE; - intel_set_cdclk(i915, &new_cdclk_state->actual, pipe); - } + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + + intel_set_cdclk(i915, &new_cdclk_state->actual, pipe, + "Post changing CDCLK to"); } static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) @@ -2731,25 +2823,6 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) if (crtc_state->dsc.compression_enable) min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state)); - /* - * HACK. Currently for TGL/DG2 platforms we calculate - * min_cdclk initially based on pixel_rate divided - * by 2, accounting for also plane requirements, - * however in some cases the lowest possible CDCLK - * doesn't work and causing the underruns. - * Explicitly stating here that this seems to be currently - * rather a Hack, than final solution. - */ - if (IS_TIGERLAKE(dev_priv) || IS_DG2(dev_priv)) { - /* - * Clamp to max_cdclk_freq in case pixel rate is higher, - * in order not to break an 8K, but still leave W/A at place. - */ - min_cdclk = max_t(int, min_cdclk, - min_t(int, crtc_state->pixel_rate, - dev_priv->display.cdclk.max_cdclk_freq)); - } - return min_cdclk; } @@ -2937,7 +3010,7 @@ static int skl_dpll0_vco(struct intel_cdclk_state *cdclk_state) vco = cdclk_state->logical.vco; if (!vco) - vco = dev_priv->skl_preferred_vco_freq; + vco = dev_priv->display.cdclk.skl_preferred_vco_freq; for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { if (!crtc_state->hw.enable) @@ -3058,6 +3131,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa return NULL; cdclk_state->pipe = INVALID_PIPE; + cdclk_state->disable_pipes = false; return &cdclk_state->base; } @@ -3121,6 +3195,20 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, return 0; } +int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus) +{ + struct intel_cdclk_state *cdclk_state; + + cdclk_state = intel_atomic_get_cdclk_state(state); + if (IS_ERR(cdclk_state)) + return PTR_ERR(cdclk_state); + + cdclk_state->actual.joined_mbus = joined_mbus; + cdclk_state->logical.joined_mbus = joined_mbus; + + return intel_atomic_lock_global_state(&cdclk_state->base); +} + int intel_cdclk_init(struct drm_i915_private *dev_priv) { struct intel_cdclk_state *cdclk_state; @@ -3229,17 +3317,28 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) drm_dbg_kms(&dev_priv->drm, "Can change cdclk cd2x divider with pipe %c active\n", pipe_name(pipe)); - } else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual, + } else if (intel_cdclk_clock_changed(&old_cdclk_state->actual, &new_cdclk_state->actual)) { /* All pipes must be switched off while we change the cdclk. */ ret = intel_modeset_all_pipes_late(state, "CDCLK change"); if (ret) return ret; + new_cdclk_state->disable_pipes = true; + drm_dbg_kms(&dev_priv->drm, "Modeset required for cdclk change\n"); } + if (intel_mdclk_cdclk_ratio(dev_priv, &old_cdclk_state->actual) != + intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual)) { + int ratio = intel_mdclk_cdclk_ratio(dev_priv, &new_cdclk_state->actual); + + ret = intel_dbuf_state_set_mdclk_cdclk_ratio(state, ratio); + if (ret) + return ret; + } + drm_dbg_kms(&dev_priv->drm, "New cdclk calculated to be logical %u kHz, actual %u kHz\n", new_cdclk_state->logical.cdclk, @@ -3297,7 +3396,7 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) u32 limit = intel_de_read(dev_priv, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; int max_cdclk, vco; - vco = dev_priv->skl_preferred_vco_freq; + vco = dev_priv->display.cdclk.skl_preferred_vco_freq; drm_WARN_ON(&dev_priv->drm, vco != 8100000 && vco != 8640000); /* @@ -3339,13 +3438,13 @@ void intel_update_max_cdclk(struct drm_i915_private *dev_priv) dev_priv->display.cdclk.max_cdclk_freq = dev_priv->display.cdclk.hw.cdclk; } - dev_priv->max_dotclk_freq = intel_compute_max_dotclk(dev_priv); + dev_priv->display.cdclk.max_dotclk_freq = intel_compute_max_dotclk(dev_priv); drm_dbg(&dev_priv->drm, "Max CD clock rate: %d kHz\n", dev_priv->display.cdclk.max_cdclk_freq); drm_dbg(&dev_priv->drm, "Max dotclock rate: %d kHz\n", - dev_priv->max_dotclk_freq); + dev_priv->display.cdclk.max_dotclk_freq); } /** @@ -3519,7 +3618,7 @@ static int i915_cdclk_info_show(struct seq_file *m, void *unused) seq_printf(m, "Current CD clock frequency: %d kHz\n", i915->display.cdclk.hw.cdclk); seq_printf(m, "Max CD clock frequency: %d kHz\n", i915->display.cdclk.max_cdclk_freq); - seq_printf(m, "Max pixel clock frequency: %d kHz\n", i915->max_dotclk_freq); + seq_printf(m, "Max pixel clock frequency: %d kHz\n", i915->display.cdclk.max_dotclk_freq); return 0; } @@ -3534,13 +3633,6 @@ void intel_cdclk_debugfs_register(struct drm_i915_private *i915) i915, &i915_cdclk_info_fops); } -static const struct intel_cdclk_funcs mtl_cdclk_funcs = { - .get_cdclk = bxt_get_cdclk, - .set_cdclk = bxt_set_cdclk, - .modeset_calc_cdclk = bxt_modeset_calc_cdclk, - .calc_voltage_level = rplu_calc_voltage_level, -}; - static const struct intel_cdclk_funcs rplu_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, @@ -3684,10 +3776,10 @@ static const struct intel_cdclk_funcs i830_cdclk_funcs = { void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) { if (DISPLAY_VER(dev_priv) >= 20) { - dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs; - dev_priv->display.cdclk.table = lnl_cdclk_table; + dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; + dev_priv->display.cdclk.table = xe2lpd_cdclk_table; } else if (DISPLAY_VER(dev_priv) >= 14) { - dev_priv->display.funcs.cdclk = &mtl_cdclk_funcs; + dev_priv->display.funcs.cdclk = &rplu_cdclk_funcs; dev_priv->display.cdclk.table = mtl_cdclk_table; } else if (IS_DG2(dev_priv)) { dev_priv->display.funcs.cdclk = &tgl_cdclk_funcs; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 48fd7d39e0cd..cfdcdec07a4d 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -18,6 +18,8 @@ struct intel_crtc_state; struct intel_cdclk_config { unsigned int cdclk, vco, ref, bypass; u8 voltage_level; + /* This field is only valid for Xe2LPD and above. */ + bool joined_mbus; }; struct intel_cdclk_state { @@ -51,6 +53,9 @@ struct intel_cdclk_state { /* bitmask of active pipes */ u8 active_pipes; + + /* update cdclk with pipes disabled */ + bool disable_pipes; }; int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); @@ -60,8 +65,11 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv); void intel_update_max_cdclk(struct drm_i915_private *dev_priv); void intel_update_cdclk(struct drm_i915_private *dev_priv); u32 intel_read_rawclk(struct drm_i915_private *dev_priv); -bool intel_cdclk_needs_modeset(const struct intel_cdclk_config *a, +bool intel_cdclk_clock_changed(const struct intel_cdclk_config *a, const struct intel_cdclk_config *b); +int intel_mdclk_cdclk_ratio(struct drm_i915_private *i915, + const struct intel_cdclk_config *cdclk_config); +bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state); void intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state); void intel_set_cdclk_post_plane_update(struct intel_atomic_state *state); void intel_cdclk_dump_config(struct drm_i915_private *i915, @@ -72,10 +80,13 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv, struct intel_cdclk_config *cdclk_config); int intel_cdclk_atomic_check(struct intel_atomic_state *state, bool *need_cdclk_calc); +int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus); struct intel_cdclk_state * intel_atomic_get_cdclk_state(struct intel_atomic_state *state); -#define to_intel_cdclk_state(x) container_of((x), struct intel_cdclk_state, base) +#define to_intel_cdclk_state(global_state) \ + container_of_const((global_state), struct intel_cdclk_state, base) + #define intel_atomic_get_old_cdclk_state(state) \ to_intel_cdclk_state(intel_atomic_get_old_global_obj_state(state, &to_i915(state->base.dev)->display.cdclk.obj)) #define intel_atomic_get_new_cdclk_state(state) \ diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h b/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h index b0983edccf3f..0964e392d02c 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h +++ b/drivers/gpu/drm/i915/display/intel_combo_phy_regs.h @@ -25,28 +25,26 @@ 4 * (dw)) #define ICL_PORT_CL_DW5(phy) _MMIO(_ICL_PORT_CL_DW(5, phy)) -#define CL_POWER_DOWN_ENABLE (1 << 4) -#define SUS_CLOCK_CONFIG (3 << 0) +#define CL_POWER_DOWN_ENABLE REG_BIT(4) +#define SUS_CLOCK_CONFIG REG_GENMASK(1, 0) #define ICL_PORT_CL_DW10(phy) _MMIO(_ICL_PORT_CL_DW(10, phy)) -#define PG_SEQ_DELAY_OVERRIDE_MASK (3 << 25) -#define PG_SEQ_DELAY_OVERRIDE_SHIFT 25 -#define PG_SEQ_DELAY_OVERRIDE_ENABLE (1 << 24) -#define PWR_UP_ALL_LANES (0x0 << 4) -#define PWR_DOWN_LN_3_2_1 (0xe << 4) -#define PWR_DOWN_LN_3_2 (0xc << 4) -#define PWR_DOWN_LN_3 (0x8 << 4) -#define PWR_DOWN_LN_2_1_0 (0x7 << 4) -#define PWR_DOWN_LN_1_0 (0x3 << 4) -#define PWR_DOWN_LN_3_1 (0xa << 4) -#define PWR_DOWN_LN_3_1_0 (0xb << 4) -#define PWR_DOWN_LN_MASK (0xf << 4) -#define PWR_DOWN_LN_SHIFT 4 -#define EDP4K2K_MODE_OVRD_EN (1 << 3) -#define EDP4K2K_MODE_OVRD_OPTIMIZED (1 << 2) +#define PG_SEQ_DELAY_OVERRIDE_MASK REG_GENMASK(26, 25) +#define PG_SEQ_DELAY_OVERRIDE_ENABLE REG_BIT(24) +#define PWR_DOWN_LN_MASK REG_GENMASK(7, 4) +#define PWR_UP_ALL_LANES REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0x0) +#define PWR_DOWN_LN_3_2_1 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0xe) +#define PWR_DOWN_LN_3_2 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0xc) +#define PWR_DOWN_LN_3 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0x8) +#define PWR_DOWN_LN_2_1_0 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0x7) +#define PWR_DOWN_LN_1_0 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0x3) +#define PWR_DOWN_LN_3_1 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0xa) +#define PWR_DOWN_LN_3_1_0 REG_FIELD_PREP(PWR_DOWN_LN_MASK, 0xb) +#define EDP4K2K_MODE_OVRD_EN REG_BIT(3) +#define EDP4K2K_MODE_OVRD_OPTIMIZED REG_BIT(2) #define ICL_PORT_CL_DW12(phy) _MMIO(_ICL_PORT_CL_DW(12, phy)) -#define ICL_LANE_ENABLE_AUX (1 << 0) +#define ICL_LANE_ENABLE_AUX REG_BIT(0) /* ICL Port COMP_DW registers */ #define _ICL_PORT_COMP 0x100 @@ -54,24 +52,22 @@ _ICL_PORT_COMP + 4 * (dw)) #define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy)) -#define COMP_INIT (1 << 31) +#define COMP_INIT REG_BIT(31) #define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy)) #define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy)) -#define PROCESS_INFO_DOT_0 (0 << 26) -#define PROCESS_INFO_DOT_1 (1 << 26) -#define PROCESS_INFO_DOT_4 (2 << 26) -#define PROCESS_INFO_MASK (7 << 26) -#define PROCESS_INFO_SHIFT 26 -#define VOLTAGE_INFO_0_85V (0 << 24) -#define VOLTAGE_INFO_0_95V (1 << 24) -#define VOLTAGE_INFO_1_05V (2 << 24) -#define VOLTAGE_INFO_MASK (3 << 24) -#define VOLTAGE_INFO_SHIFT 24 +#define PROCESS_INFO_MASK REG_GENMASK(28, 26) +#define PROCESS_INFO_DOT_0 REG_FIELD_PREP(PROCESS_INFO_MASK, 0) +#define PROCESS_INFO_DOT_1 REG_FIELD_PREP(PROCESS_INFO_MASK, 1) +#define PROCESS_INFO_DOT_4 REG_FIELD_PREP(PROCESS_INFO_MASK, 2) +#define VOLTAGE_INFO_MASK REG_GENMASK(25, 24) +#define VOLTAGE_INFO_0_85V REG_FIELD_PREP(VOLTAGE_INFO_MASK, 0) +#define VOLTAGE_INFO_0_95V REG_FIELD_PREP(VOLTAGE_INFO_MASK, 1) +#define VOLTAGE_INFO_1_05V REG_FIELD_PREP(VOLTAGE_INFO_MASK, 2) #define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy)) -#define IREFGEN (1 << 24) +#define IREFGEN REG_BIT(24) #define ICL_PORT_COMP_DW9(phy) _MMIO(_ICL_PORT_COMP_DW(9, phy)) @@ -92,9 +88,9 @@ #define ICL_PORT_PCS_DW1_LN(ln, phy) _MMIO(_ICL_PORT_PCS_DW_LN(1, ln, phy)) #define DCC_MODE_SELECT_MASK REG_GENMASK(21, 20) #define RUN_DCC_ONCE REG_FIELD_PREP(DCC_MODE_SELECT_MASK, 0) -#define COMMON_KEEPER_EN (1 << 26) -#define LATENCY_OPTIM_MASK (0x3 << 2) -#define LATENCY_OPTIM_VAL(x) ((x) << 2) +#define COMMON_KEEPER_EN REG_BIT(26) +#define LATENCY_OPTIM_MASK REG_GENMASK(3, 2) +#define LATENCY_OPTIM_VAL(x) REG_FIELD_PREP(LATENCY_OPTIM_MASK, (x)) /* ICL Port TX registers */ #define _ICL_PORT_TX_AUX 0x380 @@ -111,42 +107,49 @@ #define ICL_PORT_TX_DW2_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(2, phy)) #define ICL_PORT_TX_DW2_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(2, phy)) #define ICL_PORT_TX_DW2_LN(ln, phy) _MMIO(_ICL_PORT_TX_DW_LN(2, ln, phy)) -#define SWING_SEL_UPPER(x) (((x) >> 3) << 15) -#define SWING_SEL_UPPER_MASK (1 << 15) -#define SWING_SEL_LOWER(x) (((x) & 0x7) << 11) -#define SWING_SEL_LOWER_MASK (0x7 << 11) -#define FRC_LATENCY_OPTIM_MASK (0x7 << 8) -#define FRC_LATENCY_OPTIM_VAL(x) ((x) << 8) -#define RCOMP_SCALAR(x) ((x) << 0) -#define RCOMP_SCALAR_MASK (0xFF << 0) +#define SWING_SEL_UPPER_MASK REG_BIT(15) +#define SWING_SEL_UPPER(x) REG_FIELD_PREP(SWING_SEL_UPPER_MASK, (x) >> 3) +#define SWING_SEL_LOWER_MASK REG_GENMASK(13, 11) +#define SWING_SEL_LOWER(x) REG_FIELD_PREP(SWING_SEL_LOWER_MASK, (x) & 0x7) +#define FRC_LATENCY_OPTIM_MASK REG_GENMASK(10, 8) +#define FRC_LATENCY_OPTIM_VAL(x) REG_FIELD_PREP(FRC_LATENCY_OPTIM_MASK, (x)) +#define RCOMP_SCALAR_MASK REG_GENMASK(7, 0) +#define RCOMP_SCALAR(x) REG_FIELD_PREP(RCOMP_SCALAR_MASK, (x)) #define ICL_PORT_TX_DW4_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(4, phy)) #define ICL_PORT_TX_DW4_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(4, phy)) #define ICL_PORT_TX_DW4_LN(ln, phy) _MMIO(_ICL_PORT_TX_DW_LN(4, ln, phy)) -#define LOADGEN_SELECT (1 << 31) -#define POST_CURSOR_1(x) ((x) << 12) -#define POST_CURSOR_1_MASK (0x3F << 12) -#define POST_CURSOR_2(x) ((x) << 6) -#define POST_CURSOR_2_MASK (0x3F << 6) -#define CURSOR_COEFF(x) ((x) << 0) -#define CURSOR_COEFF_MASK (0x3F << 0) +#define LOADGEN_SELECT REG_BIT(31) +#define POST_CURSOR_1_MASK REG_GENMASK(17, 12) +#define POST_CURSOR_1(x) REG_FIELD_PREP(POST_CURSOR_1_MASK, (x)) +#define POST_CURSOR_2_MASK REG_GENMASK(11, 6) +#define POST_CURSOR_2(x) REG_FIELD_PREP(POST_CURSOR_2_MASK, (x)) +#define CURSOR_COEFF_MASK REG_GENMASK(5, 0) +#define CURSOR_COEFF(x) REG_FIELD_PREP(CURSOR_COEFF_MASK, (x)) #define ICL_PORT_TX_DW5_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(5, phy)) #define ICL_PORT_TX_DW5_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(5, phy)) #define ICL_PORT_TX_DW5_LN(ln, phy) _MMIO(_ICL_PORT_TX_DW_LN(5, ln, phy)) -#define TX_TRAINING_EN (1 << 31) -#define TAP2_DISABLE (1 << 30) -#define TAP3_DISABLE (1 << 29) -#define SCALING_MODE_SEL(x) ((x) << 18) -#define SCALING_MODE_SEL_MASK (0x7 << 18) -#define RTERM_SELECT(x) ((x) << 3) -#define RTERM_SELECT_MASK (0x7 << 3) +#define TX_TRAINING_EN REG_BIT(31) +#define TAP2_DISABLE REG_BIT(30) +#define TAP3_DISABLE REG_BIT(29) +#define SCALING_MODE_SEL_MASK REG_GENMASK(20, 18) +#define SCALING_MODE_SEL(x) REG_FIELD_PREP(SCALING_MODE_SEL_MASK, (x)) +#define RTERM_SELECT_MASK REG_GENMASK(5, 3) +#define RTERM_SELECT(x) REG_FIELD_PREP(RTERM_SELECT_MASK, (x)) + +#define ICL_PORT_TX_DW6_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(6, phy)) +#define ICL_PORT_TX_DW6_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(6, phy)) +#define ICL_PORT_TX_DW6_LN(ln, phy) _MMIO(_ICL_PORT_TX_DW_LN(6, ln, phy)) +#define O_FUNC_OVRD_EN REG_BIT(7) +#define O_LDO_REF_SEL_CRI REG_GENMASK(6, 1) +#define O_LDO_BYPASS_CRI REG_BIT(0) #define ICL_PORT_TX_DW7_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(7, phy)) #define ICL_PORT_TX_DW7_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(7, phy)) #define ICL_PORT_TX_DW7_LN(ln, phy) _MMIO(_ICL_PORT_TX_DW_LN(7, ln, phy)) -#define N_SCALAR(x) ((x) << 24) -#define N_SCALAR_MASK (0x7F << 24) +#define N_SCALAR_MASK REG_GENMASK(30, 24) +#define N_SCALAR(x) REG_FIELD_PREP(N_SCALAR_MASK, (x)) #define ICL_PORT_TX_DW8_AUX(phy) _MMIO(_ICL_PORT_TX_DW_AUX(8, phy)) #define ICL_PORT_TX_DW8_GRP(phy) _MMIO(_ICL_PORT_TX_DW_GRP(8, phy)) diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c index 93479db0f89f..10e95dc425a6 100644 --- a/drivers/gpu/drm/i915/display/intel_crt.c +++ b/drivers/gpu/drm/i915/display/intel_crt.c @@ -348,7 +348,7 @@ intel_crt_mode_valid(struct drm_connector *connector, { struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = to_i915(dev); - int max_dotclk = dev_priv->max_dotclk_freq; + int max_dotclk = dev_priv->display.cdclk.max_dotclk_freq; enum drm_mode_status status; int max_clock; @@ -356,9 +356,6 @@ intel_crt_mode_valid(struct drm_connector *connector, if (status != MODE_OK) return status; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if (mode->clock < 25000) return MODE_CLOCK_LOW; diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index 4bcf446c75f4..ccaa4cb2809b 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -12,33 +12,31 @@ #include "intel_hdmi.h" #include "intel_vrr.h" -static void intel_dump_crtc_timings(struct drm_i915_private *i915, +static void intel_dump_crtc_timings(struct drm_printer *p, const struct drm_display_mode *mode) { - drm_dbg_kms(&i915->drm, "crtc timings: clock=%d, " - "hd=%d hb=%d-%d hs=%d-%d ht=%d, " - "vd=%d vb=%d-%d vs=%d-%d vt=%d, " - "flags=0x%x\n", - mode->crtc_clock, - mode->crtc_hdisplay, mode->crtc_hblank_start, mode->crtc_hblank_end, - mode->crtc_hsync_start, mode->crtc_hsync_end, mode->crtc_htotal, - mode->crtc_vdisplay, mode->crtc_vblank_start, mode->crtc_vblank_end, - mode->crtc_vsync_start, mode->crtc_vsync_end, mode->crtc_vtotal, - mode->flags); + drm_printf(p, "crtc timings: clock=%d, " + "hd=%d hb=%d-%d hs=%d-%d ht=%d, " + "vd=%d vb=%d-%d vs=%d-%d vt=%d, " + "flags=0x%x\n", + mode->crtc_clock, + mode->crtc_hdisplay, mode->crtc_hblank_start, mode->crtc_hblank_end, + mode->crtc_hsync_start, mode->crtc_hsync_end, mode->crtc_htotal, + mode->crtc_vdisplay, mode->crtc_vblank_start, mode->crtc_vblank_end, + mode->crtc_vsync_start, mode->crtc_vsync_end, mode->crtc_vtotal, + mode->flags); } static void -intel_dump_m_n_config(const struct intel_crtc_state *pipe_config, +intel_dump_m_n_config(struct drm_printer *p, + const struct intel_crtc_state *pipe_config, const char *id, unsigned int lane_count, const struct intel_link_m_n *m_n) { - struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); - - drm_dbg_kms(&i915->drm, - "%s: lanes: %i; data_m: %u, data_n: %u, link_m: %u, link_n: %u, tu: %u\n", - id, lane_count, - m_n->data_m, m_n->data_n, - m_n->link_m, m_n->link_n, m_n->tu); + drm_printf(p, "%s: lanes: %i; data_m: %u, data_n: %u, link_m: %u, link_n: %u, tu: %u\n", + id, lane_count, + m_n->data_m, m_n->data_n, + m_n->link_m, m_n->link_n, m_n->tu); } static void @@ -52,17 +50,7 @@ intel_dump_infoframe(struct drm_i915_private *i915, } static void -intel_dump_dp_vsc_sdp(struct drm_i915_private *i915, - const struct drm_dp_vsc_sdp *vsc) -{ - struct drm_printer p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, NULL); - - drm_dp_vsc_sdp_log(&p, vsc); -} - -static void -intel_dump_buffer(struct drm_i915_private *i915, - const char *prefix, const u8 *buf, size_t len) +intel_dump_buffer(const char *prefix, const u8 *buf, size_t len) { if (!drm_debug_enabled(DRM_UT_KMS)) return; @@ -130,71 +118,66 @@ const char *intel_output_format_name(enum intel_output_format format) return output_format_str[format]; } -static void intel_dump_plane_state(const struct intel_plane_state *plane_state) +static void intel_dump_plane_state(struct drm_printer *p, + const struct intel_plane_state *plane_state) { 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; if (!fb) { - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] fb: [NOFB], visible: %s\n", - plane->base.base.id, plane->base.name, - str_yes_no(plane_state->uapi.visible)); + drm_printf(p, "[PLANE:%d:%s] fb: [NOFB], visible: %s\n", + plane->base.base.id, plane->base.name, + str_yes_no(plane_state->uapi.visible)); return; } - drm_dbg_kms(&i915->drm, - "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n", - plane->base.base.id, plane->base.name, - fb->base.id, fb->width, fb->height, &fb->format->format, - fb->modifier, str_yes_no(plane_state->uapi.visible)); - drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d, scaling_filter: %d\n", - plane_state->hw.rotation, plane_state->scaler_id, plane_state->hw.scaling_filter); + drm_printf(p, "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n", + plane->base.base.id, plane->base.name, + fb->base.id, fb->width, fb->height, &fb->format->format, + fb->modifier, str_yes_no(plane_state->uapi.visible)); + drm_printf(p, "\trotation: 0x%x, scaler: %d, scaling_filter: %d\n", + plane_state->hw.rotation, plane_state->scaler_id, plane_state->hw.scaling_filter); if (plane_state->uapi.visible) - drm_dbg_kms(&i915->drm, - "\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", - DRM_RECT_FP_ARG(&plane_state->uapi.src), - DRM_RECT_ARG(&plane_state->uapi.dst)); + drm_printf(p, "\tsrc: " DRM_RECT_FP_FMT " dst: " DRM_RECT_FMT "\n", + DRM_RECT_FP_ARG(&plane_state->uapi.src), + DRM_RECT_ARG(&plane_state->uapi.dst)); } static void -ilk_dump_csc(struct drm_i915_private *i915, const char *name, +ilk_dump_csc(struct drm_i915_private *i915, + struct drm_printer *p, + const char *name, const struct intel_csc_matrix *csc) { int i; - drm_dbg_kms(&i915->drm, - "%s: pre offsets: 0x%04x 0x%04x 0x%04x\n", name, - csc->preoff[0], csc->preoff[1], csc->preoff[2]); + drm_printf(p, "%s: pre offsets: 0x%04x 0x%04x 0x%04x\n", name, + csc->preoff[0], csc->preoff[1], csc->preoff[2]); for (i = 0; i < 3; i++) - drm_dbg_kms(&i915->drm, - "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name, - csc->coeff[3 * i + 0], - csc->coeff[3 * i + 1], - csc->coeff[3 * i + 2]); + drm_printf(p, "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name, + csc->coeff[3 * i + 0], + csc->coeff[3 * i + 1], + csc->coeff[3 * i + 2]); if (DISPLAY_VER(i915) < 7) return; - drm_dbg_kms(&i915->drm, - "%s: post offsets: 0x%04x 0x%04x 0x%04x\n", name, - csc->postoff[0], csc->postoff[1], csc->postoff[2]); + drm_printf(p, "%s: post offsets: 0x%04x 0x%04x 0x%04x\n", name, + csc->postoff[0], csc->postoff[1], csc->postoff[2]); } static void -vlv_dump_csc(struct drm_i915_private *i915, const char *name, +vlv_dump_csc(struct drm_printer *p, const char *name, const struct intel_csc_matrix *csc) { int i; for (i = 0; i < 3; i++) - drm_dbg_kms(&i915->drm, - "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name, - csc->coeff[3 * i + 0], - csc->coeff[3 * i + 1], - csc->coeff[3 * i + 2]); + drm_printf(p, "%s: coefficients: 0x%04x 0x%04x 0x%04x\n", name, + csc->coeff[3 * i + 0], + csc->coeff[3 * i + 1], + csc->coeff[3 * i + 2]); } void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, @@ -205,85 +188,86 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, struct drm_i915_private *i915 = to_i915(crtc->base.dev); const struct intel_plane_state *plane_state; struct intel_plane *plane; + struct drm_printer p; char buf[64]; int i; - drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] enable: %s [%s]\n", - crtc->base.base.id, crtc->base.name, - str_yes_no(pipe_config->hw.enable), context); + if (!drm_debug_enabled(DRM_UT_KMS)) + return; + + p = drm_dbg_printer(&i915->drm, DRM_UT_KMS, NULL); + + drm_printf(&p, "[CRTC:%d:%s] enable: %s [%s]\n", + crtc->base.base.id, crtc->base.name, + str_yes_no(pipe_config->hw.enable), context); if (!pipe_config->hw.enable) goto dump_planes; snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); - drm_dbg_kms(&i915->drm, - "active: %s, output_types: %s (0x%x), output format: %s, sink format: %s\n", - str_yes_no(pipe_config->hw.active), - buf, pipe_config->output_types, - intel_output_format_name(pipe_config->output_format), - intel_output_format_name(pipe_config->sink_format)); + drm_printf(&p, "active: %s, output_types: %s (0x%x), output format: %s, sink format: %s\n", + str_yes_no(pipe_config->hw.active), + buf, pipe_config->output_types, + intel_output_format_name(pipe_config->output_format), + intel_output_format_name(pipe_config->sink_format)); - drm_dbg_kms(&i915->drm, - "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", - transcoder_name(pipe_config->cpu_transcoder), - pipe_config->pipe_bpp, pipe_config->dither); + drm_printf(&p, "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", + transcoder_name(pipe_config->cpu_transcoder), + pipe_config->pipe_bpp, pipe_config->dither); - drm_dbg_kms(&i915->drm, "MST master transcoder: %s\n", - transcoder_name(pipe_config->mst_master_transcoder)); + drm_printf(&p, "MST master transcoder: %s\n", + transcoder_name(pipe_config->mst_master_transcoder)); - drm_dbg_kms(&i915->drm, - "port sync: master transcoder: %s, slave transcoder bitmask = 0x%x\n", - transcoder_name(pipe_config->master_transcoder), - pipe_config->sync_mode_slaves_mask); + drm_printf(&p, "port sync: master transcoder: %s, slave transcoder bitmask = 0x%x\n", + transcoder_name(pipe_config->master_transcoder), + pipe_config->sync_mode_slaves_mask); - drm_dbg_kms(&i915->drm, "bigjoiner: %s, pipes: 0x%x\n", - intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : - intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", - pipe_config->bigjoiner_pipes); + drm_printf(&p, "bigjoiner: %s, pipes: 0x%x\n", + intel_crtc_is_bigjoiner_slave(pipe_config) ? "slave" : + intel_crtc_is_bigjoiner_master(pipe_config) ? "master" : "no", + pipe_config->bigjoiner_pipes); - drm_dbg_kms(&i915->drm, "splitter: %s, link count %d, overlap %d\n", - str_enabled_disabled(pipe_config->splitter.enable), - pipe_config->splitter.link_count, - pipe_config->splitter.pixel_overlap); + drm_printf(&p, "splitter: %s, link count %d, overlap %d\n", + str_enabled_disabled(pipe_config->splitter.enable), + pipe_config->splitter.link_count, + pipe_config->splitter.pixel_overlap); if (pipe_config->has_pch_encoder) - intel_dump_m_n_config(pipe_config, "fdi", + intel_dump_m_n_config(&p, pipe_config, "fdi", pipe_config->fdi_lanes, &pipe_config->fdi_m_n); if (intel_crtc_has_dp_encoder(pipe_config)) { - intel_dump_m_n_config(pipe_config, "dp m_n", + intel_dump_m_n_config(&p, pipe_config, "dp m_n", pipe_config->lane_count, &pipe_config->dp_m_n); - intel_dump_m_n_config(pipe_config, "dp m2_n2", + intel_dump_m_n_config(&p, pipe_config, "dp m2_n2", pipe_config->lane_count, &pipe_config->dp_m2_n2); - drm_dbg_kms(&i915->drm, "fec: %s, enhanced framing: %s\n", - str_enabled_disabled(pipe_config->fec_enable), - str_enabled_disabled(pipe_config->enhanced_framing)); + drm_printf(&p, "fec: %s, enhanced framing: %s\n", + str_enabled_disabled(pipe_config->fec_enable), + str_enabled_disabled(pipe_config->enhanced_framing)); - drm_dbg_kms(&i915->drm, "sdp split: %s\n", - str_enabled_disabled(pipe_config->sdp_split_enable)); + drm_printf(&p, "sdp split: %s\n", + str_enabled_disabled(pipe_config->sdp_split_enable)); - drm_dbg_kms(&i915->drm, "psr: %s, psr2: %s, panel replay: %s, selective fetch: %s\n", - str_enabled_disabled(pipe_config->has_psr), - str_enabled_disabled(pipe_config->has_psr2), - str_enabled_disabled(pipe_config->has_panel_replay), - str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); + drm_printf(&p, "psr: %s, psr2: %s, panel replay: %s, selective fetch: %s\n", + str_enabled_disabled(pipe_config->has_psr), + str_enabled_disabled(pipe_config->has_psr2), + str_enabled_disabled(pipe_config->has_panel_replay), + str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); } - drm_dbg_kms(&i915->drm, "framestart delay: %d, MSA timing delay: %d\n", - pipe_config->framestart_delay, pipe_config->msa_timing_delay); + drm_printf(&p, "framestart delay: %d, MSA timing delay: %d\n", + pipe_config->framestart_delay, pipe_config->msa_timing_delay); - drm_dbg_kms(&i915->drm, - "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", - pipe_config->has_audio, pipe_config->has_infoframe, - pipe_config->infoframes.enable); + drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", + pipe_config->has_audio, pipe_config->has_infoframe, + pipe_config->infoframes.enable); if (pipe_config->infoframes.enable & intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL)) - drm_dbg_kms(&i915->drm, "GCP: 0x%x\n", - pipe_config->infoframes.gcp); + drm_printf(&p, "GCP: 0x%x\n", pipe_config->infoframes.gcp); if (pipe_config->infoframes.enable & intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI)) intel_dump_infoframe(i915, &pipe_config->infoframes.avi); @@ -301,91 +285,88 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, intel_dump_infoframe(i915, &pipe_config->infoframes.drm); if (pipe_config->infoframes.enable & intel_hdmi_infoframe_enable(DP_SDP_VSC)) - intel_dump_dp_vsc_sdp(i915, &pipe_config->infoframes.vsc); + drm_dp_vsc_sdp_log(&p, &pipe_config->infoframes.vsc); + if (pipe_config->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC)) + drm_dp_as_sdp_log(&p, &pipe_config->infoframes.as_sdp); if (pipe_config->has_audio) - intel_dump_buffer(i915, "ELD: ", pipe_config->eld, + intel_dump_buffer("ELD: ", pipe_config->eld, drm_eld_size(pipe_config->eld)); - drm_dbg_kms(&i915->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", - str_yes_no(pipe_config->vrr.enable), - pipe_config->vrr.vmin, pipe_config->vrr.vmax, - pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, - pipe_config->vrr.flipline, - intel_vrr_vmin_vblank_start(pipe_config), - intel_vrr_vmax_vblank_start(pipe_config)); + drm_printf(&p, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", + str_yes_no(pipe_config->vrr.enable), + pipe_config->vrr.vmin, pipe_config->vrr.vmax, + pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, + pipe_config->vrr.flipline, + intel_vrr_vmin_vblank_start(pipe_config), + intel_vrr_vmax_vblank_start(pipe_config)); - drm_dbg_kms(&i915->drm, "requested mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.mode)); - drm_dbg_kms(&i915->drm, "adjusted mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.adjusted_mode)); - intel_dump_crtc_timings(i915, &pipe_config->hw.adjusted_mode); - drm_dbg_kms(&i915->drm, "pipe mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); - intel_dump_crtc_timings(i915, &pipe_config->hw.pipe_mode); - drm_dbg_kms(&i915->drm, - "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", - pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), - pipe_config->pixel_rate); + drm_printf(&p, "requested mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.mode)); + drm_printf(&p, "adjusted mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.adjusted_mode)); + intel_dump_crtc_timings(&p, &pipe_config->hw.adjusted_mode); + drm_printf(&p, "pipe mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); + intel_dump_crtc_timings(&p, &pipe_config->hw.pipe_mode); + drm_printf(&p, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", + pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), + pipe_config->pixel_rate); - drm_dbg_kms(&i915->drm, "linetime: %d, ips linetime: %d\n", - pipe_config->linetime, pipe_config->ips_linetime); + drm_printf(&p, "linetime: %d, ips linetime: %d\n", + pipe_config->linetime, pipe_config->ips_linetime); if (DISPLAY_VER(i915) >= 9) - drm_dbg_kms(&i915->drm, - "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d\n", - crtc->num_scalers, - pipe_config->scaler_state.scaler_users, - pipe_config->scaler_state.scaler_id, - pipe_config->hw.scaling_filter); + drm_printf(&p, "num_scalers: %d, scaler_users: 0x%x, scaler_id: %d, scaling_filter: %d\n", + crtc->num_scalers, + pipe_config->scaler_state.scaler_users, + pipe_config->scaler_state.scaler_id, + pipe_config->hw.scaling_filter); if (HAS_GMCH(i915)) - drm_dbg_kms(&i915->drm, - "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", - pipe_config->gmch_pfit.control, - pipe_config->gmch_pfit.pgm_ratios, - pipe_config->gmch_pfit.lvds_border_bits); + drm_printf(&p, "gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n", + pipe_config->gmch_pfit.control, + pipe_config->gmch_pfit.pgm_ratios, + pipe_config->gmch_pfit.lvds_border_bits); else - drm_dbg_kms(&i915->drm, - "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", - DRM_RECT_ARG(&pipe_config->pch_pfit.dst), - str_enabled_disabled(pipe_config->pch_pfit.enabled), - str_yes_no(pipe_config->pch_pfit.force_thru)); + drm_printf(&p, "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", + DRM_RECT_ARG(&pipe_config->pch_pfit.dst), + str_enabled_disabled(pipe_config->pch_pfit.enabled), + str_yes_no(pipe_config->pch_pfit.force_thru)); - drm_dbg_kms(&i915->drm, "ips: %i, double wide: %i, drrs: %i\n", - pipe_config->ips_enabled, pipe_config->double_wide, - pipe_config->has_drrs); + drm_printf(&p, "ips: %i, double wide: %i, drrs: %i\n", + pipe_config->ips_enabled, pipe_config->double_wide, + pipe_config->has_drrs); - intel_dpll_dump_hw_state(i915, &pipe_config->dpll_hw_state); + intel_dpll_dump_hw_state(i915, &p, &pipe_config->dpll_hw_state); if (IS_CHERRYVIEW(i915)) - drm_dbg_kms(&i915->drm, - "cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", - pipe_config->cgm_mode, pipe_config->gamma_mode, - pipe_config->gamma_enable, pipe_config->csc_enable); + drm_printf(&p, "cgm_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", + pipe_config->cgm_mode, pipe_config->gamma_mode, + pipe_config->gamma_enable, pipe_config->csc_enable); else - drm_dbg_kms(&i915->drm, - "csc_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", - pipe_config->csc_mode, pipe_config->gamma_mode, - pipe_config->gamma_enable, pipe_config->csc_enable); + drm_printf(&p, "csc_mode: 0x%x gamma_mode: 0x%x gamma_enable: %d csc_enable: %d\n", + pipe_config->csc_mode, pipe_config->gamma_mode, + pipe_config->gamma_enable, pipe_config->csc_enable); - drm_dbg_kms(&i915->drm, "pre csc lut: %s%d entries, post csc lut: %d entries\n", - pipe_config->pre_csc_lut && pipe_config->pre_csc_lut == - i915->display.color.glk_linear_degamma_lut ? "(linear) " : "", - pipe_config->pre_csc_lut ? - drm_color_lut_size(pipe_config->pre_csc_lut) : 0, - pipe_config->post_csc_lut ? - drm_color_lut_size(pipe_config->post_csc_lut) : 0); + drm_printf(&p, "pre csc lut: %s%d entries, post csc lut: %d entries\n", + pipe_config->pre_csc_lut && pipe_config->pre_csc_lut == + i915->display.color.glk_linear_degamma_lut ? "(linear) " : "", + pipe_config->pre_csc_lut ? + drm_color_lut_size(pipe_config->pre_csc_lut) : 0, + pipe_config->post_csc_lut ? + drm_color_lut_size(pipe_config->post_csc_lut) : 0); if (DISPLAY_VER(i915) >= 11) - ilk_dump_csc(i915, "output csc", &pipe_config->output_csc); + ilk_dump_csc(i915, &p, "output csc", &pipe_config->output_csc); if (!HAS_GMCH(i915)) - ilk_dump_csc(i915, "pipe csc", &pipe_config->csc); + ilk_dump_csc(i915, &p, "pipe csc", &pipe_config->csc); else if (IS_CHERRYVIEW(i915)) - vlv_dump_csc(i915, "cgm csc", &pipe_config->csc); + vlv_dump_csc(&p, "cgm csc", &pipe_config->csc); else if (IS_VALLEYVIEW(i915)) - vlv_dump_csc(i915, "wgc csc", &pipe_config->csc); + vlv_dump_csc(&p, "wgc csc", &pipe_config->csc); dump_planes: if (!state) @@ -393,6 +374,6 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, for_each_new_intel_plane_in_state(state, plane, plane_state, i) { if (plane->pipe == crtc->pipe) - intel_dump_plane_state(plane_state); + intel_dump_plane_state(&p, plane_state); } } diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 0d3da55e1c24..23a122ee20c9 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -509,6 +509,24 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), 0); } +static void wa_16021440873(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + u32 ctl = plane_state->ctl; + int et_y_position = drm_rect_height(&crtc_state->pipe_src) + 1; + enum pipe pipe = plane->pipe; + + ctl &= ~MCURSOR_MODE_MASK; + ctl |= MCURSOR_MODE_64_2B; + + intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), ctl); + + intel_de_write(dev_priv, PIPE_SRCSZ_ERLY_TPT(pipe), + PIPESRC_HEIGHT(et_y_position)); +} + static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) @@ -529,7 +547,11 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SEL_FETCH_CTL(pipe, plane->id), plane_state->ctl); } else { - i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state); + /* Wa_16021440873 */ + if (crtc_state->enable_psr2_su_region_et) + wa_16021440873(plane, crtc_state, plane_state); + else + i9xx_cursor_disable_sel_fetch_arm(plane, crtc_state); } } @@ -821,6 +843,28 @@ static const struct drm_plane_funcs intel_cursor_plane_funcs = { .format_mod_supported = intel_cursor_format_mod_supported, }; +static void intel_cursor_add_size_hints_property(struct intel_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + const struct drm_mode_config *config = &i915->drm.mode_config; + struct drm_plane_size_hint hints[4]; + int size, max_size, num_hints = 0; + + max_size = min(config->cursor_width, config->cursor_height); + + /* for simplicity only enumerate the supported square+POT sizes */ + for (size = 64; size <= max_size; size *= 2) { + if (drm_WARN_ON(&i915->drm, num_hints >= ARRAY_SIZE(hints))) + break; + + hints[num_hints].width = size; + hints[num_hints].height = size; + num_hints++; + } + + drm_plane_add_size_hints_property(&plane->base, hints, num_hints); +} + struct intel_plane * intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -879,6 +923,8 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180); + intel_cursor_add_size_hints_property(cursor); + zpos = DISPLAY_RUNTIME_INFO(dev_priv)->num_sprites[pipe] + 1; drm_plane_create_zpos_immutable_property(&cursor->base, zpos); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 64e0f820a789..8e3b13884bb8 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -29,8 +29,11 @@ #define INTEL_CX0_LANE1 BIT(1) #define INTEL_CX0_BOTH_LANES (INTEL_CX0_LANE1 | INTEL_CX0_LANE0) -bool intel_is_c10phy(struct drm_i915_private *i915, enum phy phy) +bool intel_encoder_is_c10phy(struct intel_encoder *encoder) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); + if ((IS_LUNARLAKE(i915) || IS_METEORLAKE(i915)) && phy < PHY_C) return true; @@ -46,8 +49,7 @@ static int lane_mask_to_lane(u8 lane_mask) return ilog2(lane_mask); } -static u8 intel_cx0_get_owned_lane_mask(struct drm_i915_private *i915, - struct intel_encoder *encoder) +static u8 intel_cx0_get_owned_lane_mask(struct intel_encoder *encoder) { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); @@ -114,16 +116,20 @@ static void intel_cx0_phy_transaction_end(struct intel_encoder *encoder, intel_w intel_display_power_put(i915, POWER_DOMAIN_DC_OFF, wakeref); } -static void intel_clear_response_ready_flag(struct drm_i915_private *i915, - enum port port, int lane) +static void intel_clear_response_ready_flag(struct intel_encoder *encoder, + int lane) { - intel_de_rmw(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane), + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + intel_de_rmw(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(i915, encoder->port, lane), 0, XELPDP_PORT_P2M_RESPONSE_READY | XELPDP_PORT_P2M_ERROR_SET); } -static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, int lane) +static void intel_cx0_bus_reset(struct intel_encoder *encoder, int lane) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + enum phy phy = intel_encoder_to_phy(encoder); intel_de_write(i915, XELPDP_PORT_M2P_MSGBUS_CTL(i915, port, lane), XELPDP_PORT_M2P_TRANSACTION_RESET); @@ -135,20 +141,22 @@ static void intel_cx0_bus_reset(struct drm_i915_private *i915, enum port port, i return; } - intel_clear_response_ready_flag(i915, port, lane); + intel_clear_response_ready_flag(encoder, lane); } -static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port, +static int intel_cx0_wait_for_ack(struct intel_encoder *encoder, int command, int lane, u32 *val) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + enum phy phy = intel_encoder_to_phy(encoder); - if (__intel_de_wait_for_register(i915, - XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane), - XELPDP_PORT_P2M_RESPONSE_READY, - XELPDP_PORT_P2M_RESPONSE_READY, - XELPDP_MSGBUS_TIMEOUT_FAST_US, - XELPDP_MSGBUS_TIMEOUT_SLOW, val)) { + if (intel_de_wait_custom(i915, + XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane), + XELPDP_PORT_P2M_RESPONSE_READY, + XELPDP_PORT_P2M_RESPONSE_READY, + XELPDP_MSGBUS_TIMEOUT_FAST_US, + XELPDP_MSGBUS_TIMEOUT_SLOW, val)) { drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for message ACK. Status: 0x%x\n", phy_name(phy), *val); @@ -158,31 +166,33 @@ static int intel_cx0_wait_for_ack(struct drm_i915_private *i915, enum port port, "PHY %c Hardware did not detect a timeout\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -ETIMEDOUT; } if (*val & XELPDP_PORT_P2M_ERROR_SET) { drm_dbg_kms(&i915->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy), command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -EINVAL; } if (REG_FIELD_GET(XELPDP_PORT_P2M_COMMAND_TYPE_MASK, *val) != command) { drm_dbg_kms(&i915->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy), command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -EINVAL; } return 0; } -static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port, +static int __intel_cx0_read_once(struct intel_encoder *encoder, int lane, u16 addr) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + enum phy phy = intel_encoder_to_phy(encoder); int ack; u32 val; @@ -191,7 +201,7 @@ static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port, XELPDP_MSGBUS_TIMEOUT_SLOW)) { drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for previous transaction to complete. Reset the bus and retry.\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -ETIMEDOUT; } @@ -200,33 +210,34 @@ static int __intel_cx0_read_once(struct drm_i915_private *i915, enum port port, XELPDP_PORT_M2P_COMMAND_READ | XELPDP_PORT_M2P_ADDRESS(addr)); - ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val); + ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_READ_ACK, lane, &val); if (ack < 0) return ack; - intel_clear_response_ready_flag(i915, port, lane); + intel_clear_response_ready_flag(encoder, lane); /* * FIXME: Workaround to let HW to settle * down and let the message bus to end up * in a known state */ - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return REG_FIELD_GET(XELPDP_PORT_P2M_DATA_MASK, val); } -static u8 __intel_cx0_read(struct drm_i915_private *i915, enum port port, +static u8 __intel_cx0_read(struct intel_encoder *encoder, int lane, u16 addr) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); int i, status; assert_dc_off(i915); /* 3 tries is assumed to be enough to read successfully */ for (i = 0; i < 3; i++) { - status = __intel_cx0_read_once(i915, port, lane, addr); + status = __intel_cx0_read_once(encoder, lane, addr); if (status >= 0) return status; @@ -238,18 +249,20 @@ static u8 __intel_cx0_read(struct drm_i915_private *i915, enum port port, return 0; } -static u8 intel_cx0_read(struct drm_i915_private *i915, enum port port, +static u8 intel_cx0_read(struct intel_encoder *encoder, u8 lane_mask, u16 addr) { int lane = lane_mask_to_lane(lane_mask); - return __intel_cx0_read(i915, port, lane, addr); + return __intel_cx0_read(encoder, lane, addr); } -static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port, +static int __intel_cx0_write_once(struct intel_encoder *encoder, int lane, u16 addr, u8 data, bool committed) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + enum phy phy = intel_encoder_to_phy(encoder); int ack; u32 val; @@ -258,7 +271,7 @@ static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port, XELPDP_MSGBUS_TIMEOUT_SLOW)) { drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for previous transaction to complete. Resetting the bus.\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -ETIMEDOUT; } @@ -274,45 +287,46 @@ static int __intel_cx0_write_once(struct drm_i915_private *i915, enum port port, XELPDP_MSGBUS_TIMEOUT_SLOW)) { drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for write to complete. Resetting the bus.\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -ETIMEDOUT; } if (committed) { - ack = intel_cx0_wait_for_ack(i915, port, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); + ack = intel_cx0_wait_for_ack(encoder, XELPDP_PORT_P2M_COMMAND_WRITE_ACK, lane, &val); if (ack < 0) return ack; } else if ((intel_de_read(i915, XELPDP_PORT_P2M_MSGBUS_STATUS(i915, port, lane)) & XELPDP_PORT_P2M_ERROR_SET)) { drm_dbg_kms(&i915->drm, "PHY %c Error occurred during write command.\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return -EINVAL; } - intel_clear_response_ready_flag(i915, port, lane); + intel_clear_response_ready_flag(encoder, lane); /* * FIXME: Workaround to let HW to settle * down and let the message bus to end up * in a known state */ - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); return 0; } -static void __intel_cx0_write(struct drm_i915_private *i915, enum port port, +static void __intel_cx0_write(struct intel_encoder *encoder, int lane, u16 addr, u8 data, bool committed) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); int i, status; assert_dc_off(i915); /* 3 tries is assumed to be enough to write successfully */ for (i = 0; i < 3; i++) { - status = __intel_cx0_write_once(i915, port, lane, addr, data, committed); + status = __intel_cx0_write_once(encoder, lane, addr, data, committed); if (status == 0) return; @@ -322,63 +336,66 @@ static void __intel_cx0_write(struct drm_i915_private *i915, enum port port, "PHY %c Write %04x failed after %d retries.\n", phy_name(phy), addr, i); } -static void intel_cx0_write(struct drm_i915_private *i915, enum port port, +static void intel_cx0_write(struct intel_encoder *encoder, u8 lane_mask, u16 addr, u8 data, bool committed) { int lane; for_each_cx0_lane_in_mask(lane_mask, lane) - __intel_cx0_write(i915, port, lane, addr, data, committed); + __intel_cx0_write(encoder, lane, addr, data, committed); } -static void intel_c20_sram_write(struct drm_i915_private *i915, enum port port, +static void intel_c20_sram_write(struct intel_encoder *encoder, int lane, u16 addr, u16 data) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + assert_dc_off(i915); - intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0); - intel_cx0_write(i915, port, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0); + intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_H, addr >> 8, 0); + intel_cx0_write(encoder, lane, PHY_C20_WR_ADDRESS_L, addr & 0xff, 0); - intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_H, data >> 8, 0); - intel_cx0_write(i915, port, lane, PHY_C20_WR_DATA_L, data & 0xff, 1); + intel_cx0_write(encoder, lane, PHY_C20_WR_DATA_H, data >> 8, 0); + intel_cx0_write(encoder, lane, PHY_C20_WR_DATA_L, data & 0xff, 1); } -static u16 intel_c20_sram_read(struct drm_i915_private *i915, enum port port, +static u16 intel_c20_sram_read(struct intel_encoder *encoder, int lane, u16 addr) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); u16 val; assert_dc_off(i915); - intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0); - intel_cx0_write(i915, port, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1); + intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_H, addr >> 8, 0); + intel_cx0_write(encoder, lane, PHY_C20_RD_ADDRESS_L, addr & 0xff, 1); - val = intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_H); + val = intel_cx0_read(encoder, lane, PHY_C20_RD_DATA_H); val <<= 8; - val |= intel_cx0_read(i915, port, lane, PHY_C20_RD_DATA_L); + val |= intel_cx0_read(encoder, lane, PHY_C20_RD_DATA_L); return val; } -static void __intel_cx0_rmw(struct drm_i915_private *i915, enum port port, +static void __intel_cx0_rmw(struct intel_encoder *encoder, int lane, u16 addr, u8 clear, u8 set, bool committed) { u8 old, val; - old = __intel_cx0_read(i915, port, lane, addr); + old = __intel_cx0_read(encoder, lane, addr); val = (old & ~clear) | set; if (val != old) - __intel_cx0_write(i915, port, lane, addr, val, committed); + __intel_cx0_write(encoder, lane, addr, val, committed); } -static void intel_cx0_rmw(struct drm_i915_private *i915, enum port port, +static void intel_cx0_rmw(struct intel_encoder *encoder, u8 lane_mask, u16 addr, u8 clear, u8 set, bool committed) { u8 lane; for_each_cx0_lane_in_mask(lane_mask, lane) - __intel_cx0_rmw(i915, port, lane, addr, clear, set, committed); + __intel_cx0_rmw(encoder, lane, addr, clear, set, committed); } static u8 intel_c10_get_tx_vboost_lvl(const struct intel_crtc_state *crtc_state) @@ -414,7 +431,6 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_ddi_buf_trans *trans; - enum phy phy = intel_port_to_phy(i915, encoder->port); u8 owned_lane_mask; intel_wakeref_t wakeref; int n_entries, ln; @@ -423,7 +439,7 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) return; - owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder); + owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); wakeref = intel_cx0_phy_transaction_begin(encoder); @@ -433,14 +449,14 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, return; } - if (intel_is_c10phy(i915, phy)) { - intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1), + if (intel_encoder_is_c10phy(encoder)) { + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); - intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CMN(3), + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CMN(3), C10_CMN3_TXVBOOST_MASK, C10_CMN3_TXVBOOST(intel_c10_get_tx_vboost_lvl(crtc_state)), MB_WRITE_UNCOMMITTED); - intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_TX(1), + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_TX(1), C10_TX1_TERMCTL_MASK, C10_TX1_TERMCTL(intel_c10_get_tx_term_ctl(crtc_state)), MB_WRITE_COMMITTED); @@ -455,27 +471,27 @@ void intel_cx0_phy_set_signal_levels(struct intel_encoder *encoder, if (!(lane_mask & owned_lane_mask)) continue; - intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 0), + intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 0), C10_PHY_OVRD_LEVEL_MASK, C10_PHY_OVRD_LEVEL(trans->entries[level].snps.pre_cursor), MB_WRITE_COMMITTED); - intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 1), + intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 1), C10_PHY_OVRD_LEVEL_MASK, C10_PHY_OVRD_LEVEL(trans->entries[level].snps.vswing), MB_WRITE_COMMITTED); - intel_cx0_rmw(i915, encoder->port, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 2), + intel_cx0_rmw(encoder, lane_mask, PHY_CX0_VDROVRD_CTL(lane, tx, 2), C10_PHY_OVRD_LEVEL_MASK, C10_PHY_OVRD_LEVEL(trans->entries[level].snps.post_cursor), MB_WRITE_COMMITTED); } /* Write Override enables in 0xD71 */ - intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_OVRD, + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_OVRD, 0, PHY_C10_VDR_OVRD_TX1 | PHY_C10_VDR_OVRD_TX2, MB_WRITE_COMMITTED); - if (intel_is_c10phy(i915, phy)) - intel_cx0_rmw(i915, encoder->port, owned_lane_mask, PHY_C10_VDR_CONTROL(1), + if (intel_encoder_is_c10phy(encoder)) + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); intel_cx0_phy_transaction_end(encoder, wakeref); @@ -1811,7 +1827,7 @@ static void intel_c10pll_update_pll(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_cx0pll_state *pll_state = &crtc_state->cx0pll_state; + struct intel_cx0pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll; int i; if (intel_crtc_has_dp_encoder(crtc_state)) { @@ -1843,7 +1859,7 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { - crtc_state->cx0pll_state.c10 = *tables[i]; + crtc_state->dpll_hw_state.cx0pll.c10 = *tables[i]; intel_c10pll_update_pll(crtc_state, encoder); return 0; @@ -1856,7 +1872,6 @@ static int intel_c10pll_calc_state(struct intel_crtc_state *crtc_state, static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, struct intel_c10pll_state *pll_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); u8 lane = INTEL_CX0_LANE0; intel_wakeref_t wakeref; int i; @@ -1867,16 +1882,15 @@ static void intel_c10pll_readout_hw_state(struct intel_encoder *encoder, * According to C10 VDR Register programming Sequence we need * to do this to read PHY internal registers from MsgBus. */ - intel_cx0_rmw(i915, encoder->port, lane, PHY_C10_VDR_CONTROL(1), + intel_cx0_rmw(encoder, lane, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) - pll_state->pll[i] = intel_cx0_read(i915, encoder->port, lane, - PHY_C10_VDR_PLL(i)); + pll_state->pll[i] = intel_cx0_read(encoder, lane, PHY_C10_VDR_PLL(i)); - pll_state->cmn = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_CMN(0)); - pll_state->tx = intel_cx0_read(i915, encoder->port, lane, PHY_C10_VDR_TX(0)); + pll_state->cmn = intel_cx0_read(encoder, lane, PHY_C10_VDR_CMN(0)); + pll_state->tx = intel_cx0_read(encoder, lane, PHY_C10_VDR_TX(0)); intel_cx0_phy_transaction_end(encoder, wakeref); } @@ -1885,31 +1899,31 @@ static void intel_c10_pll_program(struct drm_i915_private *i915, const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - const struct intel_c10pll_state *pll_state = &crtc_state->cx0pll_state.c10; + const struct intel_c10pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c10; int i; - intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); /* Custom width needs to be programmed to 0 for both the phy lanes */ - intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH, + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH, C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10, MB_WRITE_COMMITTED); - intel_cx0_rmw(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), + intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); /* Program the pll values only for the master lane */ for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++) - intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i), + intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i), pll_state->pll[i], (i % 4) ? MB_WRITE_UNCOMMITTED : MB_WRITE_COMMITTED); - intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED); - intel_cx0_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED); + intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED); + intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED); - intel_cx0_rmw(i915, encoder->port, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1), + intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); } @@ -2037,10 +2051,8 @@ static int intel_c20_phy_check_hdmi_link_rate(int clock) int intel_cx0_phy_check_hdmi_link_rate(struct intel_hdmi *hdmi, int clock) { struct intel_digital_port *dig_port = hdmi_to_dig_port(hdmi); - struct drm_i915_private *i915 = intel_hdmi_to_i915(hdmi); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(&dig_port->base)) return intel_c10_phy_check_hdmi_link_rate(clock); return intel_c20_phy_check_hdmi_link_rate(clock); } @@ -2067,7 +2079,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, /* try computed C20 HDMI tables before using consolidated tables */ if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { if (intel_c20_compute_hdmi_tmds_pll(crtc_state->port_clock, - &crtc_state->cx0pll_state.c20) == 0) + &crtc_state->dpll_hw_state.cx0pll.c20) == 0) return 0; } @@ -2077,7 +2089,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { - crtc_state->cx0pll_state.c20 = *tables[i]; + crtc_state->dpll_hw_state.cx0pll.c20 = *tables[i]; return 0; } } @@ -2088,10 +2100,7 @@ static int intel_c20pll_calc_state(struct intel_crtc_state *crtc_state, int intel_cx0pll_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) return intel_c10pll_calc_state(crtc_state, encoder); return intel_c20pll_calc_state(crtc_state, encoder); } @@ -2149,7 +2158,6 @@ static int intel_c20pll_calc_port_clock(struct intel_encoder *encoder, static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, struct intel_c20pll_state *pll_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); bool cntx; intel_wakeref_t wakeref; int i; @@ -2157,25 +2165,25 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, wakeref = intel_cx0_phy_transaction_begin(encoder); /* 1. Read current context selection */ - cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; + cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & PHY_C20_CONTEXT_TOGGLE; /* Read Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { if (cntx) - pll_state->tx[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->tx[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_B_TX_CNTX_CFG(i)); else - pll_state->tx[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->tx[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_A_TX_CNTX_CFG(i)); } /* Read common configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { if (cntx) - pll_state->cmn[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->cmn[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_B_CMN_CNTX_CFG(i)); else - pll_state->cmn[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->cmn[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_A_CMN_CNTX_CFG(i)); } @@ -2183,20 +2191,20 @@ static void intel_c20pll_readout_hw_state(struct intel_encoder *encoder, /* MPLLB configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { if (cntx) - pll_state->mpllb[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->mpllb[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_B_MPLLB_CNTX_CFG(i)); else - pll_state->mpllb[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->mpllb[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_A_MPLLB_CNTX_CFG(i)); } } else { /* MPLLA configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { if (cntx) - pll_state->mplla[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->mplla[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_B_MPLLA_CNTX_CFG(i)); else - pll_state->mplla[i] = intel_c20_sram_read(i915, encoder->port, INTEL_CX0_LANE0, + pll_state->mplla[i] = intel_c20_sram_read(encoder, INTEL_CX0_LANE0, PHY_C20_A_MPLLA_CNTX_CFG(i)); } } @@ -2327,7 +2335,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, const struct intel_crtc_state *crtc_state, struct intel_encoder *encoder) { - const struct intel_c20pll_state *pll_state = &crtc_state->cx0pll_state.c20; + const struct intel_c20pll_state *pll_state = &crtc_state->dpll_hw_state.cx0pll.c20; bool dp = false; int lane = crtc_state->lane_count > 2 ? INTEL_CX0_BOTH_LANES : INTEL_CX0_LANE0; u32 clock = crtc_state->port_clock; @@ -2338,7 +2346,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, dp = true; /* 1. Read current context selection */ - cntx = intel_cx0_read(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0); + cntx = intel_cx0_read(encoder, INTEL_CX0_LANE0, PHY_C20_VDR_CUSTOM_SERDES_RATE) & BIT(0); /* * 2. If there is a protocol switch from HDMI to DP or vice versa, clear @@ -2347,7 +2355,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, */ if (intel_c20_protocol_switch_valid(encoder)) { for (i = 0; i < 4; i++) - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(i), 0); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, RAWLANEAONX_DIG_TX_MPLLB_CAL_DONE_BANK(i), 0); usleep_range(4000, 4100); } @@ -2355,63 +2363,63 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, /* 3.1 Tx configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->tx); i++) { if (cntx) - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_A_TX_CNTX_CFG(i), pll_state->tx[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_TX_CNTX_CFG(i), pll_state->tx[i]); else - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_B_TX_CNTX_CFG(i), pll_state->tx[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_TX_CNTX_CFG(i), pll_state->tx[i]); } /* 3.2 common configuration */ for (i = 0; i < ARRAY_SIZE(pll_state->cmn); i++) { if (cntx) - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_A_CMN_CNTX_CFG(i), pll_state->cmn[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_CMN_CNTX_CFG(i), pll_state->cmn[i]); else - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, PHY_C20_B_CMN_CNTX_CFG(i), pll_state->cmn[i]); + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_CMN_CNTX_CFG(i), pll_state->cmn[i]); } /* 3.3 mpllb or mplla configuration */ if (intel_c20phy_use_mpllb(pll_state)) { for (i = 0; i < ARRAY_SIZE(pll_state->mpllb); i++) { if (cntx) - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_MPLLB_CNTX_CFG(i), pll_state->mpllb[i]); else - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_MPLLB_CNTX_CFG(i), pll_state->mpllb[i]); } } else { for (i = 0; i < ARRAY_SIZE(pll_state->mplla); i++) { if (cntx) - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_A_MPLLA_CNTX_CFG(i), pll_state->mplla[i]); else - intel_c20_sram_write(i915, encoder->port, INTEL_CX0_LANE0, + intel_c20_sram_write(encoder, INTEL_CX0_LANE0, PHY_C20_B_MPLLA_CNTX_CFG(i), pll_state->mplla[i]); } } /* 4. Program custom width to match the link protocol */ - intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_WIDTH, + intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_WIDTH, PHY_C20_CUSTOM_WIDTH_MASK, PHY_C20_CUSTOM_WIDTH(intel_get_c20_custom_width(clock, dp)), MB_WRITE_COMMITTED); /* 5. For DP or 6. For HDMI */ if (dp) { - intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(6) | PHY_C20_CUSTOM_SERDES_MASK, BIT(6) | PHY_C20_CUSTOM_SERDES(intel_c20_get_dp_rate(clock)), MB_WRITE_COMMITTED); } else { - intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(7) | PHY_C20_CUSTOM_SERDES_MASK, is_hdmi_frl(clock) ? BIT(7) : 0, MB_WRITE_COMMITTED); - intel_cx0_write(i915, encoder->port, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, + intel_cx0_write(encoder, INTEL_CX0_BOTH_LANES, PHY_C20_VDR_HDMI_RATE, intel_c20_get_hdmi_rate(clock), MB_WRITE_COMMITTED); } @@ -2420,7 +2428,7 @@ static void intel_c20_pll_program(struct drm_i915_private *i915, * 7. Write Vendor specific registers to toggle context setting to load * the updated programming toggle context bit */ - intel_cx0_rmw(i915, encoder->port, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, + intel_cx0_rmw(encoder, lane, PHY_C20_VDR_CUSTOM_SERDES_RATE, BIT(0), cntx ? 0 : 1, MB_WRITE_COMMITTED); } @@ -2476,9 +2484,9 @@ static void intel_program_port_clock_ctl(struct intel_encoder *encoder, /* TODO: HDMI FRL */ /* DP2.0 10G and 20G rates enable MPLLA*/ if (crtc_state->port_clock == 1000000 || crtc_state->port_clock == 2000000) - val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0; + val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLA : 0; else - val |= crtc_state->cx0pll_state.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0; + val |= crtc_state->dpll_hw_state.cx0pll.ssc_enabled ? XELPDP_SSC_ENABLE_PLLB : 0; intel_de_rmw(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), XELPDP_LANE1_PHY_CLOCK_SELECT | XELPDP_FORWARD_CLOCK_UNGATE | @@ -2508,11 +2516,12 @@ static u32 intel_cx0_get_powerdown_state(u8 lane_mask, u8 state) return val; } -static void intel_cx0_powerdown_change_sequence(struct drm_i915_private *i915, - enum port port, +static void intel_cx0_powerdown_change_sequence(struct intel_encoder *encoder, u8 lane_mask, u8 state) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + enum phy phy = intel_encoder_to_phy(encoder); i915_reg_t buf_ctl2_reg = XELPDP_PORT_BUF_CTL2(i915, port); int lane; @@ -2528,7 +2537,7 @@ static void intel_cx0_powerdown_change_sequence(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "PHY %c Timeout waiting for previous transaction to complete. Reset the bus.\n", phy_name(phy)); - intel_cx0_bus_reset(i915, port, lane); + intel_cx0_bus_reset(encoder, lane); } intel_de_rmw(i915, buf_ctl2_reg, @@ -2536,15 +2545,18 @@ static void intel_cx0_powerdown_change_sequence(struct drm_i915_private *i915, intel_cx0_get_powerdown_update(lane_mask)); /* Update Timeout Value */ - if (__intel_de_wait_for_register(i915, buf_ctl2_reg, - intel_cx0_get_powerdown_update(lane_mask), 0, - XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, buf_ctl2_reg, + intel_cx0_get_powerdown_update(lane_mask), 0, + XELPDP_PORT_POWERDOWN_UPDATE_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n", phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US); } -static void intel_cx0_setup_powerdown(struct drm_i915_private *i915, enum port port) +static void intel_cx0_setup_powerdown(struct intel_encoder *encoder) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum port port = encoder->port; + intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port), XELPDP_POWER_STATE_READY_MASK, XELPDP_POWER_STATE_READY(CX0_P2_STATE_READY)); @@ -2577,13 +2589,13 @@ static u32 intel_cx0_get_pclk_refclk_ack(u8 lane_mask) return val; } -static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, - struct intel_encoder *encoder, +static void intel_cx0_phy_lane_reset(struct intel_encoder *encoder, bool lane_reversal) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; - enum phy phy = intel_port_to_phy(i915, port); - u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder); + enum phy phy = intel_encoder_to_phy(encoder); + u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); u8 lane_mask = lane_reversal ? INTEL_CX0_LANE1 : INTEL_CX0_LANE0; u32 lane_pipe_reset = owned_lane_mask == INTEL_CX0_BOTH_LANES ? XELPDP_LANE_PIPE_RESET(0) | XELPDP_LANE_PIPE_RESET(1) @@ -2593,19 +2605,19 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, XELPDP_LANE_PHY_CURRENT_STATUS(1)) : XELPDP_LANE_PHY_CURRENT_STATUS(0); - if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL1(i915, port), - XELPDP_PORT_BUF_SOC_PHY_READY, - XELPDP_PORT_BUF_SOC_PHY_READY, - XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_BUF_CTL1(i915, port), + XELPDP_PORT_BUF_SOC_PHY_READY, + XELPDP_PORT_BUF_SOC_PHY_READY, + XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "PHY %c failed to bring out of SOC reset after %dus.\n", phy_name(phy), XELPDP_PORT_BUF_SOC_READY_TIMEOUT_US); intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port), lane_pipe_reset, lane_pipe_reset); - if (__intel_de_wait_for_register(i915, XELPDP_PORT_BUF_CTL2(i915, port), - lane_phy_current_status, lane_phy_current_status, - XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_BUF_CTL2(i915, port), + lane_phy_current_status, lane_phy_current_status, + XELPDP_PORT_RESET_START_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "PHY %c failed to bring out of Lane reset after %dus.\n", phy_name(phy), XELPDP_PORT_RESET_START_TIMEOUT_US); @@ -2613,16 +2625,16 @@ static void intel_cx0_phy_lane_reset(struct drm_i915_private *i915, intel_cx0_get_pclk_refclk_request(owned_lane_mask), intel_cx0_get_pclk_refclk_request(lane_mask)); - if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(i915, port), - intel_cx0_get_pclk_refclk_ack(owned_lane_mask), - intel_cx0_get_pclk_refclk_ack(lane_mask), - XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, port), + intel_cx0_get_pclk_refclk_ack(owned_lane_mask), + intel_cx0_get_pclk_refclk_ack(lane_mask), + XELPDP_REFCLK_ENABLE_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "PHY %c failed to request refclk after %dus.\n", phy_name(phy), XELPDP_REFCLK_ENABLE_TIMEOUT_US); - intel_cx0_powerdown_change_sequence(i915, port, INTEL_CX0_BOTH_LANES, + intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, CX0_P2_STATE_RESET); - intel_cx0_setup_powerdown(i915, port); + intel_cx0_setup_powerdown(encoder); intel_de_rmw(i915, XELPDP_PORT_BUF_CTL2(i915, port), lane_pipe_reset, 0); @@ -2640,11 +2652,10 @@ static void intel_cx0_program_phy_lane(struct drm_i915_private *i915, int i; u8 disables; bool dp_alt_mode = intel_tc_port_in_dp_alt_mode(enc_to_dig_port(encoder)); - u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(i915, encoder); - enum port port = encoder->port; + u8 owned_lane_mask = intel_cx0_get_owned_lane_mask(encoder); - if (intel_is_c10phy(i915, intel_port_to_phy(i915, port))) - intel_cx0_rmw(i915, port, owned_lane_mask, + if (intel_encoder_is_c10phy(encoder)) + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_MSGBUS_ACCESS, MB_WRITE_COMMITTED); @@ -2666,14 +2677,14 @@ static void intel_cx0_program_phy_lane(struct drm_i915_private *i915, if (!(owned_lane_mask & lane_mask)) continue; - intel_cx0_rmw(i915, port, lane_mask, PHY_CX0_TX_CONTROL(tx, 2), + intel_cx0_rmw(encoder, lane_mask, PHY_CX0_TX_CONTROL(tx, 2), CONTROL2_DISABLE_SINGLE_TX, disables & BIT(i) ? CONTROL2_DISABLE_SINGLE_TX : 0, MB_WRITE_COMMITTED); } - if (intel_is_c10phy(i915, intel_port_to_phy(i915, port))) - intel_cx0_rmw(i915, port, owned_lane_mask, + if (intel_encoder_is_c10phy(encoder)) + intel_cx0_rmw(encoder, owned_lane_mask, PHY_C10_VDR_CONTROL(1), 0, C10_VDR_CTRL_UPDATE_CFG, MB_WRITE_COMMITTED); @@ -2705,7 +2716,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; u8 maxpclk_lane = lane_reversal ? INTEL_CX0_LANE1 : @@ -2719,13 +2730,13 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, intel_program_port_clock_ctl(encoder, crtc_state, lane_reversal); /* 2. Bring PHY out of reset. */ - intel_cx0_phy_lane_reset(i915, encoder, lane_reversal); + intel_cx0_phy_lane_reset(encoder, lane_reversal); /* * 3. Change Phy power state to Ready. * TODO: For DP alt mode use only one lane. */ - intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES, + intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, CX0_P2_STATE_READY); /* @@ -2735,7 +2746,7 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, */ /* 5. Program PHY internal PLL internal registers. */ - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) intel_c10_pll_program(i915, crtc_state, encoder); else intel_c20_pll_program(i915, crtc_state, encoder); @@ -2767,10 +2778,10 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, intel_cx0_get_pclk_pll_request(maxpclk_lane)); /* 10. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN == "1". */ - if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), - intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES), - intel_cx0_get_pclk_pll_ack(maxpclk_lane), - XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), + intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES), + intel_cx0_get_pclk_pll_ack(maxpclk_lane), + XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "Port %c PLL not locked after %dus.\n", phy_name(phy), XELPDP_PCLK_PLL_ENABLE_TIMEOUT_US); @@ -2831,7 +2842,7 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); u32 val = 0; /* @@ -2858,10 +2869,10 @@ static void intel_mtl_tbt_pll_enable(struct intel_encoder *encoder, intel_de_write(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), val); /* 5. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "1". */ - if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), - XELPDP_TBT_CLOCK_ACK, - XELPDP_TBT_CLOCK_ACK, - 100, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), + XELPDP_TBT_CLOCK_ACK, + XELPDP_TBT_CLOCK_ACK, + 100, 0, NULL)) drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not locked after 100us.\n", encoder->base.base.id, encoder->base.name, phy_name(phy)); @@ -2892,12 +2903,12 @@ void intel_mtl_pll_enable(struct intel_encoder *encoder, static void intel_cx0pll_disable(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - bool is_c10 = intel_is_c10phy(i915, phy); + enum phy phy = intel_encoder_to_phy(encoder); + bool is_c10 = intel_encoder_is_c10phy(encoder); intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder); /* 1. Change owned PHY lane power to Disable state. */ - intel_cx0_powerdown_change_sequence(i915, encoder->port, INTEL_CX0_BOTH_LANES, + intel_cx0_powerdown_change_sequence(encoder, INTEL_CX0_BOTH_LANES, is_c10 ? CX0_P2PG_STATE_DISABLE : CX0_P4PG_STATE_DISABLE); @@ -2920,10 +2931,10 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder) /* * 5. Poll on PORT_CLOCK_CTL PCLK PLL Ack LN == "0". */ - if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), - intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) | - intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0, - XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), + intel_cx0_get_pclk_pll_ack(INTEL_CX0_BOTH_LANES) | + intel_cx0_get_pclk_refclk_ack(INTEL_CX0_BOTH_LANES), 0, + XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US, 0, NULL)) drm_warn(&i915->drm, "Port %c PLL not unlocked after %dus.\n", phy_name(phy), XELPDP_PCLK_PLL_DISABLE_TIMEOUT_US); @@ -2944,7 +2955,7 @@ static void intel_cx0pll_disable(struct intel_encoder *encoder) static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); /* * 1. Follow the Display Voltage Frequency Switching Sequence Before @@ -2958,8 +2969,8 @@ static void intel_mtl_tbt_pll_disable(struct intel_encoder *encoder) XELPDP_TBT_CLOCK_REQUEST, 0); /* 3. Poll on PORT_CLOCK_CTL TBT CLOCK Ack == "0". */ - if (__intel_de_wait_for_register(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), - XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL)) + if (intel_de_wait_custom(i915, XELPDP_PORT_CLOCK_CTL(i915, encoder->port), + XELPDP_TBT_CLOCK_ACK, 0, 10, 0, NULL)) drm_warn(&i915->drm, "[ENCODER:%d:%s][%c] PHY PLL not unlocked after 10us.\n", encoder->base.base.id, encoder->base.name, phy_name(phy)); @@ -3014,7 +3025,7 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, struct intel_c10pll_state *mpllb_hw_state) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - const struct intel_c10pll_state *mpllb_sw_state = &state->cx0pll_state.c10; + const struct intel_c10pll_state *mpllb_sw_state = &state->dpll_hw_state.cx0pll.c10; int i; if (intel_crtc_needs_fastset(state)) @@ -3043,10 +3054,7 @@ static void intel_c10pll_state_verify(const struct intel_crtc_state *state, void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, struct intel_cx0pll_state *pll_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) intel_c10pll_readout_hw_state(encoder, &pll_state->c10); else intel_c20pll_readout_hw_state(encoder, &pll_state->c20); @@ -3055,10 +3063,7 @@ void intel_cx0pll_readout_hw_state(struct intel_encoder *encoder, int intel_cx0pll_calc_port_clock(struct intel_encoder *encoder, const struct intel_cx0pll_state *pll_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) return intel_c10pll_calc_port_clock(encoder, &pll_state->c10); return intel_c20pll_calc_port_clock(encoder, &pll_state->c20); @@ -3070,7 +3075,7 @@ static void intel_c20pll_state_verify(const struct intel_crtc_state *state, struct intel_c20pll_state *mpll_hw_state) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - const struct intel_c20pll_state *mpll_sw_state = &state->cx0pll_state.c20; + const struct intel_c20pll_state *mpll_sw_state = &state->dpll_hw_state.cx0pll.c20; bool sw_use_mpllb = intel_c20phy_use_mpllb(mpll_sw_state); bool hw_use_mpllb = intel_c20phy_use_mpllb(mpll_hw_state); int i; @@ -3124,7 +3129,6 @@ void intel_cx0pll_state_verify(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct intel_encoder *encoder; struct intel_cx0pll_state mpll_hw_state = {}; - enum phy phy; if (DISPLAY_VER(i915) < 14) return; @@ -3138,14 +3142,13 @@ void intel_cx0pll_state_verify(struct intel_atomic_state *state, return; encoder = intel_get_crtc_new_encoder(state, new_crtc_state); - phy = intel_port_to_phy(i915, encoder->port); if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder))) return; intel_cx0pll_readout_hw_state(encoder, &mpll_hw_state); - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) intel_c10pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c10); else intel_c20pll_state_verify(new_crtc_state, crtc, encoder, &mpll_hw_state.c20); diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.h b/drivers/gpu/drm/i915/display/intel_cx0_phy.h index c6682677253a..3e03af3e006c 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.h +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.h @@ -11,7 +11,6 @@ #include enum icl_port_dpll_id; -enum phy; struct drm_i915_private; struct intel_atomic_state; struct intel_c10pll_state; @@ -22,7 +21,7 @@ struct intel_crtc_state; struct intel_encoder; struct intel_hdmi; -bool intel_is_c10phy(struct drm_i915_private *dev_priv, enum phy phy); +bool intel_encoder_is_c10phy(struct intel_encoder *encoder); void intel_mtl_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); void intel_mtl_pll_disable(struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c587a8efeafc..3c3fc53376ce 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -200,10 +200,10 @@ void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, port_name(port)); } -static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, - enum port port) +static void intel_wait_ddi_buf_active(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(dev_priv, port); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = encoder->port; int timeout_us; int ret; @@ -218,7 +218,7 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, } else if (IS_DG2(dev_priv)) { timeout_us = 1200; } else if (DISPLAY_VER(dev_priv) >= 12) { - if (intel_phy_is_tc(dev_priv, phy)) + if (intel_encoder_is_tc(encoder)) timeout_us = 3000; else timeout_us = 1000; @@ -331,7 +331,6 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - enum phy phy = intel_port_to_phy(i915, encoder->port); /* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */ intel_dp->DP = dig_port->saved_port_bits | @@ -345,7 +344,7 @@ static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder, intel_dp->DP |= DDI_BUF_PORT_DATA_10BIT; } - if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) { + if (IS_ALDERLAKE_P(i915) && intel_encoder_is_tc(encoder)) { intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock); if (!intel_tc_port_in_tbt_alt_mode(dig_port)) intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; @@ -632,6 +631,7 @@ intel_ddi_config_transcoder_func(struct intel_encoder *encoder, void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; @@ -662,10 +662,9 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl); - if (intel_has_quirk(dev_priv, QUIRK_INCREASE_DDI_DISABLED_TIME) && + if (intel_has_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { - drm_dbg_kms(&dev_priv->drm, - "Quirk Increase DDI disabled time\n"); + drm_dbg_kms(display->drm, "Quirk Increase DDI disabled time\n"); /* Quirk time at 100ms for reliable operation */ msleep(100); } @@ -895,7 +894,6 @@ intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); /* * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with @@ -914,7 +912,7 @@ intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port, return intel_display_power_aux_io_domain(i915, dig_port->aux_ch); else if (DISPLAY_VER(i915) < 14 && (intel_crtc_has_dp_encoder(crtc_state) || - intel_phy_is_tc(i915, phy))) + intel_encoder_is_tc(&dig_port->base))) return intel_aux_power_domain(dig_port); else return POWER_DOMAIN_INVALID; @@ -984,7 +982,7 @@ void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder, struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); u32 val; if (cpu_transcoder == TRANSCODER_EDP) @@ -1113,7 +1111,7 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct intel_ddi_buf_trans *trans; - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); int n_entries, ln; u32 val; @@ -1176,7 +1174,7 @@ static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); u32 val; int ln; @@ -1227,7 +1225,7 @@ static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); const struct intel_ddi_buf_trans *trans; int n_entries, ln; @@ -1328,7 +1326,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); const struct intel_ddi_buf_trans *trans; int n_entries, ln; @@ -1526,7 +1524,7 @@ static void adls_ddi_enable_clock(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_shared_dpll *pll = crtc_state->shared_dpll; - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(&i915->drm, !pll)) return; @@ -1540,7 +1538,7 @@ static void adls_ddi_enable_clock(struct intel_encoder *encoder, static void adls_ddi_disable_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); _icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy), ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1549,7 +1547,7 @@ static void adls_ddi_disable_clock(struct intel_encoder *encoder) static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy), ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1558,7 +1556,7 @@ static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder) static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy), ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy), @@ -1570,7 +1568,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_shared_dpll *pll = crtc_state->shared_dpll; - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(&i915->drm, !pll)) return; @@ -1584,7 +1582,7 @@ static void rkl_ddi_enable_clock(struct intel_encoder *encoder, static void rkl_ddi_disable_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0, RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1593,7 +1591,7 @@ static void rkl_ddi_disable_clock(struct intel_encoder *encoder) static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0, RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1602,7 +1600,7 @@ static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder) static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0, RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy), @@ -1614,7 +1612,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_shared_dpll *pll = crtc_state->shared_dpll; - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(&i915->drm, !pll)) return; @@ -1637,7 +1635,7 @@ static void dg1_ddi_enable_clock(struct intel_encoder *encoder, static void dg1_ddi_disable_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); _icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy), DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1646,7 +1644,7 @@ static void dg1_ddi_disable_clock(struct intel_encoder *encoder) static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy), DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1655,7 +1653,7 @@ static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder) static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); enum intel_dpll_id id; u32 val; @@ -1680,7 +1678,7 @@ static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_shared_dpll *pll = crtc_state->shared_dpll; - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); if (drm_WARN_ON(&i915->drm, !pll)) return; @@ -1694,7 +1692,7 @@ static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder, static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0, ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1703,7 +1701,7 @@ static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder) static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0, ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy)); @@ -1712,7 +1710,7 @@ static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder) struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0, ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy), @@ -1767,7 +1765,7 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); const struct intel_shared_dpll *pll = crtc_state->shared_dpll; - enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; if (drm_WARN_ON(&i915->drm, !pll)) @@ -1787,7 +1785,7 @@ static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder, static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; mutex_lock(&i915->display.dpll.lock); @@ -1803,7 +1801,7 @@ static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder) static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; u32 tmp; @@ -1820,7 +1818,7 @@ static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder) static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); enum port port = encoder->port; enum intel_dpll_id id; u32 tmp; @@ -2086,12 +2084,11 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port); - enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); + enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); u32 ln0, ln1, pin_assignment; u8 width; - if (!intel_phy_is_tc(dev_priv, phy) || + if (!intel_encoder_is_tc(&dig_port->base) || intel_tc_port_in_tbt_alt_mode(dig_port)) return; @@ -2327,9 +2324,9 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - enum phy phy = intel_port_to_phy(i915, encoder->port); - if (intel_phy_is_combo(i915, phy)) { + if (intel_encoder_is_combo(encoder)) { + enum phy phy = intel_encoder_to_phy(encoder); bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; @@ -2339,10 +2336,15 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder, } } -/* Splitter enable for eDP MSO is limited to certain pipes. */ +/* + * Splitter enable for eDP MSO is limited to certain pipes, on certain + * platforms. + */ static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915) { - if (IS_ALDERLAKE_P(i915)) + if (DISPLAY_VER(i915) > 20) + return ~0; + else if (IS_ALDERLAKE_P(i915)) return BIT(PIPE_A) | BIT(PIPE_B); else return BIT(PIPE_A); @@ -2812,15 +2814,14 @@ static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state, const struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - if (HAS_DP20(dev_priv)) { + if (HAS_DP20(dev_priv)) intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder), crtc_state); - if (crtc_state->has_panel_replay) - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, - DP_PANEL_REPLAY_ENABLE); - } + + /* Panel replay has to be enabled in sink dpcd before link training. */ + if (crtc_state->has_panel_replay) + intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state); if (DISPLAY_VER(dev_priv) >= 14) mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); @@ -3095,39 +3096,48 @@ static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state, intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); } +static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, + struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_crtc *pipe_crtc; + + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); + + intel_crtc_vblank_off(old_pipe_crtc_state); + } + + intel_disable_transcoder(old_crtc_state); + + intel_ddi_disable_transcoder_func(old_crtc_state); + + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); + + intel_dsc_disable(old_pipe_crtc_state); + + if (DISPLAY_VER(dev_priv) >= 9) + skl_scaler_disable(old_pipe_crtc_state); + else + ilk_pfit_disable(old_pipe_crtc_state); + } +} + static void intel_ddi_post_disable(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *slave_crtc; - - if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) { - intel_crtc_vblank_off(old_crtc_state); - - intel_disable_transcoder(old_crtc_state); - - intel_ddi_disable_transcoder_func(old_crtc_state); - - intel_dsc_disable(old_crtc_state); - - if (DISPLAY_VER(dev_priv) >= 9) - skl_scaler_disable(old_crtc_state); - else - ilk_pfit_disable(old_crtc_state); - } - - for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) { - const struct intel_crtc_state *old_slave_crtc_state = - intel_atomic_get_old_crtc_state(state, slave_crtc); - - intel_crtc_vblank_off(old_slave_crtc_state); - - intel_dsc_disable(old_slave_crtc_state); - skl_scaler_disable(old_slave_crtc_state); - } + if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) + intel_ddi_post_disable_hdmi_or_sst(state, encoder, old_crtc_state, + old_conn_state); /* * When called from DP MST code: @@ -3155,14 +3165,11 @@ static void intel_ddi_post_pll_disable(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - enum phy phy = intel_port_to_phy(i915, encoder->port); - bool is_tc_port = intel_phy_is_tc(i915, phy); main_link_aux_power_domain_put(dig_port, old_crtc_state); - if (is_tc_port) + if (intel_encoder_is_tc(encoder)) intel_tc_port_put_link(dig_port); } @@ -3263,7 +3270,6 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_connector *connector = conn_state->connector; enum port port = encoder->port; - enum phy phy = intel_port_to_phy(dev_priv, port); u32 buf_ctl; if (!intel_hdmi_handle_sink_scrambling(encoder, connector, @@ -3347,14 +3353,14 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, if (DISPLAY_VER(dev_priv) >= 20) buf_ctl |= XE2LPD_DDI_BUF_D2D_LINK_ENABLE; - } else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) { + } else if (IS_ALDERLAKE_P(dev_priv) && intel_encoder_is_tc(encoder)) { drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port)); buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; } intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl); - intel_wait_ddi_buf_active(dev_priv, port); + intel_wait_ddi_buf_active(encoder); } static void intel_enable_ddi(struct intel_atomic_state *state, @@ -3362,10 +3368,10 @@ static void intel_enable_ddi(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *pipe_crtc; - if (!intel_crtc_is_bigjoiner_slave(crtc_state)) - intel_ddi_enable_transcoder_func(encoder, crtc_state); + intel_ddi_enable_transcoder_func(encoder, crtc_state); /* Enable/Disable DP2.0 SDP split config before transcoder */ intel_audio_sdp_split_update(crtc_state); @@ -3374,7 +3380,13 @@ static void intel_enable_ddi(struct intel_atomic_state *state, intel_ddi_wait_for_fec_status(encoder, crtc_state, true); - intel_crtc_vblank_on(crtc_state); + for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); + + intel_crtc_vblank_on(pipe_crtc_state); + } if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state); @@ -3470,19 +3482,17 @@ void intel_ddi_update_active_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_crtc_state *crtc_state = + const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_crtc *slave_crtc; - enum phy phy = intel_port_to_phy(i915, encoder->port); + struct intel_crtc *pipe_crtc; /* FIXME: Add MTL pll_mgr */ - if (DISPLAY_VER(i915) >= 14 || !intel_phy_is_tc(i915, phy)) + if (DISPLAY_VER(i915) >= 14 || !intel_encoder_is_tc(encoder)) return; - intel_update_active_dpll(state, crtc, encoder); - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(crtc_state)) - intel_update_active_dpll(state, slave_crtc, encoder); + for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(crtc_state)) + intel_update_active_dpll(state, pipe_crtc, encoder); } static void @@ -3493,8 +3503,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); - bool is_tc_port = intel_phy_is_tc(dev_priv, phy); + bool is_tc_port = intel_encoder_is_tc(encoder); if (is_tc_port) { struct intel_crtc *master_crtc = @@ -3513,14 +3522,14 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, */ intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count); else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - bxt_ddi_phy_set_lane_optim_mask(encoder, - crtc_state->lane_lat_optim_mask); + bxt_dpio_phy_set_lane_optim_mask(encoder, + crtc_state->lane_lat_optim_mask); } static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum tc_port tc_port = intel_port_to_tc(i915, encoder->port); + enum tc_port tc_port = intel_encoder_to_tc(encoder); int ln; for (ln = 0; ln < 2; ln++) @@ -3574,7 +3583,7 @@ static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp, intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); /* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */ - intel_wait_ddi_buf_active(dev_priv, port); + intel_wait_ddi_buf_active(encoder); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, @@ -3624,7 +3633,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); - intel_wait_ddi_buf_active(dev_priv, port); + intel_wait_ddi_buf_active(encoder); } static void intel_ddi_set_link_train(struct intel_dp *intel_dp, @@ -3681,7 +3690,7 @@ static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp, if (intel_de_wait_for_set(dev_priv, dp_tp_status_reg(encoder, crtc_state), - DP_TP_STATUS_IDLE_DONE, 1)) + DP_TP_STATUS_IDLE_DONE, 2)) drm_err(&dev_priv->drm, "Timed out waiting for DP idle patterns\n"); } @@ -3946,7 +3955,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = - bxt_ddi_phy_get_lane_lat_optim_mask(encoder); + bxt_dpio_phy_get_lane_lat_optim_mask(encoder); intel_ddi_compute_min_voltage_level(pipe_config); @@ -3972,6 +3981,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); + intel_read_dp_sdp(encoder, pipe_config, DP_SDP_ADAPTIVE_SYNC); intel_audio_codec_get_config(encoder, pipe_config); } @@ -4006,8 +4016,8 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder, if (intel_tc_port_in_tbt_alt_mode(dig_port)) { crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); } else { - intel_cx0pll_readout_hw_state(encoder, &crtc_state->cx0pll_state); - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->cx0pll_state); + intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll); + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); } intel_ddi_get_config(encoder, crtc_state); @@ -4016,8 +4026,8 @@ static void mtl_ddi_get_config(struct intel_encoder *encoder, static void dg2_ddi_get_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { - intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state); - crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state); + intel_mpllb_readout_hw_state(encoder, &crtc_state->dpll_hw_state.mpllb); + crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->dpll_hw_state.mpllb); intel_ddi_get_config(encoder, crtc_state); } @@ -4144,10 +4154,7 @@ void hsw_ddi_get_config(struct intel_encoder *encoder, static void intel_ddi_sync_state(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_phy_is_tc(i915, phy)) + if (intel_encoder_is_tc(encoder)) intel_tc_port_sanitize_mode(enc_to_dig_port(encoder), crtc_state); @@ -4159,10 +4166,9 @@ static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); bool fastset = true; - if (intel_phy_is_tc(i915, phy)) { + if (intel_encoder_is_tc(encoder)) { drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n", encoder->base.base.id, encoder->base.name); crtc_state->uapi.mode_changed = true; @@ -4226,7 +4232,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder, if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = - bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); + bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); intel_ddi_compute_min_voltage_level(pipe_config); @@ -4256,7 +4262,12 @@ static bool m_n_equal(const struct intel_link_m_n *m_n_1, static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1, const struct intel_crtc_state *crtc_state2) { + /* + * FIXME the modeset sequence is currently wrong and + * can't deal with bigjoiner + port sync at the same time. + */ return crtc_state1->hw.active && crtc_state2->hw.active && + !crtc_state1->bigjoiner_pipes && !crtc_state2->bigjoiner_pipes && crtc_state1->output_types == crtc_state2->output_types && crtc_state1->output_format == crtc_state2->output_format && crtc_state1->lane_count == crtc_state2->lane_count && @@ -4348,10 +4359,9 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->dev); struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); intel_dp_encoder_flush_work(encoder); - if (intel_phy_is_tc(i915, phy)) + if (intel_encoder_is_tc(&dig_port->base)) intel_tc_port_cleanup(dig_port); intel_display_power_flush_work(i915); @@ -4362,16 +4372,14 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) static void intel_ddi_encoder_reset(struct drm_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(encoder->dev); struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); intel_dp->reset_link_params = true; intel_pps_encoder_reset(intel_dp); - if (intel_phy_is_tc(i915, phy)) + if (intel_encoder_is_tc(&dig_port->base)) intel_tc_port_init_mode(dig_port); } @@ -4538,11 +4546,9 @@ static enum intel_hotplug_state intel_ddi_hotplug(struct intel_encoder *encoder, struct intel_connector *connector) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct intel_dp *intel_dp = &dig_port->dp; - enum phy phy = intel_port_to_phy(i915, encoder->port); - bool is_tc = intel_phy_is_tc(i915, phy); + bool is_tc = intel_encoder_is_tc(encoder); struct drm_modeset_acquire_ctx ctx; enum intel_hotplug_state state; int ret; @@ -4824,10 +4830,7 @@ static bool port_strap_detected(struct drm_i915_private *i915, enum port port) static bool need_aux_ch(struct intel_encoder *encoder, bool init_dp) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - return init_dp || intel_phy_is_tc(i915, phy); + return init_dp || intel_encoder_is_tc(encoder); } static bool assert_has_icl_dsi(struct drm_i915_private *i915) @@ -5071,17 +5074,17 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, } else if (IS_DG2(dev_priv)) { encoder->set_signal_levels = intel_snps_phy_set_signal_levels; } else if (DISPLAY_VER(dev_priv) >= 12) { - if (intel_phy_is_combo(dev_priv, phy)) + if (intel_encoder_is_combo(encoder)) encoder->set_signal_levels = icl_combo_phy_set_signal_levels; else encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels; } else if (DISPLAY_VER(dev_priv) >= 11) { - if (intel_phy_is_combo(dev_priv, phy)) + if (intel_encoder_is_combo(encoder)) encoder->set_signal_levels = icl_combo_phy_set_signal_levels; else encoder->set_signal_levels = icl_mg_phy_set_signal_levels; } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { - encoder->set_signal_levels = bxt_ddi_phy_set_signal_levels; + encoder->set_signal_levels = bxt_dpio_phy_set_signal_levels; } else { encoder->set_signal_levels = hsw_set_signal_levels; } @@ -5126,7 +5129,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, goto err; } - if (intel_phy_is_tc(dev_priv, phy)) { + if (intel_encoder_is_tc(encoder)) { bool is_legacy = !intel_bios_encoder_supports_typec_usb(devdata) && !intel_bios_encoder_supports_tbt(devdata); @@ -5155,7 +5158,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port); if (DISPLAY_VER(dev_priv) >= 11) { - if (intel_phy_is_tc(dev_priv, phy)) + if (intel_encoder_is_tc(encoder)) dig_port->connected = intel_tc_port_connected; else dig_port->connected = lpt_digital_port_connected; diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index de809e2d9cac..4d21ce734343 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1691,14 +1691,11 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, int *n_entries) { - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - if (intel_crtc_has_dp_encoder(crtc_state) && crtc_state->port_clock >= 1000000) return intel_get_buf_trans(&mtl_c20_trans_uhbr, n_entries); - else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_is_c10phy(i915, phy))) + else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && !(intel_encoder_is_c10phy(encoder))) return intel_get_buf_trans(&mtl_c20_trans_hdmi, n_entries); - else if (!intel_is_c10phy(i915, phy)) + else if (!intel_encoder_is_c10phy(encoder)) return intel_get_buf_trans(&mtl_c20_trans_dp14, n_entries); else return intel_get_buf_trans(&mtl_c10_trans_dp14, n_entries); @@ -1707,14 +1704,13 @@ mtl_get_cx0_buf_trans(struct intel_encoder *encoder, void intel_ddi_buf_trans_init(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); if (DISPLAY_VER(i915) >= 14) { encoder->get_buf_trans = mtl_get_cx0_buf_trans; } else if (IS_DG2(i915)) { encoder->get_buf_trans = dg2_get_snps_buf_trans; } else if (IS_ALDERLAKE_P(i915)) { - if (intel_phy_is_combo(i915, phy)) + if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = adlp_get_combo_buf_trans; else encoder->get_buf_trans = adlp_get_dkl_buf_trans; @@ -1725,16 +1721,16 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) } else if (IS_DG1(i915)) { encoder->get_buf_trans = dg1_get_combo_buf_trans; } else if (DISPLAY_VER(i915) >= 12) { - if (intel_phy_is_combo(i915, phy)) + if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = tgl_get_combo_buf_trans; else encoder->get_buf_trans = tgl_get_dkl_buf_trans; } else if (DISPLAY_VER(i915) == 11) { - if (IS_PLATFORM(i915, INTEL_JASPERLAKE)) + if (IS_JASPERLAKE(i915)) encoder->get_buf_trans = jsl_get_combo_buf_trans; - else if (IS_PLATFORM(i915, INTEL_ELKHARTLAKE)) + else if (IS_ELKHARTLAKE(i915)) encoder->get_buf_trans = ehl_get_combo_buf_trans; - else if (intel_phy_is_combo(i915, phy)) + else if (intel_encoder_is_combo(encoder)) encoder->get_buf_trans = icl_get_combo_buf_trans; else encoder->get_buf_trans = icl_get_mg_buf_trans; diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h index 42552d8c151e..e881bfeafb47 100644 --- a/drivers/gpu/drm/i915/display/intel_de.h +++ b/drivers/gpu/drm/i915/display/intel_de.h @@ -10,80 +10,185 @@ #include "i915_trace.h" #include "intel_uncore.h" -static inline u32 -intel_de_read(struct drm_i915_private *i915, i915_reg_t reg) +static inline struct intel_uncore *__to_uncore(struct intel_display *display) { - return intel_uncore_read(&i915->uncore, reg); + return &to_i915(display->drm)->uncore; } +static inline u32 +__intel_de_read(struct intel_display *display, i915_reg_t reg) +{ + u32 val; + + intel_dmc_wl_get(display, reg); + + val = intel_uncore_read(__to_uncore(display), reg); + + intel_dmc_wl_put(display, reg); + + return val; +} +#define intel_de_read(p,...) __intel_de_read(__to_intel_display(p), __VA_ARGS__) + static inline u8 -intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg) +__intel_de_read8(struct intel_display *display, i915_reg_t reg) { - return intel_uncore_read8(&i915->uncore, reg); + u8 val; + + intel_dmc_wl_get(display, reg); + + val = intel_uncore_read8(__to_uncore(display), reg); + + intel_dmc_wl_put(display, reg); + + return val; } +#define intel_de_read8(p,...) __intel_de_read8(__to_intel_display(p), __VA_ARGS__) static inline u64 -intel_de_read64_2x32(struct drm_i915_private *i915, - i915_reg_t lower_reg, i915_reg_t upper_reg) +__intel_de_read64_2x32(struct intel_display *display, + i915_reg_t lower_reg, i915_reg_t upper_reg) { - return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg); + u64 val; + + intel_dmc_wl_get(display, lower_reg); + intel_dmc_wl_get(display, upper_reg); + + val = intel_uncore_read64_2x32(__to_uncore(display), lower_reg, + upper_reg); + + intel_dmc_wl_put(display, upper_reg); + intel_dmc_wl_put(display, lower_reg); + + return val; } +#define intel_de_read64_2x32(p,...) __intel_de_read64_2x32(__to_intel_display(p), __VA_ARGS__) static inline void -intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg) +__intel_de_posting_read(struct intel_display *display, i915_reg_t reg) { - intel_uncore_posting_read(&i915->uncore, reg); + intel_dmc_wl_get(display, reg); + + intel_uncore_posting_read(__to_uncore(display), reg); + + intel_dmc_wl_put(display, reg); } +#define intel_de_posting_read(p,...) __intel_de_posting_read(__to_intel_display(p), __VA_ARGS__) static inline void -intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val) +__intel_de_write(struct intel_display *display, i915_reg_t reg, u32 val) { - intel_uncore_write(&i915->uncore, reg, val); + intel_dmc_wl_get(display, reg); + + intel_uncore_write(__to_uncore(display), reg, val); + + intel_dmc_wl_put(display, reg); } +#define intel_de_write(p,...) __intel_de_write(__to_intel_display(p), __VA_ARGS__) static inline u32 -intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set) +____intel_de_rmw_nowl(struct intel_display *display, i915_reg_t reg, + u32 clear, u32 set) { - return intel_uncore_rmw(&i915->uncore, reg, clear, set); + return intel_uncore_rmw(__to_uncore(display), reg, clear, set); } +#define __intel_de_rmw_nowl(p,...) ____intel_de_rmw_nowl(__to_intel_display(p), __VA_ARGS__) + +static inline u32 +__intel_de_rmw(struct intel_display *display, i915_reg_t reg, u32 clear, + u32 set) +{ + u32 val; + + intel_dmc_wl_get(display, reg); + + val = __intel_de_rmw_nowl(display, reg, clear, set); + + intel_dmc_wl_put(display, reg); + + return val; +} +#define intel_de_rmw(p,...) __intel_de_rmw(__to_intel_display(p), __VA_ARGS__) static inline int -intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout) +____intel_de_wait_for_register_nowl(struct intel_display *display, + i915_reg_t reg, + u32 mask, u32 value, unsigned int timeout) { - return intel_wait_for_register(&i915->uncore, reg, mask, value, timeout); + return intel_wait_for_register(__to_uncore(display), reg, mask, + value, timeout); } +#define __intel_de_wait_for_register_nowl(p,...) ____intel_de_wait_for_register_nowl(__to_intel_display(p), __VA_ARGS__) static inline int -intel_de_wait_for_register_fw(struct drm_i915_private *i915, i915_reg_t reg, - u32 mask, u32 value, unsigned int timeout) +__intel_de_wait(struct intel_display *display, i915_reg_t reg, + u32 mask, u32 value, unsigned int timeout) { - return intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout); + int ret; + + intel_dmc_wl_get(display, reg); + + ret = __intel_de_wait_for_register_nowl(display, reg, mask, value, + timeout); + + intel_dmc_wl_put(display, reg); + + return ret; } +#define intel_de_wait(p,...) __intel_de_wait(__to_intel_display(p), __VA_ARGS__) static inline int -__intel_de_wait_for_register(struct drm_i915_private *i915, i915_reg_t reg, - u32 mask, u32 value, - unsigned int fast_timeout_us, - unsigned int slow_timeout_ms, u32 *out_value) +__intel_de_wait_fw(struct intel_display *display, i915_reg_t reg, + u32 mask, u32 value, unsigned int timeout) { - return __intel_wait_for_register(&i915->uncore, reg, mask, value, - fast_timeout_us, slow_timeout_ms, out_value); + int ret; + + intel_dmc_wl_get(display, reg); + + ret = intel_wait_for_register_fw(__to_uncore(display), reg, mask, + value, timeout); + + intel_dmc_wl_put(display, reg); + + return ret; } +#define intel_de_wait_fw(p,...) __intel_de_wait_fw(__to_intel_display(p), __VA_ARGS__) static inline int -intel_de_wait_for_set(struct drm_i915_private *i915, i915_reg_t reg, - u32 mask, unsigned int timeout) +__intel_de_wait_custom(struct intel_display *display, i915_reg_t reg, + u32 mask, u32 value, + unsigned int fast_timeout_us, + unsigned int slow_timeout_ms, u32 *out_value) { - return intel_de_wait_for_register(i915, reg, mask, mask, timeout); + int ret; + + intel_dmc_wl_get(display, reg); + + ret = __intel_wait_for_register(__to_uncore(display), reg, mask, + value, + fast_timeout_us, slow_timeout_ms, out_value); + + intel_dmc_wl_put(display, reg); + + return ret; } +#define intel_de_wait_custom(p,...) __intel_de_wait_custom(__to_intel_display(p), __VA_ARGS__) static inline int -intel_de_wait_for_clear(struct drm_i915_private *i915, i915_reg_t reg, +__intel_de_wait_for_set(struct intel_display *display, i915_reg_t reg, u32 mask, unsigned int timeout) { - return intel_de_wait_for_register(i915, reg, mask, 0, timeout); + return intel_de_wait(display, reg, mask, mask, timeout); } +#define intel_de_wait_for_set(p,...) __intel_de_wait_for_set(__to_intel_display(p), __VA_ARGS__) + +static inline int +__intel_de_wait_for_clear(struct intel_display *display, i915_reg_t reg, + u32 mask, unsigned int timeout) +{ + return intel_de_wait(display, reg, mask, 0, timeout); +} +#define intel_de_wait_for_clear(p,...) __intel_de_wait_for_clear(__to_intel_display(p), __VA_ARGS__) /* * Unlocked mmio-accessors, think carefully before using these. @@ -94,33 +199,38 @@ intel_de_wait_for_clear(struct drm_i915_private *i915, i915_reg_t reg, * a more localised lock guarding all access to that bank of registers. */ static inline u32 -intel_de_read_fw(struct drm_i915_private *i915, i915_reg_t reg) +__intel_de_read_fw(struct intel_display *display, i915_reg_t reg) { u32 val; - val = intel_uncore_read_fw(&i915->uncore, reg); + val = intel_uncore_read_fw(__to_uncore(display), reg); trace_i915_reg_rw(false, reg, val, sizeof(val), true); return val; } +#define intel_de_read_fw(p,...) __intel_de_read_fw(__to_intel_display(p), __VA_ARGS__) static inline void -intel_de_write_fw(struct drm_i915_private *i915, i915_reg_t reg, u32 val) +__intel_de_write_fw(struct intel_display *display, i915_reg_t reg, u32 val) { trace_i915_reg_rw(true, reg, val, sizeof(val), true); - intel_uncore_write_fw(&i915->uncore, reg, val); + intel_uncore_write_fw(__to_uncore(display), reg, val); } +#define intel_de_write_fw(p,...) __intel_de_write_fw(__to_intel_display(p), __VA_ARGS__) static inline u32 -intel_de_read_notrace(struct drm_i915_private *i915, i915_reg_t reg) +__intel_de_read_notrace(struct intel_display *display, i915_reg_t reg) { - return intel_uncore_read_notrace(&i915->uncore, reg); + return intel_uncore_read_notrace(__to_uncore(display), reg); } +#define intel_de_read_notrace(p,...) __intel_de_read_notrace(__to_intel_display(p), __VA_ARGS__) static inline void -intel_de_write_notrace(struct drm_i915_private *i915, i915_reg_t reg, u32 val) +__intel_de_write_notrace(struct intel_display *display, i915_reg_t reg, + u32 val) { - intel_uncore_write_notrace(&i915->uncore, reg, val); + intel_uncore_write_notrace(__to_uncore(display), reg, val); } +#define intel_de_write_notrace(p,...) __intel_de_write_notrace(__to_intel_display(p), __VA_ARGS__) #endif /* __INTEL_DE_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ab2f52d21bad..b9434465d3a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -275,6 +275,13 @@ static int intel_bigjoiner_num_pipes(const struct intel_crtc_state *crtc_state) return hweight8(crtc_state->bigjoiner_pipes); } +u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return BIT(crtc->pipe) | crtc_state->bigjoiner_pipes; +} + struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -383,8 +390,7 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, break; } - if (intel_de_wait_for_register(dev_priv, dpll_reg, - port_mask, expected_mask, 1000)) + if (intel_de_wait(dev_priv, dpll_reg, port_mask, expected_mask, 1000)) drm_WARN(&dev_priv->drm, 1, "timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n", dig_port->base.base.base.id, dig_port->base.base.name, @@ -430,6 +436,18 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) intel_de_rmw(dev_priv, PIPE_ARB_CTL(pipe), 0, PIPE_ARB_USE_PROG_SLOTS); + if (DISPLAY_VER(dev_priv) >= 14) { + u32 clear = DP_DSC_INSERT_SF_AT_EOL_WA; + u32 set = 0; + + if (DISPLAY_VER(dev_priv) == 14) + set |= DP_FEC_BS_JITTER_WA; + + intel_de_rmw(dev_priv, + hsw_chicken_trans_reg(dev_priv, cpu_transcoder), + clear, set); + } + val = intel_de_read(dev_priv, TRANSCONF(cpu_transcoder)); if (val & TRANSCONF_ENABLE) { /* we keep both pipes enabled on 830 */ @@ -437,6 +455,14 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) return; } + /* Wa_1409098942:adlp+ */ + if (DISPLAY_VER(dev_priv) >= 13 && + new_crtc_state->dsc.compression_enable) { + val &= ~TRANSCONF_PIXEL_COUNT_SCALING_MASK; + val |= REG_FIELD_PREP(TRANSCONF_PIXEL_COUNT_SCALING_MASK, + TRANSCONF_PIXEL_COUNT_SCALING_X4); + } + intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val | TRANSCONF_ENABLE); intel_de_posting_read(dev_priv, TRANSCONF(cpu_transcoder)); @@ -483,6 +509,11 @@ void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state) if (!IS_I830(dev_priv)) val &= ~TRANSCONF_ENABLE; + /* Wa_1409098942:adlp+ */ + if (DISPLAY_VER(dev_priv) >= 13 && + old_crtc_state->dsc.compression_enable) + val &= ~TRANSCONF_PIXEL_COUNT_SCALING_MASK; + intel_de_write(dev_priv, TRANSCONF(cpu_transcoder), val); if (DISPLAY_VER(dev_priv) >= 12) @@ -535,7 +566,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) struct drm_i915_private *dev_priv = to_i915(plane->base.dev); return DISPLAY_VER(dev_priv) < 4 || - (plane->fbc && + (plane->fbc && !plane_state->no_fbc_reason && plane_state->view.gtt.type == I915_GTT_VIEW_NORMAL); } @@ -1552,18 +1583,21 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true); } -static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, - enum pipe pipe, bool apply) +/* Display WA #1180: WaDisableScalarClockGating: glk */ +static bool glk_need_scaler_clock_gating_wa(const struct intel_crtc_state *crtc_state) { - u32 val = intel_de_read(dev_priv, CLKGATE_DIS_PSL(pipe)); + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + return DISPLAY_VER(i915) == 10 && crtc_state->pch_pfit.enabled; +} + +static void glk_pipe_scaler_clock_gating_wa(struct intel_crtc *crtc, bool enable) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); u32 mask = DPF_GATING_DIS | DPF_RAM_GATING_DIS | DPFR_GATING_DIS; - if (apply) - val |= mask; - else - val &= ~mask; - - intel_de_write(dev_priv, CLKGATE_DIS_PSL(pipe), val); + intel_de_rmw(i915, CLKGATE_DIS_PSL(crtc->pipe), + mask, enable ? mask : 0); } static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state) @@ -1586,24 +1620,6 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1)); } -static void icl_ddi_bigjoiner_pre_enable(struct intel_atomic_state *state, - const struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *master_crtc = intel_master_crtc(crtc_state); - - /* - * Enable sequence steps 1-7 on bigjoiner master - */ - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - intel_encoders_pre_pll_enable(state, master_crtc); - - if (crtc_state->shared_dpll) - intel_enable_shared_dpll(crtc_state); - - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - intel_encoders_pre_enable(state, master_crtc); -} - static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1639,90 +1655,107 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe, hsw_workaround_pipe; enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder; - bool psl_clkgate_wa; + struct intel_crtc *pipe_crtc; if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; - intel_dmc_enable_pipe(dev_priv, crtc->pipe); + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) + intel_dmc_enable_pipe(dev_priv, pipe_crtc->pipe); - if (!new_crtc_state->bigjoiner_pipes) { - intel_encoders_pre_pll_enable(state, crtc); + intel_encoders_pre_pll_enable(state, crtc); - if (new_crtc_state->shared_dpll) - intel_enable_shared_dpll(new_crtc_state); + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); - intel_encoders_pre_enable(state, crtc); - } else { - icl_ddi_bigjoiner_pre_enable(state, new_crtc_state); + if (pipe_crtc_state->shared_dpll) + intel_enable_shared_dpll(pipe_crtc_state); } - intel_dsc_enable(new_crtc_state); + intel_encoders_pre_enable(state, crtc); - if (DISPLAY_VER(dev_priv) >= 13) - intel_uncompressed_joiner_enable(new_crtc_state); + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); - intel_set_pipe_src_size(new_crtc_state); - if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) - bdw_set_pipe_misc(new_crtc_state); + intel_dsc_enable(pipe_crtc_state); - if (!intel_crtc_is_bigjoiner_slave(new_crtc_state) && - !transcoder_is_dsi(cpu_transcoder)) + if (DISPLAY_VER(dev_priv) >= 13) + intel_uncompressed_joiner_enable(pipe_crtc_state); + + intel_set_pipe_src_size(pipe_crtc_state); + + if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) + bdw_set_pipe_misc(pipe_crtc_state); + } + + if (!transcoder_is_dsi(cpu_transcoder)) hsw_configure_cpu_transcoder(new_crtc_state); - crtc->active = true; + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); - /* Display WA #1180: WaDisableScalarClockGating: glk */ - psl_clkgate_wa = DISPLAY_VER(dev_priv) == 10 && - new_crtc_state->pch_pfit.enabled; - if (psl_clkgate_wa) - glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true); + pipe_crtc->active = true; - if (DISPLAY_VER(dev_priv) >= 9) - skl_pfit_enable(new_crtc_state); - else - ilk_pfit_enable(new_crtc_state); + if (glk_need_scaler_clock_gating_wa(pipe_crtc_state)) + glk_pipe_scaler_clock_gating_wa(pipe_crtc, true); - /* - * On ILK+ LUT must be loaded before the pipe is running but with - * clocks enabled - */ - intel_color_load_luts(new_crtc_state); - intel_color_commit_noarm(new_crtc_state); - intel_color_commit_arm(new_crtc_state); - /* update DSPCNTR to configure gamma/csc for pipe bottom color */ - if (DISPLAY_VER(dev_priv) < 9) - intel_disable_primary_plane(new_crtc_state); + if (DISPLAY_VER(dev_priv) >= 9) + skl_pfit_enable(pipe_crtc_state); + else + ilk_pfit_enable(pipe_crtc_state); - hsw_set_linetime_wm(new_crtc_state); + /* + * On ILK+ LUT must be loaded before the pipe is running but with + * clocks enabled + */ + intel_color_load_luts(pipe_crtc_state); + intel_color_commit_noarm(pipe_crtc_state); + intel_color_commit_arm(pipe_crtc_state); + /* update DSPCNTR to configure gamma/csc for pipe bottom color */ + if (DISPLAY_VER(dev_priv) < 9) + intel_disable_primary_plane(pipe_crtc_state); - if (DISPLAY_VER(dev_priv) >= 11) - icl_set_pipe_chicken(new_crtc_state); + hsw_set_linetime_wm(pipe_crtc_state); - intel_initial_watermarks(state, crtc); + if (DISPLAY_VER(dev_priv) >= 11) + icl_set_pipe_chicken(pipe_crtc_state); - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) - intel_crtc_vblank_on(new_crtc_state); + intel_initial_watermarks(state, pipe_crtc); + } intel_encoders_enable(state, crtc); - if (psl_clkgate_wa) { - intel_crtc_wait_for_next_vblank(crtc); - glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, false); - } + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); + enum pipe hsw_workaround_pipe; - /* If we change the relative order between pipe/planes enabling, we need - * to change the workaround. */ - hsw_workaround_pipe = new_crtc_state->hsw_workaround_pipe; - if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { - struct intel_crtc *wa_crtc; + if (glk_need_scaler_clock_gating_wa(pipe_crtc_state)) { + intel_crtc_wait_for_next_vblank(pipe_crtc); + glk_pipe_scaler_clock_gating_wa(pipe_crtc, false); + } - wa_crtc = intel_crtc_for_pipe(dev_priv, hsw_workaround_pipe); + /* + * If we change the relative order between pipe/planes + * enabling, we need to change the workaround. + */ + hsw_workaround_pipe = pipe_crtc_state->hsw_workaround_pipe; + if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { + struct intel_crtc *wa_crtc = + intel_crtc_for_pipe(dev_priv, hsw_workaround_pipe); - intel_crtc_wait_for_next_vblank(wa_crtc); - intel_crtc_wait_for_next_vblank(wa_crtc); + intel_crtc_wait_for_next_vblank(wa_crtc); + intel_crtc_wait_for_next_vblank(wa_crtc); + } } } @@ -1786,29 +1819,28 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_crtc *pipe_crtc; /* * FIXME collapse everything to one hook. * Need care with mst->ddi interactions. */ - if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) { - intel_encoders_disable(state, crtc); - intel_encoders_post_disable(state, crtc); + intel_encoders_disable(state, crtc); + intel_encoders_post_disable(state, crtc); + + for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); + + intel_disable_shared_dpll(old_pipe_crtc_state); } - intel_disable_shared_dpll(old_crtc_state); + intel_encoders_post_pll_disable(state, crtc); - if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) { - struct intel_crtc *slave_crtc; - - intel_encoders_post_pll_disable(state, crtc); - - intel_dmc_disable_pipe(i915, crtc->pipe); - - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, - intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) - intel_dmc_disable_pipe(i915, slave_crtc->pipe); - } + for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) + intel_dmc_disable_pipe(i915, pipe_crtc->pipe); } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) @@ -1836,6 +1868,7 @@ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, BCLRPAT(crtc->pipe), 0); } +/* Prefer intel_encoder_is_combo() */ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) { if (phy == PHY_NONE) @@ -1857,6 +1890,7 @@ bool intel_phy_is_combo(struct drm_i915_private *dev_priv, enum phy phy) return false; } +/* Prefer intel_encoder_is_tc() */ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) { /* @@ -1877,6 +1911,7 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy) return false; } +/* Prefer intel_encoder_is_snps() */ bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy) { /* @@ -1886,6 +1921,7 @@ bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy) return IS_DG2(dev_priv) && phy > PHY_NONE && phy <= PHY_E; } +/* Prefer intel_encoder_to_phy() */ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) { if (DISPLAY_VER(i915) >= 13 && port >= PORT_D_XELPD) @@ -1903,6 +1939,7 @@ enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port) return PHY_A + port - PORT_A; } +/* Prefer intel_encoder_to_tc() */ 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))) @@ -1914,6 +1951,41 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port) return TC_PORT_1 + port - PORT_C; } +enum phy intel_encoder_to_phy(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return intel_port_to_phy(i915, encoder->port); +} + +bool intel_encoder_is_combo(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return intel_phy_is_combo(i915, intel_encoder_to_phy(encoder)); +} + +bool intel_encoder_is_snps(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return intel_phy_is_snps(i915, intel_encoder_to_phy(encoder)); +} + +bool intel_encoder_is_tc(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return intel_phy_is_tc(i915, intel_encoder_to_phy(encoder)); +} + +enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + return intel_port_to_tc(i915, encoder->port); +} + enum intel_display_power_domain intel_aux_power_domain(struct intel_digital_port *dig_port) { @@ -2381,7 +2453,7 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; - int clock_limit = i915->max_dotclk_freq; + int clock_limit = i915->display.cdclk.max_dotclk_freq; /* * Start with the adjusted_mode crtc timings, which @@ -2405,7 +2477,7 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) */ if (intel_crtc_supports_double_wide(crtc) && pipe_mode->crtc_clock > clock_limit) { - clock_limit = i915->max_dotclk_freq; + clock_limit = i915->display.cdclk.max_dotclk_freq; crtc_state->double_wide = true; } } @@ -2709,15 +2781,6 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state) */ intel_de_write(dev_priv, PIPESRC(pipe), PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1)); - - if (!crtc_state->enable_psr2_su_region_et) - return; - - width = drm_rect_width(&crtc_state->psr2_su_area); - height = drm_rect_height(&crtc_state->psr2_su_area); - - intel_de_write(dev_priv, PIPE_SRCSZ_ERLY_TPT(pipe), - PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1)); } static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state) @@ -3008,19 +3071,16 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, i9xx_get_pfit_config(pipe_config); + i9xx_dpll_get_hw_state(crtc, &pipe_config->dpll_hw_state); + if (DISPLAY_VER(dev_priv) >= 4) { - /* No way to read it out on pipes B and C */ - if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) - tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; - else - tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); + tmp = pipe_config->dpll_hw_state.i9xx.dpll_md; pipe_config->pixel_multiplier = ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; - pipe_config->dpll_hw_state.dpll_md = tmp; } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv) || IS_PINEVIEW(dev_priv)) { - tmp = intel_de_read(dev_priv, DPLL(crtc->pipe)); + tmp = pipe_config->dpll_hw_state.i9xx.dpll; pipe_config->pixel_multiplier = ((tmp & SDVO_MULTIPLIER_MASK) >> SDVO_MULTIPLIER_SHIFT_HIRES) + 1; @@ -3030,26 +3090,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, * function. */ pipe_config->pixel_multiplier = 1; } - pipe_config->dpll_hw_state.dpll = intel_de_read(dev_priv, - DPLL(crtc->pipe)); - if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { - pipe_config->dpll_hw_state.fp0 = intel_de_read(dev_priv, - FP0(crtc->pipe)); - pipe_config->dpll_hw_state.fp1 = intel_de_read(dev_priv, - FP1(crtc->pipe)); - } else { - /* Mask out read-only status bits. */ - pipe_config->dpll_hw_state.dpll &= ~(DPLL_LOCK_VLV | - DPLL_PORTC_READY_MASK | - DPLL_PORTB_READY_MASK); - } if (IS_CHERRYVIEW(dev_priv)) - chv_crtc_clock_get(crtc, pipe_config); + chv_crtc_clock_get(pipe_config); else if (IS_VALLEYVIEW(dev_priv)) - vlv_crtc_clock_get(crtc, pipe_config); + vlv_crtc_clock_get(pipe_config); else - i9xx_crtc_clock_get(crtc, pipe_config); + i9xx_crtc_clock_get(pipe_config); /* * Normally the dotclock is filled in by the encoder .get_config() @@ -3675,8 +3722,8 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, struct intel_display_power_domain_set *power_domain_set) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder; enum port port; u32 tmp; @@ -3702,11 +3749,11 @@ static bool bxt_get_dsi_transcoder_state(struct intel_crtc *crtc, break; /* XXX: this works for video mode only */ - tmp = intel_de_read(dev_priv, BXT_MIPI_PORT_CTRL(port)); + tmp = intel_de_read(display, BXT_MIPI_PORT_CTRL(port)); if (!(tmp & DPI_ENABLE)) continue; - tmp = intel_de_read(dev_priv, MIPI_CTRL(port)); + tmp = intel_de_read(display, MIPI_CTRL(display, port)); if ((tmp & BXT_PIPE_SELECT_MASK) != BXT_PIPE_SELECT(crtc->pipe)) continue; @@ -4723,8 +4770,6 @@ intel_modeset_pipe_config_late(struct intel_atomic_state *state, struct drm_connector *connector; int i; - intel_bigjoiner_adjust_pipe_src(crtc_state); - for_each_new_connector_in_state(&state->base, connector, conn_state, i) { struct intel_encoder *encoder = @@ -4791,42 +4836,92 @@ intel_compare_dp_vsc_sdp(const struct drm_dp_vsc_sdp *a, a->content_type == b->content_type; } +static bool +intel_compare_dp_as_sdp(const struct drm_dp_as_sdp *a, + const struct drm_dp_as_sdp *b) +{ + return a->vtotal == b->vtotal && + a->target_rr == b->target_rr && + a->duration_incr_ms == b->duration_incr_ms && + a->duration_decr_ms == b->duration_decr_ms && + a->mode == b->mode; +} + static bool intel_compare_buffer(const u8 *a, const u8 *b, size_t len) { return memcmp(a, b, len) == 0; } +static void __printf(5, 6) +pipe_config_mismatch(struct drm_printer *p, bool fastset, + const struct intel_crtc *crtc, + const char *name, const char *format, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, format); + vaf.fmt = format; + vaf.va = &args; + + if (fastset) + drm_printf(p, "[CRTC:%d:%s] fastset requirement not met in %s %pV\n", + crtc->base.base.id, crtc->base.name, name, &vaf); + else + drm_printf(p, "[CRTC:%d:%s] mismatch in %s %pV\n", + crtc->base.base.id, crtc->base.name, name, &vaf); + + va_end(args); +} + static void -pipe_config_infoframe_mismatch(struct drm_i915_private *dev_priv, - bool fastset, const char *name, +pipe_config_infoframe_mismatch(struct drm_printer *p, bool fastset, + const struct intel_crtc *crtc, + const char *name, const union hdmi_infoframe *a, const union hdmi_infoframe *b) { + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + const char *loglevel; + if (fastset) { if (!drm_debug_enabled(DRM_UT_KMS)) return; - drm_dbg_kms(&dev_priv->drm, - "fastset requirement not met in %s infoframe\n", name); - drm_dbg_kms(&dev_priv->drm, "expected:\n"); - hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, a); - drm_dbg_kms(&dev_priv->drm, "found:\n"); - hdmi_infoframe_log(KERN_DEBUG, dev_priv->drm.dev, b); + loglevel = KERN_DEBUG; } else { - drm_err(&dev_priv->drm, "mismatch in %s infoframe\n", name); - drm_err(&dev_priv->drm, "expected:\n"); - hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, a); - drm_err(&dev_priv->drm, "found:\n"); - hdmi_infoframe_log(KERN_ERR, dev_priv->drm.dev, b); + loglevel = KERN_ERR; } + + pipe_config_mismatch(p, fastset, crtc, name, "infoframe"); + + drm_printf(p, "expected:\n"); + hdmi_infoframe_log(loglevel, i915->drm.dev, a); + drm_printf(p, "found:\n"); + hdmi_infoframe_log(loglevel, i915->drm.dev, b); } static void -pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *i915, - bool fastset, const char *name, +pipe_config_dp_vsc_sdp_mismatch(struct drm_printer *p, bool fastset, + const struct intel_crtc *crtc, + const char *name, const struct drm_dp_vsc_sdp *a, const struct drm_dp_vsc_sdp *b) +{ + pipe_config_mismatch(p, fastset, crtc, name, "dp sdp"); + + drm_printf(p, "expected:\n"); + drm_dp_vsc_sdp_log(p, a); + drm_printf(p, "found:\n"); + drm_dp_vsc_sdp_log(p, b); +} + +static void +pipe_config_dp_as_sdp_mismatch(struct drm_i915_private *i915, + bool fastset, const char *name, + const struct drm_dp_as_sdp *a, + const struct drm_dp_as_sdp *b) { struct drm_printer p; @@ -4841,9 +4936,9 @@ pipe_config_dp_vsc_sdp_mismatch(struct drm_i915_private *i915, } drm_printf(&p, "expected:\n"); - drm_dp_vsc_sdp_log(&p, a); + drm_dp_as_sdp_log(&p, a); drm_printf(&p, "found:\n"); - drm_dp_vsc_sdp_log(&p, b); + drm_dp_as_sdp_log(&p, b); } /* Returns the length up to and including the last differing byte */ @@ -4861,64 +4956,35 @@ memcmp_diff_len(const u8 *a, const u8 *b, size_t len) } static void -pipe_config_buffer_mismatch(bool fastset, const struct intel_crtc *crtc, +pipe_config_buffer_mismatch(struct drm_printer *p, bool fastset, + const struct intel_crtc *crtc, const char *name, const u8 *a, const u8 *b, size_t len) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const char *loglevel; if (fastset) { if (!drm_debug_enabled(DRM_UT_KMS)) return; - /* only dump up to the last difference */ - len = memcmp_diff_len(a, b, len); - - drm_dbg_kms(&dev_priv->drm, - "[CRTC:%d:%s] fastset requirement not met in %s buffer\n", - crtc->base.base.id, crtc->base.name, name); - print_hex_dump(KERN_DEBUG, "expected: ", DUMP_PREFIX_NONE, - 16, 0, a, len, false); - print_hex_dump(KERN_DEBUG, "found: ", DUMP_PREFIX_NONE, - 16, 0, b, len, false); + loglevel = KERN_DEBUG; } else { - /* only dump up to the last difference */ - len = memcmp_diff_len(a, b, len); - - drm_err(&dev_priv->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", - crtc->base.base.id, crtc->base.name, name); - print_hex_dump(KERN_ERR, "expected: ", DUMP_PREFIX_NONE, - 16, 0, a, len, false); - print_hex_dump(KERN_ERR, "found: ", DUMP_PREFIX_NONE, - 16, 0, b, len, false); + loglevel = KERN_ERR; } -} -static void __printf(4, 5) -pipe_config_mismatch(bool fastset, const struct intel_crtc *crtc, - const char *name, const char *format, ...) -{ - struct drm_i915_private *i915 = to_i915(crtc->base.dev); - struct va_format vaf; - va_list args; + pipe_config_mismatch(p, fastset, crtc, name, "buffer"); - va_start(args, format); - vaf.fmt = format; - vaf.va = &args; + /* only dump up to the last difference */ + len = memcmp_diff_len(a, b, len); - if (fastset) - drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] fastset requirement not met in %s %pV\n", - crtc->base.base.id, crtc->base.name, name, &vaf); - else - drm_err(&i915->drm, "[CRTC:%d:%s] mismatch in %s %pV\n", - crtc->base.base.id, crtc->base.name, name, &vaf); - - va_end(args); + print_hex_dump(loglevel, "expected: ", DUMP_PREFIX_NONE, + 16, 0, a, len, false); + print_hex_dump(loglevel, "found: ", DUMP_PREFIX_NONE, + 16, 0, b, len, false); } static void -pipe_config_pll_mismatch(bool fastset, +pipe_config_pll_mismatch(struct drm_printer *p, bool fastset, const struct intel_crtc *crtc, const char *name, const struct intel_dpll_hw_state *a, @@ -4926,25 +4992,12 @@ pipe_config_pll_mismatch(bool fastset, { struct drm_i915_private *i915 = to_i915(crtc->base.dev); - if (fastset) { - if (!drm_debug_enabled(DRM_UT_KMS)) - return; + pipe_config_mismatch(p, fastset, crtc, name, " "); /* stupid -Werror=format-zero-length */ - drm_dbg_kms(&i915->drm, - "[CRTC:%d:%s] fastset requirement not met in %s\n", - crtc->base.base.id, crtc->base.name, name); - drm_dbg_kms(&i915->drm, "expected:\n"); - intel_dpll_dump_hw_state(i915, a); - drm_dbg_kms(&i915->drm, "found:\n"); - intel_dpll_dump_hw_state(i915, b); - } else { - drm_err(&i915->drm, "[CRTC:%d:%s] mismatch in %s buffer\n", - crtc->base.base.id, crtc->base.name, name); - drm_err(&i915->drm, "expected:\n"); - intel_dpll_dump_hw_state(i915, a); - drm_err(&i915->drm, "found:\n"); - intel_dpll_dump_hw_state(i915, b); - } + drm_printf(p, "expected:\n"); + intel_dpll_dump_hw_state(i915, p, a); + drm_printf(p, "found:\n"); + intel_dpll_dump_hw_state(i915, p, b); } bool @@ -4954,13 +5007,19 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, { struct drm_i915_private *dev_priv = to_i915(current_config->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); + struct drm_printer p; bool ret = true; + if (fastset) + p = drm_dbg_printer(&dev_priv->drm, DRM_UT_KMS, NULL); + else + p = drm_err_printer(&dev_priv->drm, NULL); + #define PIPE_CONF_CHECK_X(name) do { \ if (current_config->name != pipe_config->name) { \ BUILD_BUG_ON_MSG(__same_type(current_config->name, bool), \ __stringify(name) " is bool"); \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected 0x%08x, found 0x%08x)", \ current_config->name, \ pipe_config->name); \ @@ -4972,7 +5031,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if ((current_config->name & (mask)) != (pipe_config->name & (mask))) { \ BUILD_BUG_ON_MSG(__same_type(current_config->name, bool), \ __stringify(name) " is bool"); \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected 0x%08x, found 0x%08x)", \ current_config->name & (mask), \ pipe_config->name & (mask)); \ @@ -4984,7 +5043,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (current_config->name != pipe_config->name) { \ BUILD_BUG_ON_MSG(__same_type(current_config->name, bool), \ __stringify(name) " is bool"); \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected %i, found %i)", \ current_config->name, \ pipe_config->name); \ @@ -4996,7 +5055,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (current_config->name != pipe_config->name) { \ BUILD_BUG_ON_MSG(!__same_type(current_config->name, bool), \ __stringify(name) " is not bool"); \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected %s, found %s)", \ str_yes_no(current_config->name), \ str_yes_no(pipe_config->name)); \ @@ -5006,7 +5065,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_P(name) do { \ if (current_config->name != pipe_config->name) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected %p, found %p)", \ current_config->name, \ pipe_config->name); \ @@ -5017,7 +5076,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_M_N(name) do { \ if (!intel_compare_link_m_n(¤t_config->name, \ &pipe_config->name)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(expected tu %i data %i/%i link %i/%i, " \ "found tu %i, data %i/%i link %i/%i)", \ current_config->name.tu, \ @@ -5037,7 +5096,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_PLL(name) do { \ if (!intel_dpll_compare_hw_state(dev_priv, ¤t_config->name, \ &pipe_config->name)) { \ - pipe_config_pll_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_pll_mismatch(&p, fastset, crtc, __stringify(name), \ ¤t_config->name, \ &pipe_config->name); \ ret = false; \ @@ -5070,7 +5129,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_FLAGS(name, mask) do { \ if ((current_config->name ^ pipe_config->name) & (mask)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(name), \ "(%x) (expected %i, found %i)", \ (mask), \ current_config->name & (mask), \ @@ -5082,7 +5141,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_INFOFRAME(name) do { \ if (!intel_compare_infoframe(¤t_config->infoframes.name, \ &pipe_config->infoframes.name)) { \ - pipe_config_infoframe_mismatch(dev_priv, fastset, __stringify(name), \ + pipe_config_infoframe_mismatch(&p, fastset, crtc, __stringify(name), \ ¤t_config->infoframes.name, \ &pipe_config->infoframes.name); \ ret = false; \ @@ -5092,7 +5151,17 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, #define PIPE_CONF_CHECK_DP_VSC_SDP(name) do { \ if (!intel_compare_dp_vsc_sdp(¤t_config->infoframes.name, \ &pipe_config->infoframes.name)) { \ - pipe_config_dp_vsc_sdp_mismatch(dev_priv, fastset, __stringify(name), \ + pipe_config_dp_vsc_sdp_mismatch(&p, fastset, crtc, __stringify(name), \ + ¤t_config->infoframes.name, \ + &pipe_config->infoframes.name); \ + ret = false; \ + } \ +} while (0) + +#define PIPE_CONF_CHECK_DP_AS_SDP(name) do { \ + if (!intel_compare_dp_as_sdp(¤t_config->infoframes.name, \ + &pipe_config->infoframes.name)) { \ + pipe_config_dp_as_sdp_mismatch(dev_priv, fastset, __stringify(name), \ ¤t_config->infoframes.name, \ &pipe_config->infoframes.name); \ ret = false; \ @@ -5103,7 +5172,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, BUILD_BUG_ON(sizeof(current_config->name) != (len)); \ BUILD_BUG_ON(sizeof(pipe_config->name) != (len)); \ if (!intel_compare_buffer(current_config->name, pipe_config->name, (len))) { \ - pipe_config_buffer_mismatch(fastset, crtc, __stringify(name), \ + pipe_config_buffer_mismatch(&p, fastset, crtc, __stringify(name), \ current_config->name, \ pipe_config->name, \ (len)); \ @@ -5116,7 +5185,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, !intel_color_lut_equal(current_config, \ current_config->lut, pipe_config->lut, \ is_pre_csc_lut)) { \ - pipe_config_mismatch(fastset, crtc, __stringify(lut), \ + pipe_config_mismatch(&p, fastset, crtc, __stringify(lut), \ "hw_state doesn't match sw_state"); \ ret = false; \ } \ @@ -5245,6 +5314,18 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_CSC(output_csc); } + /* + * Panel replay has to be enabled before link training. PSR doesn't have + * this requirement -> check these only if using panel replay + */ + if (current_config->has_panel_replay || pipe_config->has_panel_replay) { + PIPE_CONF_CHECK_BOOL(has_psr); + PIPE_CONF_CHECK_BOOL(has_psr2); + PIPE_CONF_CHECK_BOOL(enable_psr2_sel_fetch); + PIPE_CONF_CHECK_BOOL(enable_psr2_su_region_et); + PIPE_CONF_CHECK_BOOL(has_panel_replay); + } + PIPE_CONF_CHECK_BOOL(double_wide); if (dev_priv->display.dpll.mgr) @@ -5280,6 +5361,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_INFOFRAME(hdmi); PIPE_CONF_CHECK_INFOFRAME(drm); PIPE_CONF_CHECK_DP_VSC_SDP(vsc); + PIPE_CONF_CHECK_DP_AS_SDP(as_sdp); PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); @@ -5331,6 +5413,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(vrr.flipline); PIPE_CONF_CHECK_I(vrr.pipeline_full); PIPE_CONF_CHECK_I(vrr.guardband); + PIPE_CONF_CHECK_I(vrr.vsync_start); + PIPE_CONF_CHECK_I(vrr.vsync_end); } #undef PIPE_CONF_CHECK_X @@ -5576,14 +5660,16 @@ static int intel_modeset_checks(struct intel_atomic_state *state) static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_state, struct intel_crtc_state *new_crtc_state) { - struct drm_i915_private *i915 = to_i915(old_crtc_state->uapi.crtc->dev); + struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); /* only allow LRR when the timings stay within the VRR range */ if (old_crtc_state->vrr.in_range != new_crtc_state->vrr.in_range) new_crtc_state->update_lrr = false; if (!intel_pipe_config_compare(old_crtc_state, new_crtc_state, true)) - drm_dbg_kms(&i915->drm, "fastset requirement not met, forcing full modeset\n"); + drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] fastset requirement not met, forcing full modeset\n", + crtc->base.base.id, crtc->base.name); else new_crtc_state->uapi.mode_changed = false; @@ -6237,27 +6323,37 @@ static int intel_atomic_check_config(struct intel_atomic_state *state, continue; } - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) { - drm_WARN_ON(&i915->drm, new_crtc_state->uapi.enable); + if (drm_WARN_ON(&i915->drm, intel_crtc_is_bigjoiner_slave(new_crtc_state))) continue; - } ret = intel_crtc_prepare_cleared_state(state, crtc); if (ret) - break; + goto fail; if (!new_crtc_state->hw.enable) continue; ret = intel_modeset_pipe_config(state, crtc, limits); if (ret) - break; - - ret = intel_atomic_check_bigjoiner(state, crtc); - if (ret) - break; + goto fail; } + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + if (!intel_crtc_needs_modeset(new_crtc_state)) + continue; + + if (drm_WARN_ON(&i915->drm, intel_crtc_is_bigjoiner_slave(new_crtc_state))) + continue; + + if (!new_crtc_state->hw.enable) + continue; + + ret = intel_modeset_pipe_config_late(state, crtc); + if (ret) + goto fail; + } + +fail: if (ret) *failed_pipe = crtc->pipe; @@ -6353,16 +6449,26 @@ int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + if (!intel_crtc_needs_modeset(new_crtc_state)) + continue; + + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) { + drm_WARN_ON(&dev_priv->drm, new_crtc_state->uapi.enable); + continue; + } + + ret = intel_atomic_check_bigjoiner(state, crtc); + if (ret) + goto fail; + } + for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!intel_crtc_needs_modeset(new_crtc_state)) continue; - if (new_crtc_state->hw.enable) { - ret = intel_modeset_pipe_config_late(state, crtc); - if (ret) - goto fail; - } + intel_bigjoiner_adjust_pipe_src(new_crtc_state); intel_crtc_check_fastset(old_crtc_state, new_crtc_state); } @@ -6644,18 +6750,22 @@ static void intel_enable_crtc(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(state->base.dev); const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct intel_crtc *pipe_crtc; if (!intel_crtc_needs_modeset(new_crtc_state)) return; - /* VRR will be enable later, if required */ - intel_crtc_update_active_timings(new_crtc_state, false); + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(new_crtc_state)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); + + /* VRR will be enable later, if required */ + intel_crtc_update_active_timings(pipe_crtc_state, false); + } dev_priv->display.funcs.display->crtc_enable(state, crtc); - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) - return; - /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } @@ -6746,31 +6856,42 @@ static void intel_update_crtc(struct intel_atomic_state *state, } static void intel_old_crtc_state_disables(struct intel_atomic_state *state, - struct intel_crtc_state *old_crtc_state, - struct intel_crtc_state *new_crtc_state, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + struct intel_crtc *pipe_crtc; /* * We need to disable pipe CRC before disabling the pipe, * or we race against vblank off. */ - intel_crtc_disable_pipe_crc(crtc); + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) + intel_crtc_disable_pipe_crc(pipe_crtc); dev_priv->display.funcs.display->crtc_disable(state, crtc); - crtc->active = false; - intel_fbc_disable(crtc); - if (!new_crtc_state->hw.active) - intel_initial_watermarks(state, crtc); + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *new_pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); + + pipe_crtc->active = false; + intel_fbc_disable(pipe_crtc); + + if (!new_pipe_crtc_state->hw.active) + intel_initial_watermarks(state, pipe_crtc); + } } static void intel_commit_modeset_disables(struct intel_atomic_state *state) { - struct intel_crtc_state *new_crtc_state, *old_crtc_state; + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; - u32 handled = 0; + u8 disable_pipes = 0; int i; for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, @@ -6778,21 +6899,31 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) if (!intel_crtc_needs_modeset(new_crtc_state)) continue; + /* + * Needs to be done even for pipes + * that weren't enabled previously. + */ intel_pre_plane_update(state, crtc); if (!old_crtc_state->hw.active) continue; + disable_pipes |= BIT(crtc->pipe); + } + + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + if ((disable_pipes & BIT(crtc->pipe)) == 0) + continue; + intel_crtc_disable_planes(state, crtc); } /* Only disable port sync and MST slaves */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - if (!intel_crtc_needs_modeset(new_crtc_state)) + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; - if (!old_crtc_state->hw.active) + if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) continue; /* In case of Transcoder port Sync master slave CRTCs can be @@ -6801,28 +6932,28 @@ static void intel_commit_modeset_disables(struct intel_atomic_state *state) * Slave vblanks are masked till Master Vblanks. */ if (!is_trans_port_sync_slave(old_crtc_state) && - !intel_dp_mst_is_slave_trans(old_crtc_state) && - !intel_crtc_is_bigjoiner_slave(old_crtc_state)) + !intel_dp_mst_is_slave_trans(old_crtc_state)) continue; - intel_old_crtc_state_disables(state, old_crtc_state, - new_crtc_state, crtc); - handled |= BIT(crtc->pipe); + intel_old_crtc_state_disables(state, crtc); + + disable_pipes &= ~intel_crtc_joined_pipe_mask(old_crtc_state); } /* Disable everything else left on */ - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { - if (!intel_crtc_needs_modeset(new_crtc_state) || - (handled & BIT(crtc->pipe))) + for_each_old_intel_crtc_in_state(state, crtc, old_crtc_state, i) { + if ((disable_pipes & BIT(crtc->pipe)) == 0) continue; - if (!old_crtc_state->hw.active) + if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) continue; - intel_old_crtc_state_disables(state, old_crtc_state, - new_crtc_state, crtc); + intel_old_crtc_state_disables(state, crtc); + + disable_pipes &= ~intel_crtc_joined_pipe_mask(old_crtc_state); } + + drm_WARN_ON(&i915->drm, disable_pipes); } static void intel_commit_modeset_enables(struct intel_atomic_state *state) @@ -6889,9 +7020,15 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) intel_pre_update_crtc(state, crtc); } + intel_dbuf_mbus_pre_ddb_update(state); + while (update_pipes) { - for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, - new_crtc_state, i) { + /* + * Commit in reverse order to make bigjoiner master + * send the uapi events after slaves are done. + */ + for_each_oldnew_intel_crtc_in_state_reverse(state, crtc, old_crtc_state, + new_crtc_state, i) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -6919,6 +7056,8 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) } } + intel_dbuf_mbus_post_ddb_update(state); + update_pipes = modeset_pipes; /* @@ -6931,12 +7070,14 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) if ((modeset_pipes & BIT(pipe)) == 0) continue; - if (intel_dp_mst_is_slave_trans(new_crtc_state) || - is_trans_port_sync_master(new_crtc_state) || - intel_crtc_is_bigjoiner_master(new_crtc_state)) + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) continue; - modeset_pipes &= ~BIT(pipe); + if (intel_dp_mst_is_slave_trans(new_crtc_state) || + is_trans_port_sync_master(new_crtc_state)) + continue; + + modeset_pipes &= ~intel_crtc_joined_pipe_mask(new_crtc_state); intel_enable_crtc(state, crtc); } @@ -6951,7 +7092,10 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) if ((modeset_pipes & BIT(pipe)) == 0) continue; - modeset_pipes &= ~BIT(pipe); + if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) + continue; + + modeset_pipes &= ~intel_crtc_joined_pipe_mask(new_crtc_state); intel_enable_crtc(state, crtc); } @@ -6968,7 +7112,11 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) intel_pre_update_crtc(state, crtc); } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + /* + * Commit in reverse order to make bigjoiner master + * send the uapi events after slaves are done. + */ + for_each_new_intel_crtc_in_state_reverse(state, crtc, new_crtc_state, i) { enum pipe pipe = crtc->pipe; if ((update_pipes & BIT(pipe)) == 0) @@ -7165,7 +7313,6 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_encoders_update_prepare(state); intel_dbuf_pre_plane_update(state); - intel_mbus_dbox_update(state); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->do_async_flip) @@ -7690,7 +7837,7 @@ void intel_setup_outputs(struct drm_i915_private *dev_priv) static int max_dotclock(struct drm_i915_private *i915) { - int max_dotclock = i915->max_dotclk_freq; + int max_dotclock = i915->display.cdclk.max_dotclk_freq; /* icl+ might use bigjoiner */ if (DISPLAY_VER(i915) >= 11) diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index f4a0773f0fca..56d1c0e3e62c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -280,6 +280,12 @@ enum phy_fia { base.head) \ for_each_if((pipe_mask) & BIT(intel_crtc->pipe)) +#define for_each_intel_crtc_in_pipe_mask_reverse(dev, intel_crtc, pipe_mask) \ + list_for_each_entry_reverse((intel_crtc), \ + &(dev)->mode_config.crtc_list, \ + base.head) \ + for_each_if((pipe_mask) & BIT((intel_crtc)->pipe)) + #define for_each_intel_encoder(dev, intel_encoder) \ list_for_each_entry(intel_encoder, \ &(dev)->mode_config.encoder_list, \ @@ -344,6 +350,14 @@ enum phy_fia { (__i)++) \ for_each_if(crtc) +#define for_each_new_intel_crtc_in_state_reverse(__state, crtc, new_crtc_state, __i) \ + for ((__i) = (__state)->base.dev->mode_config.num_crtc - 1; \ + (__i) >= 0 && \ + ((crtc) = to_intel_crtc((__state)->base.crtcs[__i].ptr), \ + (new_crtc_state) = to_intel_crtc_state((__state)->base.crtcs[__i].new_state), 1); \ + (__i)--) \ + for_each_if(crtc) + #define for_each_oldnew_intel_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \ for ((__i) = 0; \ (__i) < (__state)->base.dev->mode_config.num_total_plane && \ @@ -408,6 +422,7 @@ intel_cpu_transcoder_mode_valid(struct drm_i915_private *i915, enum phy intel_port_to_phy(struct drm_i915_private *i915, enum port port); bool is_trans_port_sync_mode(const struct intel_crtc_state *state); bool is_trans_port_sync_master(const struct intel_crtc_state *state); +u8 intel_crtc_joined_pipe_mask(const struct intel_crtc_state *crtc_state); bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state); bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state); u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state); @@ -448,6 +463,13 @@ bool intel_phy_is_tc(struct drm_i915_private *dev_priv, enum phy phy); bool intel_phy_is_snps(struct drm_i915_private *dev_priv, enum phy phy); enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv, enum port port); + +enum phy intel_encoder_to_phy(struct intel_encoder *encoder); +bool intel_encoder_is_combo(struct intel_encoder *encoder); +bool intel_encoder_is_snps(struct intel_encoder *encoder); +bool intel_encoder_is_tc(struct intel_encoder *encoder); +enum tc_port intel_encoder_to_tc(struct intel_encoder *encoder); + int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/display/intel_display_conversion.h b/drivers/gpu/drm/i915/display/intel_display_conversion.h new file mode 100644 index 000000000000..ad8545c8055d --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_conversion.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2024 Intel Corporation */ + +/* + * This header is for transitional struct intel_display conversion helpers only. + */ + +#ifndef __INTEL_DISPLAY_CONVERSION__ +#define __INTEL_DISPLAY_CONVERSION__ + +/* + * Transitional macro to optionally convert struct drm_i915_private * to struct + * intel_display *, also accepting the latter. + */ +#define __to_intel_display(p) \ + _Generic(p, \ + const struct drm_i915_private *: (&((const struct drm_i915_private *)(p))->display), \ + struct drm_i915_private *: (&((struct drm_i915_private *)(p))->display), \ + const struct intel_display *: (p), \ + struct intel_display *: (p)) + +#endif /* __INTEL_DISPLAY_CONVERSION__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 2167dbee5eea..7715fc329057 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -26,6 +26,7 @@ #include "intel_global_state.h" #include "intel_gmbus.h" #include "intel_opregion.h" +#include "intel_dmc_wl.h" #include "intel_wm_types.h" struct task_struct; @@ -282,6 +283,9 @@ struct intel_wm { }; struct intel_display { + /* drm device backpointer */ + struct drm_device *drm; + /* Display functions */ struct { /* Top level crtc-ish functions */ @@ -345,6 +349,8 @@ struct intel_display { struct intel_global_obj obj; unsigned int max_cdclk_freq; + unsigned int max_dotclk_freq; + unsigned int skl_preferred_vco_freq; } cdclk; struct { @@ -445,6 +451,16 @@ struct intel_display { bool false_color; } ips; + struct { + bool display_irqs_enabled; + + /* For i915gm/i945gm vblank irq workaround */ + u8 vblank_enabled; + + u32 de_irq_mask[I915_MAX_PIPES]; + u32 pipestat_irq_mask[I915_MAX_PIPES]; + } irq; + struct { wait_queue_head_t waitqueue; @@ -534,6 +550,7 @@ struct intel_display { struct intel_overlay *overlay; struct intel_display_params params; struct intel_vbt_data vbt; + struct intel_dmc_wl wl; struct intel_wm wm; }; diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b99c024b0934..35f9f86ef70f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -31,6 +31,7 @@ #include "intel_hdmi.h" #include "intel_hotplug.h" #include "intel_panel.h" +#include "intel_pps.h" #include "intel_psr.h" #include "intel_psr_regs.h" #include "intel_wm.h" @@ -191,7 +192,7 @@ static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, bool remote_req) { - bool hdcp_cap, hdcp2_cap; + bool hdcp_cap = false, hdcp2_cap = false; if (!intel_connector->hdcp.shim) { seq_puts(m, "No Connector Support"); @@ -252,9 +253,6 @@ static void intel_connector_info(struct seq_file *m, struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - const struct drm_connector_state *conn_state = connector->state; - struct intel_encoder *encoder = - to_intel_encoder(conn_state->best_encoder); const struct drm_display_mode *mode; seq_printf(m, "[CONNECTOR:%d:%s]: status: %s\n", @@ -271,28 +269,23 @@ static void intel_connector_info(struct seq_file *m, drm_get_subpixel_order_name(connector->display_info.subpixel_order)); seq_printf(m, "\tCEA rev: %d\n", connector->display_info.cea_rev); - if (!encoder) - return; - switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - if (encoder->type == INTEL_OUTPUT_DP_MST) + if (intel_connector->mst_port) intel_dp_mst_info(m, intel_connector); else intel_dp_info(m, intel_connector); break; case DRM_MODE_CONNECTOR_HDMIA: - if (encoder->type == INTEL_OUTPUT_HDMI || - encoder->type == INTEL_OUTPUT_DDI) - intel_hdmi_info(m, intel_connector); + intel_hdmi_info(m, intel_connector); break; default: break; } seq_puts(m, "\tHDCP version: "); - if (intel_encoder_is_mst(encoder)) { + if (intel_connector->mst_port) { intel_hdcp_info(m, intel_connector, true); seq_puts(m, "\tMST Hub HDCP version: "); } @@ -645,51 +638,24 @@ static int i915_display_capabilities(struct seq_file *m, void *unused) static int i915_shared_dplls_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct drm_printer p = drm_seq_file_printer(m); struct intel_shared_dpll *pll; int i; drm_modeset_lock_all(&dev_priv->drm); - seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n", + drm_printf(&p, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n", dev_priv->display.dpll.ref_clks.nssc, dev_priv->display.dpll.ref_clks.ssc); for_each_shared_dpll(dev_priv, pll, i) { - seq_printf(m, "DPLL%i: %s, id: %i\n", pll->index, + drm_printf(&p, "DPLL%i: %s, id: %i\n", pll->index, pll->info->name, pll->info->id); - seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n", + drm_printf(&p, " pipe_mask: 0x%x, active: 0x%x, on: %s\n", pll->state.pipe_mask, pll->active_mask, str_yes_no(pll->on)); - seq_printf(m, " tracked hardware state:\n"); - seq_printf(m, " dpll: 0x%08x\n", pll->state.hw_state.dpll); - seq_printf(m, " dpll_md: 0x%08x\n", - pll->state.hw_state.dpll_md); - seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0); - seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1); - seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll); - seq_printf(m, " cfgcr0: 0x%08x\n", pll->state.hw_state.cfgcr0); - seq_printf(m, " cfgcr1: 0x%08x\n", pll->state.hw_state.cfgcr1); - seq_printf(m, " div0: 0x%08x\n", pll->state.hw_state.div0); - seq_printf(m, " mg_refclkin_ctl: 0x%08x\n", - pll->state.hw_state.mg_refclkin_ctl); - seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n", - pll->state.hw_state.mg_clktop2_coreclkctl1); - seq_printf(m, " mg_clktop2_hsclkctl: 0x%08x\n", - pll->state.hw_state.mg_clktop2_hsclkctl); - seq_printf(m, " mg_pll_div0: 0x%08x\n", - pll->state.hw_state.mg_pll_div0); - seq_printf(m, " mg_pll_div1: 0x%08x\n", - pll->state.hw_state.mg_pll_div1); - seq_printf(m, " mg_pll_lf: 0x%08x\n", - pll->state.hw_state.mg_pll_lf); - seq_printf(m, " mg_pll_frac_lock: 0x%08x\n", - pll->state.hw_state.mg_pll_frac_lock); - seq_printf(m, " mg_pll_ssc: 0x%08x\n", - pll->state.hw_state.mg_pll_ssc); - seq_printf(m, " mg_pll_bias: 0x%08x\n", - pll->state.hw_state.mg_pll_bias); - seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n", - pll->state.hw_state.mg_pll_tdc_coldst_bias); + drm_printf(&p, " tracked hardware state:\n"); + intel_dpll_dump_hw_state(dev_priv, &p, &pll->state.hw_state); } drm_modeset_unlock_all(&dev_priv->drm); @@ -1103,27 +1069,6 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) intel_display_debugfs_params(i915); } -static int i915_panel_show(struct seq_file *m, void *data) -{ - struct intel_connector *connector = m->private; - struct intel_dp *intel_dp = intel_attached_dp(connector); - - if (connector->base.status != connector_status_connected) - return -ENODEV; - - seq_printf(m, "Panel power up delay: %d\n", - intel_dp->pps.panel_power_up_delay); - seq_printf(m, "Panel power down delay: %d\n", - intel_dp->pps.panel_power_down_delay); - seq_printf(m, "Backlight on delay: %d\n", - intel_dp->pps.backlight_on_delay); - seq_printf(m, "Backlight off delay: %d\n", - intel_dp->pps.backlight_off_delay); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(i915_panel); - static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) { struct intel_connector *connector = m->private; @@ -1402,20 +1347,6 @@ out: drm_modeset_unlock(&i915->drm.mode_config.connection_mutex); return ret; } -static int i915_bigjoiner_enable_show(struct seq_file *m, void *data) -{ - struct intel_connector *connector = m->private; - struct drm_crtc *crtc; - - crtc = connector->base.state->crtc; - if (connector->base.status != connector_status_connected || !crtc) - return -ENODEV; - - seq_printf(m, "Bigjoiner enable: %d\n", connector->force_bigjoiner_enable); - - return 0; -} - static ssize_t i915_dsc_output_format_write(struct file *file, const char __user *ubuf, size_t len, loff_t *offp) @@ -1437,30 +1368,6 @@ static ssize_t i915_dsc_output_format_write(struct file *file, return len; } -static ssize_t i915_bigjoiner_enable_write(struct file *file, - const char __user *ubuf, - size_t len, loff_t *offp) -{ - struct seq_file *m = file->private_data; - struct intel_connector *connector = m->private; - struct drm_crtc *crtc; - bool bigjoiner_en = 0; - int ret; - - crtc = connector->base.state->crtc; - if (connector->base.status != connector_status_connected || !crtc) - return -ENODEV; - - ret = kstrtobool_from_user(ubuf, len, &bigjoiner_en); - if (ret < 0) - return ret; - - connector->force_bigjoiner_enable = bigjoiner_en; - *offp += len; - - return len; -} - static int i915_dsc_output_format_open(struct inode *inode, struct file *file) { @@ -1554,8 +1461,6 @@ static const struct file_operations i915_dsc_fractional_bpp_fops = { .write = i915_dsc_fractional_bpp_write }; -DEFINE_SHOW_STORE_ATTRIBUTE(i915_bigjoiner_enable); - /* * Returns the Current CRTC's bpc. * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc @@ -1608,12 +1513,9 @@ void intel_connector_debugfs_add(struct intel_connector *connector) return; intel_drrs_connector_debugfs_add(connector); + intel_pps_connector_debugfs_add(connector); intel_psr_connector_debugfs_add(connector); - if (connector_type == DRM_MODE_CONNECTOR_eDP) - debugfs_create_file("i915_panel_timings", 0444, root, - connector, &i915_panel_fops); - if (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_HDMIA || connector_type == DRM_MODE_CONNECTOR_HDMIB) { @@ -1640,8 +1542,8 @@ void intel_connector_debugfs_add(struct intel_connector *connector) if (DISPLAY_VER(i915) >= 11 && (connector_type == DRM_MODE_CONNECTOR_DisplayPort || connector_type == DRM_MODE_CONNECTOR_eDP)) { - debugfs_create_file("i915_bigjoiner_force_enable", 0644, root, - connector, &i915_bigjoiner_enable_fops); + debugfs_create_bool("i915_bigjoiner_force_enable", 0644, root, + &connector->force_bigjoiner_enable); } if (connector_type == DRM_MODE_CONNECTOR_DSI || diff --git a/drivers/gpu/drm/i915/display/intel_display_device.c b/drivers/gpu/drm/i915/display/intel_display_device.c index c02d79b50006..120e209ee74a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.c +++ b/drivers/gpu/drm/i915/display/intel_display_device.c @@ -17,6 +17,9 @@ #include "intel_display_reg_defs.h" #include "intel_fbc.h" +__diag_push(); +__diag_ignore_all("-Woverride-init", "Allow field initialization overrides for display info"); + static const struct intel_display_device_info no_display = {}; #define PIPE_A_OFFSET 0x70000 @@ -768,6 +771,8 @@ static const struct intel_display_device_info xe2_lpd_display = { BIT(INTEL_FBC_C) | BIT(INTEL_FBC_D), }; +__diag_pop(); + /* * Separate detection for no display cases to keep the display id array simple. * @@ -922,6 +927,9 @@ void intel_display_device_probe(struct drm_i915_private *i915) const struct intel_display_device_info *info; u16 ver, rel, step; + /* Add drm device backpointer as early as possible. */ + i915->display.drm = &i915->drm; + if (HAS_GMD_ID(i915)) info = probe_gmdid_display(i915, &ver, &rel, &step); else diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h index fe4268813786..17ddf82f0b6e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_device.h +++ b/drivers/gpu/drm/i915/display/intel_display_device.h @@ -8,6 +8,7 @@ #include +#include "intel_display_conversion.h" #include "intel_display_limits.h" struct drm_i915_private; @@ -47,6 +48,7 @@ struct drm_printer; #define HAS_DPT(i915) (DISPLAY_VER(i915) >= 13) #define HAS_DSB(i915) (DISPLAY_INFO(i915)->has_dsb) #define HAS_DSC(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dsc) +#define HAS_DSC_MST(__i915) (DISPLAY_VER(__i915) >= 12 && HAS_DSC(__i915)) #define HAS_FBC(i915) (DISPLAY_RUNTIME_INFO(i915)->fbc_mask != 0) #define HAS_FPGA_DBG_UNCLAIMED(i915) (DISPLAY_INFO(i915)->has_fpga_dbg) #define HAS_FW_BLC(i915) (DISPLAY_VER(i915) >= 3) @@ -68,6 +70,7 @@ struct drm_printer; #define HAS_TRANSCODER(i915, trans) ((DISPLAY_RUNTIME_INFO(i915)->cpu_transcoder_mask & \ BIT(trans)) != 0) #define HAS_VRR(i915) (DISPLAY_VER(i915) >= 11) +#define HAS_AS_SDP(i915) (DISPLAY_VER(i915) >= 13) #define INTEL_NUM_PIPES(i915) (hweight8(DISPLAY_RUNTIME_INFO(i915)->pipe_mask)) #define I915_HAS_HOTPLUG(i915) (DISPLAY_INFO(i915)->has_hotplug) #define OVERLAY_NEEDS_PHYSICAL(i915) (DISPLAY_INFO(i915)->overlay_needs_physical) @@ -98,8 +101,8 @@ struct drm_printer; (IS_DISPLAY_IP_RANGE((__i915), (ipver), (ipver)) && \ IS_DISPLAY_STEP((__i915), (from), (until))) -#define DISPLAY_INFO(i915) ((i915)->display.info.__device_info) -#define DISPLAY_RUNTIME_INFO(i915) (&(i915)->display.info.__runtime_info) +#define DISPLAY_INFO(i915) (__to_intel_display(i915)->info.__device_info) +#define DISPLAY_RUNTIME_INFO(i915) (&__to_intel_display(i915)->info.__runtime_info) #define DISPLAY_VER(i915) (DISPLAY_RUNTIME_INFO(i915)->ip.ver) #define DISPLAY_VER_FULL(i915) IP_VER(DISPLAY_RUNTIME_INFO(i915)->ip.ver, \ diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c index 87dd07e0d138..1b24339e4ab6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_driver.c +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c @@ -198,11 +198,13 @@ void intel_display_driver_early_probe(struct drm_i915_private *i915) intel_dpll_init_clock_hook(i915); intel_init_display_hooks(i915); intel_fdi_init_hook(i915); + intel_dmc_wl_init(&i915->display); } /* part #1: call before irq install */ int intel_display_driver_probe_noirq(struct drm_i915_private *i915) { + struct intel_display *display = &i915->display; int ret; if (i915_inject_probe_failure(i915)) @@ -261,7 +263,7 @@ int intel_display_driver_probe_noirq(struct drm_i915_private *i915) if (ret) goto cleanup_vga_client_pw_domain_dmc; - intel_init_quirks(i915); + intel_init_quirks(display); intel_fbc_init(i915); diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index f846c5b108b5..c337e0597541 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -117,13 +117,14 @@ static void bdw_update_pipe_irq(struct drm_i915_private *dev_priv, if (drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv))) return; - new_val = dev_priv->de_irq_mask[pipe]; + new_val = dev_priv->display.irq.de_irq_mask[pipe]; new_val &= ~interrupt_mask; new_val |= (~enabled_irq_mask & interrupt_mask); - if (new_val != dev_priv->de_irq_mask[pipe]) { - dev_priv->de_irq_mask[pipe] = new_val; - intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]); + if (new_val != dev_priv->display.irq.de_irq_mask[pipe]) { + dev_priv->display.irq.de_irq_mask[pipe] = new_val; + intel_uncore_write(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe), + dev_priv->display.irq.de_irq_mask[pipe]); intel_uncore_posting_read(&dev_priv->uncore, GEN8_DE_PIPE_IMR(pipe)); } } @@ -179,7 +180,7 @@ void ibx_disable_display_interrupt(struct drm_i915_private *i915, u32 bits) u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, enum pipe pipe) { - u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; + u32 status_mask = dev_priv->display.irq.pipestat_irq_mask[pipe]; u32 enable_mask = status_mask << 16; lockdep_assert_held(&dev_priv->irq_lock); @@ -233,10 +234,10 @@ void i915_enable_pipestat(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->irq_lock); drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); - if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) + if ((dev_priv->display.irq.pipestat_irq_mask[pipe] & status_mask) == status_mask) return; - dev_priv->pipestat_irq_mask[pipe] |= status_mask; + dev_priv->display.irq.pipestat_irq_mask[pipe] |= status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); @@ -256,10 +257,10 @@ void i915_disable_pipestat(struct drm_i915_private *dev_priv, lockdep_assert_held(&dev_priv->irq_lock); drm_WARN_ON(&dev_priv->drm, !intel_irqs_enabled(dev_priv)); - if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) + if ((dev_priv->display.irq.pipestat_irq_mask[pipe] & status_mask) == 0) return; - dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; + dev_priv->display.irq.pipestat_irq_mask[pipe] &= ~status_mask; enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); intel_uncore_write(&dev_priv->uncore, reg, enable_mask | status_mask); @@ -401,7 +402,7 @@ void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) PIPESTAT_INT_STATUS_MASK | PIPE_FIFO_UNDERRUN_STATUS); - dev_priv->pipestat_irq_mask[pipe] = 0; + dev_priv->display.irq.pipestat_irq_mask[pipe] = 0; } } @@ -412,7 +413,7 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, spin_lock(&dev_priv->irq_lock); - if (!dev_priv->display_irqs_enabled) { + if (!dev_priv->display.irq.display_irqs_enabled) { spin_unlock(&dev_priv->irq_lock); return; } @@ -445,7 +446,7 @@ void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, break; } if (iir & iir_bit) - status_mask |= dev_priv->pipestat_irq_mask[pipe]; + status_mask |= dev_priv->display.irq.pipestat_irq_mask[pipe]; if (!status_mask) continue; @@ -1203,7 +1204,7 @@ int i8xx_enable_vblank(struct drm_crtc *crtc) int i915gm_enable_vblank(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc->dev); /* * Vblank interrupts fail to wake the device up from C2+. @@ -1211,8 +1212,8 @@ int i915gm_enable_vblank(struct drm_crtc *crtc) * the problem. There is a small power cost so we do this * only when vblank interrupts are actually enabled. */ - if (dev_priv->vblank_enabled++ == 0) - intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + if (i915->display.irq.vblank_enabled++ == 0) + intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_ENABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); return i8xx_enable_vblank(crtc); } @@ -1315,12 +1316,12 @@ void i8xx_disable_vblank(struct drm_crtc *crtc) void i915gm_disable_vblank(struct drm_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct drm_i915_private *i915 = to_i915(crtc->dev); i8xx_disable_vblank(crtc); - if (--dev_priv->vblank_enabled == 0) - intel_uncore_write(&dev_priv->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); + if (--i915->display.irq.vblank_enabled == 0) + intel_uncore_write(&i915->uncore, SCPD0, _MASKED_BIT_DISABLE(CSTATE_RENDER_CLOCK_GATE_DISABLE)); } void i965_disable_vblank(struct drm_crtc *crtc) @@ -1497,8 +1498,8 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, for_each_pipe_masked(dev_priv, pipe, pipe_mask) GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, - dev_priv->de_irq_mask[pipe], - ~dev_priv->de_irq_mask[pipe] | extra_ier); + dev_priv->display.irq.de_irq_mask[pipe], + ~dev_priv->display.irq.de_irq_mask[pipe] | extra_ier); spin_unlock_irq(&dev_priv->irq_lock); } @@ -1558,10 +1559,10 @@ void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv) { lockdep_assert_held(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) + if (dev_priv->display.irq.display_irqs_enabled) return; - dev_priv->display_irqs_enabled = true; + dev_priv->display.irq.display_irqs_enabled = true; if (intel_irqs_enabled(dev_priv)) { vlv_display_irq_reset(dev_priv); @@ -1573,10 +1574,10 @@ void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv) { lockdep_assert_held(&dev_priv->irq_lock); - if (!dev_priv->display_irqs_enabled) + if (!dev_priv->display.irq.display_irqs_enabled) return; - dev_priv->display_irqs_enabled = false; + dev_priv->display.irq.display_irqs_enabled = false; if (intel_irqs_enabled(dev_priv)) vlv_display_irq_reset(dev_priv); @@ -1694,12 +1695,12 @@ void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) } for_each_pipe(dev_priv, pipe) { - dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; + dev_priv->display.irq.de_irq_mask[pipe] = ~de_pipe_masked; if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_INIT_NDX(uncore, DE_PIPE, pipe, - dev_priv->de_irq_mask[pipe], + dev_priv->display.irq.de_irq_mask[pipe], de_pipe_enables); } @@ -1770,9 +1771,9 @@ void intel_display_irq_init(struct drm_i915_private *i915) * domain. We defer setting up the display irqs in this case to the * runtime pm. */ - i915->display_irqs_enabled = true; + i915->display.irq.display_irqs_enabled = true; if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) - i915->display_irqs_enabled = false; + i915->display.irq.display_irqs_enabled = false; intel_hotplug_irq_init(i915); } diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index 11e03cfb774d..1799a6643128 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -27,6 +27,10 @@ static struct intel_display_params intel_display_modparams __read_mostly = { * debugfs mode to 0. */ +intel_display_param_named_unsafe(dmc_firmware_path, charp, 0400, + "DMC firmware path to use instead of the default one. " + "Use /dev/null to disable DMC and runtime PM."); + intel_display_param_named_unsafe(vbt_firmware, charp, 0400, "Load VBT from specified file under /lib/firmware"); @@ -116,6 +120,11 @@ intel_display_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, "(0=disabled, 1=enabled) " "Default: 1"); +intel_display_param_named_unsafe(enable_dmc_wl, bool, 0400, + "Enable DMC wakelock " + "(0=disabled, 1=enabled) " + "Default: 0"); + __maybe_unused static void _param_print_bool(struct drm_printer *p, const char *driver_name, const char *name, bool val) diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h index 6206cc51df04..1208a62c16d2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.h +++ b/drivers/gpu/drm/i915/display/intel_display_params.h @@ -24,6 +24,7 @@ struct drm_i915_private; * debugfs file */ #define INTEL_DISPLAY_PARAMS_FOR_EACH(param) \ + param(char *, dmc_firmware_path, NULL, 0400) \ param(char *, vbt_firmware, NULL, 0400) \ param(int, lvds_channel_mode, 0, 0400) \ param(int, panel_use_ssc, -1, 0600) \ @@ -46,6 +47,7 @@ struct drm_i915_private; param(int, enable_psr, -1, 0600) \ param(bool, psr_safest_params, false, 0400) \ param(bool, enable_psr2_sel_fetch, true, 0400) \ + param(bool, enable_dmc_wl, false, 0400) \ #define MEMBER(T, member, ...) T member; struct intel_display_params { diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 06900ff307b2..e8a6e53fd551 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -17,6 +17,7 @@ #include "intel_dkl_phy.h" #include "intel_dkl_phy_regs.h" #include "intel_dmc.h" +#include "intel_dmc_wl.h" #include "intel_dp_aux_regs.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" @@ -199,6 +200,9 @@ static void hsw_power_well_pre_disable(struct drm_i915_private *dev_priv, gen8_irq_power_well_pre_disable(dev_priv, irq_pipe_mask); } +#define ICL_AUX_PW_TO_PHY(pw_idx) \ + ((pw_idx) - ICL_PW_CTL_IDX_AUX_A + PHY_A) + #define ICL_AUX_PW_TO_CH(pw_idx) \ ((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A) @@ -217,27 +221,22 @@ static struct intel_digital_port * aux_ch_to_digital_port(struct drm_i915_private *dev_priv, enum aux_ch aux_ch) { - struct intel_digital_port *dig_port = NULL; struct intel_encoder *encoder; for_each_intel_encoder(&dev_priv->drm, encoder) { + struct intel_digital_port *dig_port; + /* We'll check the MST primary port */ if (encoder->type == INTEL_OUTPUT_DP_MST) continue; dig_port = enc_to_dig_port(encoder); - if (!dig_port) - continue; - if (dig_port->aux_ch != aux_ch) { - dig_port = NULL; - continue; - } - - break; + if (dig_port && dig_port->aux_ch == aux_ch) + return dig_port; } - return dig_port; + return NULL; } static enum phy icl_aux_pw_to_phy(struct drm_i915_private *i915, @@ -253,7 +252,7 @@ static enum phy icl_aux_pw_to_phy(struct drm_i915_private *i915, * as HDMI-only and routed to a combo PHY, the encoder either won't be * present at all or it will not have an aux_ch assigned. */ - return dig_port ? intel_port_to_phy(i915, dig_port->base.port) : PHY_NONE; + return dig_port ? intel_encoder_to_phy(&dig_port->base) : PHY_NONE; } static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, @@ -396,17 +395,11 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv, hsw_wait_for_power_well_disable(dev_priv, power_well); } -static bool intel_port_is_edp(struct drm_i915_private *i915, enum port port) +static bool intel_aux_ch_is_edp(struct drm_i915_private *i915, enum aux_ch aux_ch) { - struct intel_encoder *encoder; + struct intel_digital_port *dig_port = aux_ch_to_digital_port(i915, aux_ch); - for_each_intel_encoder(&i915->drm, encoder) { - if (encoder->type == INTEL_OUTPUT_EDP && - encoder->port == port) - return true; - } - - return false; + return dig_port && dig_port->base.type == INTEL_OUTPUT_EDP; } static void @@ -415,24 +408,25 @@ icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, { const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = i915_power_well_instance(power_well)->hsw.idx; - enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); intel_de_rmw(dev_priv, regs->driver, 0, HSW_PWR_WELL_CTL_REQ(pw_idx)); - /* FIXME this is a mess */ - if (phy != PHY_NONE) - intel_de_rmw(dev_priv, ICL_PORT_CL_DW12(phy), - 0, ICL_LANE_ENABLE_AUX); + /* + * FIXME not sure if we should derive the PHY from the pw_idx, or + * from the VBT defined AUX_CH->DDI->PHY mapping. + */ + intel_de_rmw(dev_priv, ICL_PORT_CL_DW12(ICL_AUX_PW_TO_PHY(pw_idx)), + 0, ICL_LANE_ENABLE_AUX); hsw_wait_for_power_well_enable(dev_priv, power_well, false); /* Display WA #1178: icl */ if (pw_idx >= ICL_PW_CTL_IDX_AUX_A && pw_idx <= ICL_PW_CTL_IDX_AUX_B && - !intel_port_is_edp(dev_priv, (enum port)phy)) - intel_de_rmw(dev_priv, ICL_AUX_ANAOVRD1(pw_idx), - 0, ICL_AUX_ANAOVRD1_ENABLE | ICL_AUX_ANAOVRD1_LDO_BYPASS); + !intel_aux_ch_is_edp(dev_priv, ICL_AUX_PW_TO_CH(pw_idx))) + intel_de_rmw(dev_priv, ICL_PORT_TX_DW6_AUX(ICL_AUX_PW_TO_PHY(pw_idx)), + 0, O_FUNC_OVRD_EN | O_LDO_BYPASS_CRI); } static void @@ -441,14 +435,15 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, { const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = i915_power_well_instance(power_well)->hsw.idx; - enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); - /* FIXME this is a mess */ - if (phy != PHY_NONE) - intel_de_rmw(dev_priv, ICL_PORT_CL_DW12(phy), - ICL_LANE_ENABLE_AUX, 0); + /* + * FIXME not sure if we should derive the PHY from the pw_idx, or + * from the VBT defined AUX_CH->DDI->PHY mapping. + */ + intel_de_rmw(dev_priv, ICL_PORT_CL_DW12(ICL_AUX_PW_TO_PHY(pw_idx)), + ICL_LANE_ENABLE_AUX, 0); intel_de_rmw(dev_priv, regs->driver, HSW_PWR_WELL_CTL_REQ(pw_idx), 0); @@ -827,6 +822,8 @@ void gen9_enable_dc5(struct drm_i915_private *dev_priv) intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, SKL_SELECT_ALTERNATE_DC_EXIT); + intel_dmc_wl_enable(&dev_priv->display); + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC5); } @@ -856,6 +853,8 @@ void skl_enable_dc6(struct drm_i915_private *dev_priv) intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, SKL_SELECT_ALTERNATE_DC_EXIT); + intel_dmc_wl_enable(&dev_priv->display); + gen9_set_dc_state(dev_priv, DC_STATE_EN_UPTO_DC6); } @@ -906,39 +905,39 @@ static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - bxt_ddi_phy_init(dev_priv, i915_power_well_instance(power_well)->bxt.phy); + bxt_dpio_phy_init(dev_priv, i915_power_well_instance(power_well)->bxt.phy); } static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - bxt_ddi_phy_uninit(dev_priv, i915_power_well_instance(power_well)->bxt.phy); + bxt_dpio_phy_uninit(dev_priv, i915_power_well_instance(power_well)->bxt.phy); } static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - return bxt_ddi_phy_is_enabled(dev_priv, i915_power_well_instance(power_well)->bxt.phy); + return bxt_dpio_phy_is_enabled(dev_priv, i915_power_well_instance(power_well)->bxt.phy); } -static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) +static void bxt_verify_dpio_phy_power_wells(struct drm_i915_private *dev_priv) { struct i915_power_well *power_well; power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A); if (intel_power_well_refcount(power_well) > 0) - bxt_ddi_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy); + bxt_dpio_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy); power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC); if (intel_power_well_refcount(power_well) > 0) - bxt_ddi_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy); + bxt_dpio_phy_verify_state(dev_priv, i915_power_well_instance(power_well)->bxt.phy); if (IS_GEMINILAKE(dev_priv)) { power_well = lookup_power_well(dev_priv, GLK_DISP_PW_DPIO_CMN_C); if (intel_power_well_refcount(power_well) > 0) - bxt_ddi_phy_verify_state(dev_priv, - i915_power_well_instance(power_well)->bxt.phy); + bxt_dpio_phy_verify_state(dev_priv, + i915_power_well_instance(power_well)->bxt.phy); } } @@ -976,16 +975,18 @@ void gen9_disable_dc_states(struct drm_i915_private *dev_priv) if (!HAS_DISPLAY(dev_priv)) return; + intel_dmc_wl_disable(&dev_priv->display); + intel_cdclk_get_cdclk(dev_priv, &cdclk_config); /* Can't read out voltage_level so can't use intel_cdclk_changed() */ drm_WARN_ON(&dev_priv->drm, - intel_cdclk_needs_modeset(&dev_priv->display.cdclk.hw, + intel_cdclk_clock_changed(&dev_priv->display.cdclk.hw, &cdclk_config)); gen9_assert_dbuf_enabled(dev_priv); if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - bxt_verify_ddi_phy_power_wells(dev_priv); + bxt_verify_dpio_phy_power_wells(dev_priv); if (DISPLAY_VER(dev_priv) >= 11) /* @@ -1396,8 +1397,8 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) * The PHY may be busy with some initial calibration and whatnot, * so the power state can take a while to actually change. */ - if (intel_de_wait_for_register(dev_priv, DISPLAY_PHY_STATUS, - phy_status_mask, phy_status, 10)) + if (intel_de_wait(dev_priv, DISPLAY_PHY_STATUS, + phy_status_mask, phy_status, 10)) drm_err(&dev_priv->drm, "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n", intel_de_read(dev_priv, DISPLAY_PHY_STATUS) & phy_status_mask, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9104f18753b4..62f7a30c37dc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -661,7 +661,8 @@ struct intel_digital_connector_state { int broadcast_rgb; }; -#define to_intel_digital_connector_state(x) container_of(x, struct intel_digital_connector_state, base) +#define to_intel_digital_connector_state(conn_state) \ + container_of_const((conn_state), struct intel_digital_connector_state, base) struct dpll { /* given values */ @@ -1003,18 +1004,6 @@ enum intel_output_format { INTEL_OUTPUT_FORMAT_YCBCR444, }; -struct intel_mpllb_state { - u32 clock; /* in KHz */ - u32 ref_control; - u32 mpllb_cp; - u32 mpllb_div; - u32 mpllb_div2; - u32 mpllb_fracn1; - u32 mpllb_fracn2; - u32 mpllb_sscen; - u32 mpllb_sscstep; -}; - /* Used by dp and fdi links */ struct intel_link_m_n { u32 tu; @@ -1030,31 +1019,6 @@ struct intel_csc_matrix { u16 postoff[3]; }; -struct intel_c10pll_state { - u32 clock; /* in KHz */ - u8 tx; - u8 cmn; - u8 pll[20]; -}; - -struct intel_c20pll_state { - u32 clock; /* in kHz */ - u16 tx[3]; - u16 cmn[4]; - union { - u16 mplla[10]; - u16 mpllb[11]; - }; -}; - -struct intel_cx0pll_state { - union { - struct intel_c10pll_state c10; - struct intel_c20pll_state c20; - }; - bool ssc_enabled; -}; - struct intel_crtc_state { /* * uapi (drm) state. This is the software state shown to userspace. @@ -1199,11 +1163,7 @@ struct intel_crtc_state { struct intel_shared_dpll *shared_dpll; /* Actual register state of the dpll, for shared dpll cross-checking. */ - union { - struct intel_dpll_hw_state dpll_hw_state; - struct intel_mpllb_state mpllb_state; - struct intel_cx0pll_state cx0pll_state; - }; + struct intel_dpll_hw_state dpll_hw_state; /* * ICL reserved DPLLs for the CRTC/port. The active PLL is selected by @@ -1346,6 +1306,7 @@ struct intel_crtc_state { union hdmi_infoframe hdmi; union hdmi_infoframe drm; struct drm_dp_vsc_sdp vsc; + struct drm_dp_as_sdp as_sdp; } infoframes; u8 eld[MAX_ELD_BYTES]; @@ -1423,6 +1384,8 @@ struct intel_crtc_state { u32 psr2_man_track_ctl; + u32 pipe_srcsz_early_tpt; + struct drm_rect psr2_su_area; /* Variable Refresh Rate state */ @@ -1430,6 +1393,7 @@ struct intel_crtc_state { bool enable, in_range; u8 pipeline_full; u16 flipline, vmin, vmax, guardband; + u32 vsync_end, vsync_start; } vrr; /* Stream Splitter for eDP MSO */ @@ -1618,12 +1582,17 @@ struct intel_watermark_params { #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) -#define to_intel_crtc_state(x) container_of(x, struct intel_crtc_state, uapi) #define to_intel_connector(x) container_of(x, struct intel_connector, base) #define to_intel_encoder(x) container_of(x, struct intel_encoder, base) -#define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) #define to_intel_plane(x) container_of(x, struct intel_plane, base) -#define to_intel_plane_state(x) container_of(x, struct intel_plane_state, uapi) + +#define to_intel_crtc_state(crtc_state) \ + container_of_const((crtc_state), struct intel_crtc_state, uapi) +#define to_intel_plane_state(plane_state) \ + container_of_const((plane_state), struct intel_plane_state, uapi) +#define to_intel_framebuffer(fb) \ + container_of_const((fb), struct intel_framebuffer, base) + #define intel_fb_obj(x) ((x) ? to_intel_bo((x)->obj[0]) : NULL) struct intel_hdmi { @@ -1738,6 +1707,8 @@ struct intel_psr { /* LNL and beyond */ u8 check_entry_lines; + u8 silence_period_sym_clocks; + u8 lfps_half_cycle_num_of_syms; } alpm_parameters; ktime_t last_entry_attempt; @@ -1799,6 +1770,7 @@ struct intel_dp { bool is_mst; int active_mst_links; + enum drm_dp_mst_mode mst_detect; /* connector directly attached - won't be use for modeset in mst world */ struct intel_connector *attached_connector; @@ -2184,4 +2156,41 @@ static inline int to_bpp_x16(int bpp) return bpp << 4; } +/* + * Conversion functions/macros from various pointer types to struct + * intel_display pointer. + */ +#define __drm_device_to_intel_display(p) \ + (&to_i915(p)->display) +#define __intel_connector_to_intel_display(p) \ + __drm_device_to_intel_display((p)->base.dev) +#define __intel_crtc_to_intel_display(p) \ + __drm_device_to_intel_display((p)->base.dev) +#define __intel_crtc_state_to_intel_display(p) \ + __drm_device_to_intel_display((p)->uapi.crtc->dev) +#define __intel_digital_port_to_intel_display(p) \ + __drm_device_to_intel_display((p)->base.base.dev) +#define __intel_dp_to_intel_display(p) \ + __drm_device_to_intel_display(dp_to_dig_port(p)->base.base.dev) +#define __intel_encoder_to_intel_display(p) \ + __drm_device_to_intel_display((p)->base.dev) +#define __intel_hdmi_to_intel_display(p) \ + __drm_device_to_intel_display(hdmi_to_dig_port(p)->base.base.dev) + +/* Helper for generic association. Map types to conversion functions/macros. */ +#define __assoc(type, p) \ + struct type: __##type##_to_intel_display((struct type *)(p)) + +/* Convert various pointer types to struct intel_display pointer. */ +#define to_intel_display(p) \ + _Generic(*p, \ + __assoc(drm_device, p), \ + __assoc(intel_connector, p), \ + __assoc(intel_crtc, p), \ + __assoc(intel_crtc_state, p), \ + __assoc(intel_digital_port, p), \ + __assoc(intel_dp, p), \ + __assoc(intel_encoder, p), \ + __assoc(intel_hdmi, p)) + #endif /* __INTEL_DISPLAY_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_display_wa.c b/drivers/gpu/drm/i915/display/intel_display_wa.c index ac136fd992ba..e5a8022db664 100644 --- a/drivers/gpu/drm/i915/display/intel_display_wa.c +++ b/drivers/gpu/drm/i915/display/intel_display_wa.c @@ -10,20 +10,12 @@ static void gen11_display_wa_apply(struct drm_i915_private *i915) { - /* Wa_1409120013 */ - intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A), - DPFC_CHICKEN_COMP_DUMMY_PIXEL); - /* Wa_14010594013 */ intel_de_rmw(i915, GEN8_CHICKEN_DCPR_1, 0, ICL_DELAY_PMRSP); } static void xe_d_display_wa_apply(struct drm_i915_private *i915) { - /* Wa_1409120013 */ - intel_de_write(i915, ILK_DPFC_CHICKEN(INTEL_FBC_A), - DPFC_CHICKEN_COMP_DUMMY_PIXEL); - /* Wa_14013723622 */ intel_de_rmw(i915, CLKREQ_POLICY, CLKREQ_POLICY_MEM_UP_OVRD, 0); } diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 835781624482..cbd2ac5671b1 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -22,6 +22,7 @@ * */ +#include #include #include "i915_drv.h" @@ -38,6 +39,8 @@ * low-power state and comes back to normal. */ +#define INTEL_DMC_FIRMWARE_URL "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git" + enum intel_dmc_id { DMC_FW_MAIN = 0, DMC_FW_PIPEA, @@ -71,6 +74,21 @@ static struct intel_dmc *i915_to_dmc(struct drm_i915_private *i915) return i915->display.dmc.dmc; } +static const char *dmc_firmware_param(struct drm_i915_private *i915) +{ + const char *p = i915->display.params.dmc_firmware_path; + + return p && *p ? p : NULL; +} + +static bool dmc_firmware_param_disabled(struct drm_i915_private *i915) +{ + const char *p = dmc_firmware_param(i915); + + /* Magic path to indicate disabled */ + return p && !strcmp(p, "/dev/null"); +} + #define DMC_VERSION(major, minor) ((major) << 16 | (minor)) #define DMC_VERSION_MAJOR(version) ((version) >> 16) #define DMC_VERSION_MINOR(version) ((version) & 0xffff) @@ -89,10 +107,14 @@ static struct intel_dmc *i915_to_dmc(struct drm_i915_private *i915) __stringify(major) "_" \ __stringify(minor) ".bin" +#define XE2LPD_DMC_MAX_FW_SIZE 0x8000 #define XELPDP_DMC_MAX_FW_SIZE 0x7000 #define DISPLAY_VER13_DMC_MAX_FW_SIZE 0x20000 #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE +#define XE2LPD_DMC_PATH DMC_PATH(xe2lpd) +MODULE_FIRMWARE(XE2LPD_DMC_PATH); + #define MTL_DMC_PATH DMC_PATH(mtl) MODULE_FIRMWARE(MTL_DMC_PATH); @@ -136,6 +158,59 @@ MODULE_FIRMWARE(SKL_DMC_PATH); #define BXT_DMC_MAX_FW_SIZE 0x3000 MODULE_FIRMWARE(BXT_DMC_PATH); +static const char *dmc_firmware_default(struct drm_i915_private *i915, u32 *size) +{ + const char *fw_path = NULL; + u32 max_fw_size = 0; + + if (DISPLAY_VER_FULL(i915) == IP_VER(20, 0)) { + fw_path = XE2LPD_DMC_PATH; + max_fw_size = XE2LPD_DMC_MAX_FW_SIZE; + } else if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) { + fw_path = MTL_DMC_PATH; + max_fw_size = XELPDP_DMC_MAX_FW_SIZE; + } else if (IS_DG2(i915)) { + fw_path = DG2_DMC_PATH; + max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; + } else if (IS_ALDERLAKE_P(i915)) { + fw_path = ADLP_DMC_PATH; + max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; + } else if (IS_ALDERLAKE_S(i915)) { + fw_path = ADLS_DMC_PATH; + max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; + } else if (IS_DG1(i915)) { + fw_path = DG1_DMC_PATH; + max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; + } else if (IS_ROCKETLAKE(i915)) { + fw_path = RKL_DMC_PATH; + max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; + } else if (IS_TIGERLAKE(i915)) { + fw_path = TGL_DMC_PATH; + max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; + } else if (DISPLAY_VER(i915) == 11) { + fw_path = ICL_DMC_PATH; + max_fw_size = ICL_DMC_MAX_FW_SIZE; + } else if (IS_GEMINILAKE(i915)) { + fw_path = GLK_DMC_PATH; + max_fw_size = GLK_DMC_MAX_FW_SIZE; + } else if (IS_KABYLAKE(i915) || + IS_COFFEELAKE(i915) || + IS_COMETLAKE(i915)) { + fw_path = KBL_DMC_PATH; + max_fw_size = KBL_DMC_MAX_FW_SIZE; + } else if (IS_SKYLAKE(i915)) { + fw_path = SKL_DMC_PATH; + max_fw_size = SKL_DMC_MAX_FW_SIZE; + } else if (IS_BROXTON(i915)) { + fw_path = BXT_DMC_PATH; + max_fw_size = BXT_DMC_MAX_FW_SIZE; + } + + *size = max_fw_size; + + return fw_path; +} + #define DMC_DEFAULT_FW_OFFSET 0xFFFFFFFF #define PACKAGE_MAX_FW_INFO_ENTRIES 20 #define PACKAGE_V2_MAX_FW_INFO_ENTRIES 32 @@ -546,6 +621,8 @@ void intel_dmc_disable_program(struct drm_i915_private *i915) pipedmc_clock_gating_wa(i915, true); disable_all_event_handlers(i915); pipedmc_clock_gating_wa(i915, false); + + intel_dmc_wl_disable(&i915->display); } void assert_dmc_loaded(struct drm_i915_private *i915) @@ -845,7 +922,7 @@ static u32 parse_dmc_fw_css(struct intel_dmc *dmc, return sizeof(struct intel_css_header); } -static void parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw) +static int parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw) { struct drm_i915_private *i915 = dmc->i915; struct intel_css_header *css_header; @@ -858,13 +935,13 @@ static void parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw) u32 r, offset; if (!fw) - return; + return -EINVAL; /* Extract CSS Header information */ css_header = (struct intel_css_header *)fw->data; r = parse_dmc_fw_css(dmc, css_header, fw->size); if (!r) - return; + return -EINVAL; readcount += r; @@ -872,7 +949,7 @@ static void parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw) package_header = (struct intel_package_header *)&fw->data[readcount]; r = parse_dmc_fw_package(dmc, package_header, si, fw->size - readcount); if (!r) - return; + return -EINVAL; readcount += r; @@ -889,6 +966,13 @@ static void parse_dmc_fw(struct intel_dmc *dmc, const struct firmware *fw) dmc_header = (struct intel_dmc_header_base *)&fw->data[offset]; parse_dmc_fw_header(dmc, dmc_header, fw->size - offset, dmc_id); } + + if (!intel_dmc_has_payload(i915)) { + drm_err(&i915->drm, "DMC firmware main program not found\n"); + return -ENOENT; + } + + return 0; } static void intel_dmc_runtime_pm_get(struct drm_i915_private *i915) @@ -923,7 +1007,7 @@ static void dmc_load_work_fn(struct work_struct *work) err = request_firmware(&fw, dmc->fw_path, i915->drm.dev); - if (err == -ENOENT && !i915->params.dmc_firmware_path) { + if (err == -ENOENT && !dmc_firmware_param(i915)) { fallback_path = dmc_fallback_path(i915); if (fallback_path) { drm_dbg_kms(&i915->drm, "%s not found, falling back to %s\n", @@ -934,24 +1018,31 @@ static void dmc_load_work_fn(struct work_struct *work) } } - parse_dmc_fw(dmc, fw); - - if (intel_dmc_has_payload(i915)) { - intel_dmc_load_program(i915); - intel_dmc_runtime_pm_put(i915); - - drm_info(&i915->drm, "Finished loading DMC firmware %s (v%u.%u)\n", - dmc->fw_path, DMC_VERSION_MAJOR(dmc->version), - DMC_VERSION_MINOR(dmc->version)); - } else { + if (err) { drm_notice(&i915->drm, - "Failed to load DMC firmware %s." - " Disabling runtime power management.\n", - dmc->fw_path); + "Failed to load DMC firmware %s (%pe). Disabling runtime power management.\n", + dmc->fw_path, ERR_PTR(err)); drm_notice(&i915->drm, "DMC firmware homepage: %s", - INTEL_UC_FIRMWARE_URL); + INTEL_DMC_FIRMWARE_URL); + return; } + err = parse_dmc_fw(dmc, fw); + if (err) { + drm_notice(&i915->drm, + "Failed to parse DMC firmware %s (%pe). Disabling runtime power management.\n", + dmc->fw_path, ERR_PTR(err)); + goto out; + } + + intel_dmc_load_program(i915); + intel_dmc_runtime_pm_put(i915); + + drm_info(&i915->drm, "Finished loading DMC firmware %s (v%u.%u)\n", + dmc->fw_path, DMC_VERSION_MAJOR(dmc->version), + DMC_VERSION_MINOR(dmc->version)); + +out: release_firmware(fw); } @@ -987,55 +1078,15 @@ void intel_dmc_init(struct drm_i915_private *i915) INIT_WORK(&dmc->work, dmc_load_work_fn); - if (DISPLAY_VER_FULL(i915) == IP_VER(14, 0)) { - dmc->fw_path = MTL_DMC_PATH; - dmc->max_fw_size = XELPDP_DMC_MAX_FW_SIZE; - } else if (IS_DG2(i915)) { - dmc->fw_path = DG2_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; - } else if (IS_ALDERLAKE_P(i915)) { - dmc->fw_path = ADLP_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER13_DMC_MAX_FW_SIZE; - } else if (IS_ALDERLAKE_S(i915)) { - dmc->fw_path = ADLS_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (IS_DG1(i915)) { - dmc->fw_path = DG1_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (IS_ROCKETLAKE(i915)) { - dmc->fw_path = RKL_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (IS_TIGERLAKE(i915)) { - dmc->fw_path = TGL_DMC_PATH; - dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (DISPLAY_VER(i915) == 11) { - dmc->fw_path = ICL_DMC_PATH; - dmc->max_fw_size = ICL_DMC_MAX_FW_SIZE; - } else if (IS_GEMINILAKE(i915)) { - dmc->fw_path = GLK_DMC_PATH; - dmc->max_fw_size = GLK_DMC_MAX_FW_SIZE; - } else if (IS_KABYLAKE(i915) || - IS_COFFEELAKE(i915) || - IS_COMETLAKE(i915)) { - dmc->fw_path = KBL_DMC_PATH; - dmc->max_fw_size = KBL_DMC_MAX_FW_SIZE; - } else if (IS_SKYLAKE(i915)) { - dmc->fw_path = SKL_DMC_PATH; - dmc->max_fw_size = SKL_DMC_MAX_FW_SIZE; - } else if (IS_BROXTON(i915)) { - dmc->fw_path = BXT_DMC_PATH; - dmc->max_fw_size = BXT_DMC_MAX_FW_SIZE; + dmc->fw_path = dmc_firmware_default(i915, &dmc->max_fw_size); + + if (dmc_firmware_param_disabled(i915)) { + drm_info(&i915->drm, "Disabling DMC firmware and runtime PM\n"); + goto out; } - if (i915->params.dmc_firmware_path) { - if (strlen(i915->params.dmc_firmware_path) == 0) { - drm_info(&i915->drm, - "Disabling DMC firmware and runtime PM\n"); - goto out; - } - - dmc->fw_path = i915->params.dmc_firmware_path; - } + if (dmc_firmware_param(i915)) + dmc->fw_path = dmc_firmware_param(i915); if (!dmc->fw_path) { drm_dbg_kms(&i915->drm, @@ -1072,6 +1123,8 @@ void intel_dmc_suspend(struct drm_i915_private *i915) if (dmc) flush_work(&dmc->work); + intel_dmc_wl_disable(&i915->display); + /* Drop the reference held in case DMC isn't loaded. */ if (!intel_dmc_has_payload(i915)) intel_dmc_runtime_pm_put(i915); diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h index 90d0dbb41cfe..1bf446f96a10 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -97,4 +97,10 @@ #define TGL_DMC_DEBUG3 _MMIO(0x101090) #define DG1_DMC_DEBUG3 _MMIO(0x13415c) +#define DMC_WAKELOCK_CFG _MMIO(0x8F1B0) +#define DMC_WAKELOCK_CFG_ENABLE REG_BIT(31) +#define DMC_WAKELOCK1_CTL _MMIO(0x8F140) +#define DMC_WAKELOCK_CTL_REQ REG_BIT(31) +#define DMC_WAKELOCK_CTL_ACK REG_BIT(15) + #endif /* __INTEL_DMC_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c new file mode 100644 index 000000000000..d9864b9cc429 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright (C) 2024 Intel Corporation + */ + +#include + +#include "intel_de.h" +#include "intel_dmc.h" +#include "intel_dmc_regs.h" +#include "intel_dmc_wl.h" + +/** + * DOC: DMC wakelock support + * + * Wake lock is the mechanism to cause display engine to exit DC + * states to allow programming to registers that are powered down in + * those states. Previous projects exited DC states automatically when + * detecting programming. Now software controls the exit by + * programming the wake lock. This improves system performance and + * system interactions and better fits the flip queue style of + * programming. Wake lock is only required when DC5, DC6, or DC6v have + * been enabled in DC_STATE_EN and the wake lock mode of operation has + * been enabled. + * + * The wakelock mechanism in DMC allows the display engine to exit DC + * states explicitly before programming registers that may be powered + * down. In earlier hardware, this was done automatically and + * implicitly when the display engine accessed a register. With the + * wakelock implementation, the driver asserts a wakelock in DMC, + * which forces it to exit the DC state until the wakelock is + * deasserted. + * + * The mechanism can be enabled and disabled by writing to the + * DMC_WAKELOCK_CFG register. There are also 13 control registers + * that can be used to hold and release different wakelocks. In the + * current implementation, we only need one wakelock, so only + * DMC_WAKELOCK1_CTL is used. The other definitions are here for + * potential future use. + */ + +#define DMC_WAKELOCK_CTL_TIMEOUT 5 +#define DMC_WAKELOCK_HOLD_TIME 50 + +struct intel_dmc_wl_range { + u32 start; + u32 end; +}; + +static struct intel_dmc_wl_range lnl_wl_range[] = { + { .start = 0x60000, .end = 0x7ffff }, +}; + +static void __intel_dmc_wl_release(struct intel_display *display) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + struct intel_dmc_wl *wl = &display->wl; + + WARN_ON(refcount_read(&wl->refcount)); + + queue_delayed_work(i915->unordered_wq, &wl->work, + msecs_to_jiffies(DMC_WAKELOCK_HOLD_TIME)); +} + +static void intel_dmc_wl_work(struct work_struct *work) +{ + struct intel_dmc_wl *wl = + container_of(work, struct intel_dmc_wl, work.work); + struct intel_display *display = + container_of(wl, struct intel_display, wl); + unsigned long flags; + + spin_lock_irqsave(&wl->lock, flags); + + /* Bail out if refcount reached zero while waiting for the spinlock */ + if (!refcount_read(&wl->refcount)) + goto out_unlock; + + __intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, DMC_WAKELOCK_CTL_REQ, 0); + + if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL, + DMC_WAKELOCK_CTL_ACK, 0, + DMC_WAKELOCK_CTL_TIMEOUT)) { + WARN_RATELIMIT(1, "DMC wakelock release timed out"); + goto out_unlock; + } + + wl->taken = false; + +out_unlock: + spin_unlock_irqrestore(&wl->lock, flags); +} + +static bool intel_dmc_wl_check_range(u32 address) +{ + int i; + bool wl_needed = false; + + for (i = 0; i < ARRAY_SIZE(lnl_wl_range); i++) { + if (address >= lnl_wl_range[i].start && + address <= lnl_wl_range[i].end) { + wl_needed = true; + break; + } + } + + return wl_needed; +} + +static bool __intel_dmc_wl_supported(struct intel_display *display) +{ + struct drm_i915_private *i915 = to_i915(display->drm); + + if (DISPLAY_VER(display) < 20 || + !intel_dmc_has_payload(i915) || + !display->params.enable_dmc_wl) + return false; + + return true; +} + +void intel_dmc_wl_init(struct intel_display *display) +{ + struct intel_dmc_wl *wl = &display->wl; + + /* don't call __intel_dmc_wl_supported(), DMC is not loaded yet */ + if (DISPLAY_VER(display) < 20 || !display->params.enable_dmc_wl) + return; + + INIT_DELAYED_WORK(&wl->work, intel_dmc_wl_work); + spin_lock_init(&wl->lock); + refcount_set(&wl->refcount, 0); +} + +void intel_dmc_wl_enable(struct intel_display *display) +{ + struct intel_dmc_wl *wl = &display->wl; + unsigned long flags; + + if (!__intel_dmc_wl_supported(display)) + return; + + spin_lock_irqsave(&wl->lock, flags); + + if (wl->enabled) + goto out_unlock; + + /* + * Enable wakelock in DMC. We shouldn't try to take the + * wakelock, because we're just enabling it, so call the + * non-locking version directly here. + */ + __intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, 0, DMC_WAKELOCK_CFG_ENABLE); + + wl->enabled = true; + wl->taken = false; + +out_unlock: + spin_unlock_irqrestore(&wl->lock, flags); +} + +void intel_dmc_wl_disable(struct intel_display *display) +{ + struct intel_dmc_wl *wl = &display->wl; + unsigned long flags; + + if (!__intel_dmc_wl_supported(display)) + return; + + flush_delayed_work(&wl->work); + + spin_lock_irqsave(&wl->lock, flags); + + if (!wl->enabled) + goto out_unlock; + + /* Disable wakelock in DMC */ + __intel_de_rmw_nowl(display, DMC_WAKELOCK_CFG, DMC_WAKELOCK_CFG_ENABLE, 0); + + refcount_set(&wl->refcount, 0); + wl->enabled = false; + wl->taken = false; + +out_unlock: + spin_unlock_irqrestore(&wl->lock, flags); +} + +void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg) +{ + struct intel_dmc_wl *wl = &display->wl; + unsigned long flags; + + if (!__intel_dmc_wl_supported(display)) + return; + + if (!intel_dmc_wl_check_range(reg.reg)) + return; + + spin_lock_irqsave(&wl->lock, flags); + + if (!wl->enabled) + goto out_unlock; + + cancel_delayed_work(&wl->work); + + if (refcount_inc_not_zero(&wl->refcount)) + goto out_unlock; + + refcount_set(&wl->refcount, 1); + + /* + * Only try to take the wakelock if it's not marked as taken + * yet. It may be already taken at this point if we have + * already released the last reference, but the work has not + * run yet. + */ + if (!wl->taken) { + __intel_de_rmw_nowl(display, DMC_WAKELOCK1_CTL, 0, + DMC_WAKELOCK_CTL_REQ); + + if (__intel_de_wait_for_register_nowl(display, DMC_WAKELOCK1_CTL, + DMC_WAKELOCK_CTL_ACK, + DMC_WAKELOCK_CTL_ACK, + DMC_WAKELOCK_CTL_TIMEOUT)) { + WARN_RATELIMIT(1, "DMC wakelock ack timed out"); + goto out_unlock; + } + + wl->taken = true; + } + +out_unlock: + spin_unlock_irqrestore(&wl->lock, flags); +} + +void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg) +{ + struct intel_dmc_wl *wl = &display->wl; + unsigned long flags; + + if (!__intel_dmc_wl_supported(display)) + return; + + if (!intel_dmc_wl_check_range(reg.reg)) + return; + + spin_lock_irqsave(&wl->lock, flags); + + if (!wl->enabled) + goto out_unlock; + + if (WARN_RATELIMIT(!refcount_read(&wl->refcount), + "Tried to put wakelock with refcount zero\n")) + goto out_unlock; + + if (refcount_dec_and_test(&wl->refcount)) { + __intel_dmc_wl_release(display); + + goto out_unlock; + } + +out_unlock: + spin_unlock_irqrestore(&wl->lock, flags); +} diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.h b/drivers/gpu/drm/i915/display/intel_dmc_wl.h new file mode 100644 index 000000000000..adab51208d0a --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2024 Intel Corporation + */ + +#ifndef __INTEL_WAKELOCK_H__ +#define __INTEL_WAKELOCK_H__ + +#include +#include +#include + +#include "i915_reg_defs.h" + +struct intel_display; + +struct intel_dmc_wl { + spinlock_t lock; /* protects enabled, taken and refcount */ + bool enabled; + bool taken; + refcount_t refcount; + struct delayed_work work; +}; + +void intel_dmc_wl_init(struct intel_display *display); +void intel_dmc_wl_enable(struct intel_display *display); +void intel_dmc_wl_disable(struct intel_display *display); +void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg); +void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg); + +#endif /* __INTEL_WAKELOCK_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f98ef4b42a44..e05e25cd4a94 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -89,6 +89,9 @@ #define DP_DSC_MAX_ENC_THROUGHPUT_0 340000 #define DP_DSC_MAX_ENC_THROUGHPUT_1 400000 +/* Max DSC line buffer depth supported by HW. */ +#define INTEL_DP_DSC_MAX_LINE_BUF_DEPTH 13 + /* DP DSC FEC Overhead factor in ppm = 1/(0.972261) = 1.028530 */ #define DP_DSC_FEC_OVERHEAD_FACTOR 1028530 @@ -123,6 +126,14 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp) return dig_port->base.type == INTEL_OUTPUT_EDP; } +bool intel_dp_as_sdp_supported(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + return HAS_AS_SDP(i915) && + drm_dp_as_sdp_supported(&intel_dp->aux, intel_dp->dpcd); +} + static void intel_dp_unset_edid(struct intel_dp *intel_dp); /* Is link rate UHBR and thus 128b/132b? */ @@ -214,7 +225,7 @@ static void intel_dp_set_dpcd_sink_rates(struct intel_dp *intel_dp) * Sink rates for 128b/132b. If set, sink should support all 8b/10b * rates and 10 Gbps. */ - if (intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B) { + if (drm_dp_128b132b_supported(intel_dp->dpcd)) { u8 uhbr_rates = 0; BUILD_BUG_ON(ARRAY_SIZE(intel_dp->sink_rates) < ARRAY_SIZE(dp_rates) + 3); @@ -425,7 +436,7 @@ int intel_dp_max_link_data_rate(struct intel_dp *intel_dp, return max_rate; } -bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp) +bool intel_dp_has_bigjoiner(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *encoder = &intel_dig_port->base; @@ -443,11 +454,9 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp) static int icl_max_source_rate(struct intel_dp *intel_dp) { - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp)) + if (intel_encoder_is_combo(encoder) && !intel_dp_is_edp(intel_dp)) return 540000; return 810000; @@ -463,11 +472,9 @@ static int ehl_max_source_rate(struct intel_dp *intel_dp) static int mtl_max_source_rate(struct intel_dp *intel_dp) { - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - if (intel_is_c10phy(i915, phy)) + if (intel_encoder_is_c10phy(encoder)) return 810000; return 2000000; @@ -499,7 +506,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) /* The values must be in increasing order */ static const int mtl_rates[] = { 162000, 216000, 243000, 270000, 324000, 432000, 540000, 675000, - 810000, 1000000, 1350000, 2000000, + 810000, 1000000, 2000000, }; static const int icl_rates[] = { 162000, 216000, 270000, 324000, 432000, 540000, 648000, 810000, @@ -1198,15 +1205,15 @@ intel_dp_mode_valid_downstream(struct intel_connector *connector, } bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + struct intel_connector *connector, int hdisplay, int clock) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - struct intel_connector *connector = intel_dp->attached_connector; - if (!intel_dp_can_bigjoiner(intel_dp)) + if (!intel_dp_has_bigjoiner(intel_dp)) return false; - return clock > i915->max_dotclk_freq || hdisplay > 5120 || + return clock > i915->display.cdclk.max_dotclk_freq || hdisplay > 5120 || connector->force_bigjoiner_enable; } @@ -1220,7 +1227,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, const struct drm_display_mode *fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; - int max_dotclk = dev_priv->max_dotclk_freq; + int max_dotclk = dev_priv->display.cdclk.max_dotclk_freq; u16 dsc_max_compressed_bpp = 0; u8 dsc_slice_count = 0; enum drm_mode_status status; @@ -1233,6 +1240,9 @@ intel_dp_mode_valid(struct drm_connector *_connector, if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; + if (mode->clock < 10000) + return MODE_CLOCK_LOW; + fixed_mode = intel_panel_fixed_mode(connector, mode); if (intel_dp_is_edp(intel_dp) && fixed_mode) { status = intel_panel_mode_valid(connector, mode); @@ -1242,10 +1252,8 @@ intel_dp_mode_valid(struct drm_connector *_connector, target_clock = fixed_mode->clock; } - if (mode->clock < 10000) - return MODE_CLOCK_LOW; - - if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) { + if (intel_dp_need_bigjoiner(intel_dp, connector, + mode->hdisplay, target_clock)) { bigjoiner = true; max_dotclk *= 2; } @@ -1306,11 +1314,7 @@ intel_dp_mode_valid(struct drm_connector *_connector, dsc = dsc_max_compressed_bpp && dsc_slice_count; } - /* - * Big joiner configuration needs DSC for TGL which is not true for - * XE_LPD where uncompressed joiner is supported. - */ - if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc) + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner) && !dsc) return MODE_CLOCK_HIGH; if (mode_rate > max_rate && !dsc) @@ -1422,7 +1426,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp, if (DISPLAY_VER(dev_priv) >= 12) return true; - if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A) + if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A && + !intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) return true; return false; @@ -1703,7 +1708,6 @@ static int intel_dp_dsc_compute_params(const struct intel_connector *connector, { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; - u8 line_buf_depth; int ret; /* @@ -1732,20 +1736,14 @@ static int intel_dp_dsc_compute_params(const struct intel_connector *connector, connector->dp.dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & DP_DSC_RGB; - line_buf_depth = drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd); - if (!line_buf_depth) { + vdsc_cfg->line_buf_depth = min(INTEL_DP_DSC_MAX_LINE_BUF_DEPTH, + drm_dp_dsc_sink_line_buf_depth(connector->dp.dsc_dpcd)); + if (!vdsc_cfg->line_buf_depth) { drm_dbg_kms(&i915->drm, "DSC Sink Line Buffer Depth invalid\n"); return -EINVAL; } - if (vdsc_cfg->dsc_version_minor == 2) - vdsc_cfg->line_buf_depth = (line_buf_depth == DSC_1_2_MAX_LINEBUF_DEPTH_BITS) ? - DSC_1_2_MAX_LINEBUF_DEPTH_VAL : line_buf_depth; - else - vdsc_cfg->line_buf_depth = (line_buf_depth > DSC_1_1_MAX_LINEBUF_DEPTH_BITS) ? - DSC_1_1_MAX_LINEBUF_DEPTH_BITS : line_buf_depth; - vdsc_cfg->block_pred_enable = connector->dp.dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] & DP_DSC_BLK_PREDICTION_IS_SUPPORTED; @@ -1917,8 +1915,9 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp, dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1); for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { - if (valid_dsc_bpp[i] < dsc_min_bpp || - valid_dsc_bpp[i] > dsc_max_bpp) + if (valid_dsc_bpp[i] < dsc_min_bpp) + continue; + if (valid_dsc_bpp[i] > dsc_max_bpp) break; ret = dsc_compute_link_config(intel_dp, @@ -2399,6 +2398,16 @@ int intel_dp_config_required_rate(const struct intel_crtc_state *crtc_state) return intel_dp_link_required(adjusted_mode->crtc_clock, bpp); } +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner) +{ + /* + * Pipe joiner needs compression up to display 12 due to bandwidth + * limitation. DG2 onwards pipe joiner can be enabled without + * compression. + */ + return DISPLAY_VER(i915) < 13 && use_joiner; +} + static int intel_dp_compute_link_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -2407,30 +2416,25 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, { struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - const struct intel_connector *connector = + struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct link_config_limits limits; - bool joiner_needs_dsc = false; - bool dsc_needed; + bool dsc_needed, joiner_needs_dsc; int ret = 0; if (pipe_config->fec_enable && !intel_dp_supports_fec(intel_dp, connector, pipe_config)) return -EINVAL; - if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay, + if (intel_dp_need_bigjoiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_clock)) pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); - /* - * Pipe joiner needs compression up to display 12 due to bandwidth - * limitation. DG2 onwards pipe joiner can be enabled without - * compression. - */ - joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes; + joiner_needs_dsc = intel_dp_joiner_needs_dsc(i915, pipe_config->bigjoiner_pipes); dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_compute_config_limits(intel_dp, pipe_config, @@ -2613,6 +2617,29 @@ static void intel_dp_compute_vsc_colorimetry(const struct intel_crtc_state *crtc vsc->content_type = DP_CONTENT_TYPE_NOT_DEFINED; } +static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_dp_as_sdp *as_sdp = &crtc_state->infoframes.as_sdp; + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + + if (!crtc_state->vrr.enable || + !intel_dp_as_sdp_supported(intel_dp)) + return; + + crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); + + /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */ + as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC; + as_sdp->length = 0x9; + as_sdp->mode = DP_AS_SDP_AVT_FIXED_VTOTAL; + as_sdp->vtotal = adjusted_mode->vtotal; + as_sdp->target_rr = 0; + as_sdp->duration_incr_ms = 0; + as_sdp->duration_incr_ms = 0; +} + static void intel_dp_compute_vsc_sdp(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) @@ -2723,7 +2750,11 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (has_seamless_m_n(connector)) + /* + * FIXME all joined pipes share the same transcoder. + * Need to account for that when updating M/N live. + */ + if (has_seamless_m_n(connector) && !pipe_config->bigjoiner_pipes) pipe_config->update_m_n = true; if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { @@ -2964,6 +2995,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, g4x_dp_set_clock(encoder, pipe_config); intel_vrr_compute_config(pipe_config, conn_state); + intel_dp_compute_as_sdp(intel_dp, pipe_config); intel_psr_compute_config(intel_dp, pipe_config, conn_state); intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); @@ -3356,6 +3388,14 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, fastset = false; } + if (CAN_PANEL_REPLAY(intel_dp)) { + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] Forcing full modeset to compute panel replay state\n", + encoder->base.base.id, encoder->base.name); + crtc_state->uapi.mode_changed = true; + fastset = false; + } + return fastset; } @@ -4039,39 +4079,84 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) intel_dp->downstream_ports) == 0; } -static bool -intel_dp_can_mst(struct intel_dp *intel_dp) +static const char *intel_dp_mst_mode_str(enum drm_dp_mst_mode mst_mode) +{ + if (mst_mode == DRM_DP_MST) + return "MST"; + else if (mst_mode == DRM_DP_SST_SIDEBAND_MSG) + return "SST w/ sideband messaging"; + else + return "SST"; +} + +static enum drm_dp_mst_mode +intel_dp_mst_mode_choose(struct intel_dp *intel_dp, + enum drm_dp_mst_mode sink_mst_mode) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); - return i915->display.params.enable_dp_mst && - intel_dp_mst_source_support(intel_dp) && - drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); + if (!i915->display.params.enable_dp_mst) + return DRM_DP_SST; + + if (!intel_dp_mst_source_support(intel_dp)) + return DRM_DP_SST; + + if (sink_mst_mode == DRM_DP_SST_SIDEBAND_MSG && + !(intel_dp->dpcd[DP_MAIN_LINK_CHANNEL_CODING] & DP_CAP_ANSI_128B132B)) + return DRM_DP_SST; + + return sink_mst_mode; +} + +static enum drm_dp_mst_mode +intel_dp_mst_detect(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + enum drm_dp_mst_mode sink_mst_mode; + enum drm_dp_mst_mode mst_detect; + + sink_mst_mode = drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); + + mst_detect = intel_dp_mst_mode_choose(intel_dp, sink_mst_mode); + + drm_dbg_kms(&i915->drm, + "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s -> enable: %s\n", + encoder->base.base.id, encoder->base.name, + str_yes_no(intel_dp_mst_source_support(intel_dp)), + intel_dp_mst_mode_str(sink_mst_mode), + str_yes_no(i915->display.params.enable_dp_mst), + intel_dp_mst_mode_str(mst_detect)); + + return mst_detect; } static void -intel_dp_configure_mst(struct intel_dp *intel_dp) +intel_dp_mst_configure(struct intel_dp *intel_dp) { - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - struct intel_encoder *encoder = - &dp_to_dig_port(intel_dp)->base; - bool sink_can_mst = drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); - - drm_dbg_kms(&i915->drm, - "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n", - encoder->base.base.id, encoder->base.name, - str_yes_no(intel_dp_mst_source_support(intel_dp)), - str_yes_no(sink_can_mst), - str_yes_no(i915->display.params.enable_dp_mst)); - if (!intel_dp_mst_source_support(intel_dp)) return; - intel_dp->is_mst = sink_can_mst && - i915->display.params.enable_dp_mst; + intel_dp->is_mst = intel_dp->mst_detect != DRM_DP_SST; - drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, - intel_dp->is_mst); + drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); + + /* Avoid stale info on the next detect cycle. */ + intel_dp->mst_detect = DRM_DP_SST; +} + +static void +intel_dp_mst_disconnect(struct intel_dp *intel_dp) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + + if (!intel_dp->is_mst) + return; + + drm_dbg_kms(&i915->drm, "MST device may have disappeared %d vs %d\n", + intel_dp->is_mst, intel_dp->mst_mgr.mst_state); + intel_dp->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); } static bool @@ -4119,6 +4204,32 @@ intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, return false; } +static ssize_t intel_dp_as_sdp_pack(const struct drm_dp_as_sdp *as_sdp, + struct dp_sdp *sdp, size_t size) +{ + size_t length = sizeof(struct dp_sdp); + + if (size < length) + return -ENOSPC; + + memset(sdp, 0, size); + + /* Prepare AS (Adaptive Sync) SDP Header */ + sdp->sdp_header.HB0 = 0; + sdp->sdp_header.HB1 = as_sdp->sdp_type; + sdp->sdp_header.HB2 = 0x02; + sdp->sdp_header.HB3 = as_sdp->length; + + /* Fill AS (Adaptive Sync) SDP Payload */ + sdp->db[0] = as_sdp->mode; + sdp->db[1] = as_sdp->vtotal & 0xFF; + sdp->db[2] = (as_sdp->vtotal >> 8) & 0xFF; + sdp->db[3] = as_sdp->target_rr & 0xFF; + sdp->db[4] = (as_sdp->target_rr >> 8) & 0x3; + + return length; +} + static ssize_t intel_dp_hdr_metadata_infoframe_sdp_pack(struct drm_i915_private *i915, const struct hdmi_drm_infoframe *drm_infoframe, @@ -4218,6 +4329,10 @@ static void intel_write_dp_sdp(struct intel_encoder *encoder, &crtc_state->infoframes.drm.drm, &sdp, sizeof(sdp)); break; + case DP_SDP_ADAPTIVE_SYNC: + len = intel_dp_as_sdp_pack(&crtc_state->infoframes.as_sdp, &sdp, + sizeof(sdp)); + break; default: MISSING_CASE(type); return; @@ -4239,6 +4354,10 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder, u32 dip_enable = VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW | VIDEO_DIP_ENABLE_DRM_GLK; + + if (HAS_AS_SDP(dev_priv)) + dip_enable |= VIDEO_DIP_ENABLE_AS_ADL; + u32 val = intel_de_read(dev_priv, reg) & ~dip_enable; /* TODO: Sanitize DSC enabling wrt. intel_dsc_dp_pps_write(). */ @@ -4256,10 +4375,42 @@ void intel_dp_set_infoframes(struct intel_encoder *encoder, return; intel_write_dp_sdp(encoder, crtc_state, DP_SDP_VSC); + intel_write_dp_sdp(encoder, crtc_state, DP_SDP_ADAPTIVE_SYNC); intel_write_dp_sdp(encoder, crtc_state, HDMI_PACKET_TYPE_GAMUT_METADATA); } +static +int intel_dp_as_sdp_unpack(struct drm_dp_as_sdp *as_sdp, + const void *buffer, size_t size) +{ + const struct dp_sdp *sdp = buffer; + + if (size < sizeof(struct dp_sdp)) + return -EINVAL; + + memset(as_sdp, 0, sizeof(*as_sdp)); + + if (sdp->sdp_header.HB0 != 0) + return -EINVAL; + + if (sdp->sdp_header.HB1 != DP_SDP_ADAPTIVE_SYNC) + return -EINVAL; + + if (sdp->sdp_header.HB2 != 0x02) + return -EINVAL; + + if ((sdp->sdp_header.HB3 & 0x3F) != 9) + return -EINVAL; + + as_sdp->length = sdp->sdp_header.HB3 & DP_ADAPTIVE_SYNC_SDP_LENGTH; + as_sdp->mode = sdp->db[0] & DP_ADAPTIVE_SYNC_SDP_OPERATION_MODE; + as_sdp->vtotal = (sdp->db[2] << 8) | sdp->db[1]; + as_sdp->target_rr = (u64)sdp->db[3] | ((u64)sdp->db[4] & 0x3); + + return 0; +} + static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, const void *buffer, size_t size) { @@ -4330,6 +4481,29 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, return 0; } +static void +intel_read_dp_as_sdp(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + struct drm_dp_as_sdp *as_sdp) +{ + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + unsigned int type = DP_SDP_ADAPTIVE_SYNC; + struct dp_sdp sdp = {}; + int ret; + + if ((crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(type)) == 0) + return; + + dig_port->read_infoframe(encoder, crtc_state, type, &sdp, + sizeof(sdp)); + + ret = intel_dp_as_sdp_unpack(as_sdp, &sdp, sizeof(sdp)); + if (ret) + drm_dbg_kms(&dev_priv->drm, "Failed to unpack DP AS SDP\n"); +} + static int intel_dp_hdr_metadata_infoframe_sdp_unpack(struct hdmi_drm_infoframe *drm_infoframe, const void *buffer, size_t size) @@ -4436,6 +4610,10 @@ void intel_read_dp_sdp(struct intel_encoder *encoder, intel_read_dp_hdr_metadata_infoframe_sdp(encoder, crtc_state, &crtc_state->infoframes.drm.drm); break; + case DP_SDP_ADAPTIVE_SYNC: + intel_read_dp_as_sdp(encoder, crtc_state, + &crtc_state->infoframes.as_sdp); + break; default: MISSING_CASE(type); break; @@ -5363,6 +5541,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) if (!intel_dp_get_dpcd(intel_dp)) return connector_status_disconnected; + intel_dp->mst_detect = intel_dp_mst_detect(intel_dp); + /* if there's no downstream port, we're done */ if (!drm_dp_is_branch(dpcd)) return connector_status_connected; @@ -5374,7 +5554,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) connector_status_connected : connector_status_disconnected; } - if (intel_dp_can_mst(intel_dp)) + if (intel_dp->mst_detect == DRM_DP_MST) return connector_status_connected; /* If no HPD, poke DDC gently */ @@ -5679,15 +5859,7 @@ intel_dp_detect(struct drm_connector *connector, memset(intel_connector->dp.dsc_dpcd, 0, sizeof(intel_connector->dp.dsc_dpcd)); intel_dp->psr.sink_panel_replay_support = false; - if (intel_dp->is_mst) { - drm_dbg_kms(&dev_priv->drm, - "MST device may have disappeared %d vs %d\n", - intel_dp->is_mst, - intel_dp->mst_mgr.mst_state); - intel_dp->is_mst = false; - drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, - intel_dp->is_mst); - } + intel_dp_mst_disconnect(intel_dp); intel_dp_tunnel_disconnect(intel_dp); @@ -5706,7 +5878,7 @@ intel_dp_detect(struct drm_connector *connector, intel_dp_detect_dsc_caps(intel_dp, intel_connector); - intel_dp_configure_mst(intel_dp); + intel_dp_mst_configure(intel_dp); /* * TODO: Reset link params when switching to MST mode, until MST @@ -6489,7 +6661,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, struct drm_device *dev = intel_encoder->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); enum port port = intel_encoder->port; - enum phy phy = intel_port_to_phy(dev_priv, port); int type; /* Initialize the work for modeset in case of link train failure */ @@ -6514,7 +6685,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, * Currently we don't support eDP on TypeC ports, although in * theory it could work on TypeC legacy ports. */ - drm_WARN_ON(dev, intel_phy_is_tc(dev_priv, phy)); + drm_WARN_ON(dev, intel_encoder_is_tc(intel_encoder)); type = DRM_MODE_CONNECTOR_eDP; intel_encoder->type = INTEL_OUTPUT_EDP; @@ -6557,6 +6728,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port, intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; else intel_connector->get_hw_state = intel_connector_get_hw_state; + intel_connector->sync_state = intel_dp_connector_sync_state; if (!intel_edp_init_connector(intel_dp, intel_connector)) { intel_dp_aux_fini(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index c540d3a73fe7..106ecfde36d9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -88,6 +88,7 @@ void intel_dp_audio_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state); bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp); bool intel_dp_is_edp(struct intel_dp *intel_dp); +bool intel_dp_as_sdp_supported(struct intel_dp *intel_dp); bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state); int intel_dp_link_symbol_size(int rate); int intel_dp_link_symbol_clock(int rate); @@ -119,7 +120,8 @@ int intel_dp_effective_data_rate(int pixel_clock, int bpp_x16, int bw_overhead); int intel_dp_max_link_data_rate(struct intel_dp *intel_dp, int max_dprx_rate, int max_dprx_lanes); -bool intel_dp_can_bigjoiner(struct intel_dp *intel_dp); +bool intel_dp_joiner_needs_dsc(struct drm_i915_private *i915, bool use_joiner); +bool intel_dp_has_bigjoiner(struct intel_dp *intel_dp); bool intel_dp_needs_vsc_sdp(const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); void intel_dp_set_infoframes(struct intel_encoder *encoder, bool enable, @@ -149,6 +151,7 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector, int mode_clock, int mode_hdisplay, bool bigjoiner); bool intel_dp_need_bigjoiner(struct intel_dp *intel_dp, + struct intel_connector *connector, int hdisplay, int clock); static inline unsigned int intel_dp_unused_lane_mask(int lane_count) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c index 4f4a0e3b3114..b8a53bb174da 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c @@ -61,9 +61,8 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp) u32 status; int ret; - ret = __intel_de_wait_for_register(i915, ch_ctl, - DP_AUX_CH_CTL_SEND_BUSY, 0, - 2, timeout_ms, &status); + ret = intel_de_wait_custom(i915, ch_ctl, DP_AUX_CH_CTL_SEND_BUSY, 0, + 2, timeout_ms, &status); if (ret == -ETIMEDOUT) drm_err(&i915->drm, @@ -143,9 +142,15 @@ static int intel_dp_aux_sync_len(void) return precharge + preamble; } -static int intel_dp_aux_fw_sync_len(void) +int intel_dp_aux_fw_sync_len(void) { - int precharge = 10; /* 10-16 */ + /* + * We faced some glitches on Dell Precision 5490 MTL laptop with panel: + * "Manufacturer: AUO, Model: 63898" when using HW default 18. Using 20 + * is fixing these problems with the panel. It is still within range + * mentioned in eDP specification. + */ + int precharge = 12; /* 10-16 */ int preamble = 8; return precharge + preamble; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h b/drivers/gpu/drm/i915/display/intel_dp_aux.h index 8447f3e601fe..76d1f2ed7c2f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux.h +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h @@ -20,5 +20,6 @@ enum aux_ch intel_dp_aux_ch(struct intel_encoder *encoder); void intel_dp_aux_irq_handler(struct drm_i915_private *i915); u32 intel_dp_aux_pack(const u8 *src, int src_bytes); +int intel_dp_aux_fw_sync_len(void); #endif /* __INTEL_DP_AUX_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index b98a87883fef..92b03073acdd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -691,12 +691,15 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, u8 bcaps; int ret; + *hdcp_capable = false; + *hdcp2_capable = false; if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) - return ret; + drm_dbg_kms(&i915->drm, + "HDCP2 DPCD capability read failed err: %d\n", ret); ret = intel_dp_hdcp_read_bcaps(aux, i915, &bcaps); if (ret) @@ -766,11 +769,9 @@ intel_dp_mst_hdcp_stream_encryption(struct intel_connector *connector, return -EINVAL; /* Wait for encryption confirmation */ - if (intel_de_wait_for_register(i915, - HDCP_STATUS(i915, cpu_transcoder, port), - stream_enc_status, - enable ? stream_enc_status : 0, - HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { + if (intel_de_wait(i915, HDCP_STATUS(i915, cpu_transcoder, port), + stream_enc_status, enable ? stream_enc_status : 0, + HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { drm_err(&i915->drm, "Timed out waiting for transcoder: %s stream encryption %s\n", transcoder_name(cpu_transcoder), enable ? "enabled" : "disabled"); return -ETIMEDOUT; @@ -801,11 +802,10 @@ intel_dp_mst_hdcp2_stream_encryption(struct intel_connector *connector, return ret; /* Wait for encryption confirmation */ - if (intel_de_wait_for_register(i915, - HDCP2_STREAM_STATUS(i915, cpu_transcoder, pipe), - STREAM_ENCRYPTION_STATUS, - enable ? STREAM_ENCRYPTION_STATUS : 0, - HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { + if (intel_de_wait(i915, HDCP2_STREAM_STATUS(i915, cpu_transcoder, pipe), + STREAM_ENCRYPTION_STATUS, + enable ? STREAM_ENCRYPTION_STATUS : 0, + HDCP_ENCRYPT_STATUS_CHANGE_TIMEOUT_MS)) { drm_err(&i915->drm, "Timed out waiting for transcoder: %s stream encryption %s\n", transcoder_name(cpu_transcoder), enable ? "enabled" : "disabled"); return -ETIMEDOUT; diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index fb84ca98bb7a..947575140059 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -334,7 +334,7 @@ static bool has_per_lane_signal_levels(struct intel_dp *intel_dp, struct drm_i915_private *i915 = dp_to_i915(intel_dp); return !intel_dp_phy_is_downstream_of_source(intel_dp, dp_phy) || - DISPLAY_VER(i915) >= 11; + DISPLAY_VER(i915) >= 10 || IS_BROXTON(i915); } /* 128b/132b */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 53aec023ce92..c772ba19c547 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -51,25 +51,39 @@ #include "intel_vdsc.h" #include "skl_scaler.h" -static int intel_dp_mst_check_constraints(struct drm_i915_private *i915, int bpp, - const struct drm_display_mode *adjusted_mode, - struct intel_crtc_state *crtc_state, - bool dsc) +static int intel_dp_mst_max_dpt_bpp(const struct intel_crtc_state *crtc_state, + bool dsc) { - if (intel_dp_is_uhbr(crtc_state) && DISPLAY_VER(i915) < 14 && dsc) { - int output_bpp = bpp; - /* DisplayPort 2 128b/132b, bits per lane is always 32 */ - int symbol_clock = crtc_state->port_clock / 32; + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; - if (output_bpp * adjusted_mode->crtc_clock >= - symbol_clock * 72) { - drm_dbg_kms(&i915->drm, "UHBR check failed(required bw %d available %d)\n", - output_bpp * adjusted_mode->crtc_clock, symbol_clock * 72); - return -EINVAL; - } - } + if (!intel_dp_is_uhbr(crtc_state) || DISPLAY_VER(i915) >= 20 || !dsc) + return INT_MAX; - return 0; + /* + * DSC->DPT interface width: + * ICL-MTL: 72 bits (each branch has 72 bits, only left branch is used) + * LNL+: 144 bits (not a bottleneck in any config) + * + * Bspec/49259 suggests that the FEC overhead needs to be + * applied here, though HW people claim that neither this FEC + * or any other overhead is applicable here (that is the actual + * available_bw is just symbol_clock * 72). However based on + * testing on MTL-P the + * - DELL U3224KBA display + * - Unigraf UCD-500 CTS test sink + * devices the + * - 5120x2880/995.59Mhz + * - 6016x3384/1357.23Mhz + * - 6144x3456/1413.39Mhz + * modes (all the ones having a DPT limit on the above devices), + * both the channel coding efficiency and an additional 3% + * overhead needs to be accounted for. + */ + return div64_u64(mul_u32_u32(intel_dp_link_symbol_clock(crtc_state->port_clock) * 72, + drm_dp_bw_channel_coding_efficiency(true)), + mul_u32_u32(adjusted_mode->crtc_clock, 1030000)); } static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, @@ -88,11 +102,10 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state, if (dsc) { flags |= DRM_DP_BW_OVERHEAD_DSC; - /* TODO: add support for bigjoiner */ dsc_slice_count = intel_dp_dsc_get_slice_count(connector, adjusted_mode->clock, adjusted_mode->hdisplay, - false); + crtc_state->bigjoiner_pipes); } overhead = drm_dp_bw_overhead(crtc_state->lane_count, @@ -158,6 +171,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; int bpp, slots = -EINVAL; + int max_dpt_bpp; int ret = 0; mst_state = drm_atomic_get_mst_topology_state(state, &intel_dp->mst_mgr); @@ -178,6 +192,13 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, crtc_state->port_clock, crtc_state->lane_count); + max_dpt_bpp = intel_dp_mst_max_dpt_bpp(crtc_state, dsc); + if (max_bpp > max_dpt_bpp) { + drm_dbg_kms(&i915->drm, "Limiting bpp to max DPT bpp (%d -> %d)\n", + max_bpp, max_dpt_bpp); + max_bpp = max_dpt_bpp; + } + drm_dbg_kms(&i915->drm, "Looking for slots in range min bpp %d max bpp %d\n", min_bpp, max_bpp); @@ -189,10 +210,6 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder, drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp); - ret = intel_dp_mst_check_constraints(i915, bpp, adjusted_mode, crtc_state, dsc); - if (ret) - continue; - link_bpp_x16 = to_bpp_x16(dsc ? bpp : intel_dp_output_bpp(crtc_state->output_format, bpp)); @@ -404,15 +421,22 @@ static int mode_hblank_period_ns(const struct drm_display_mode *mode) static bool hblank_expansion_quirk_needs_dsc(const struct intel_connector *connector, - const struct intel_crtc_state *crtc_state) + const struct intel_crtc_state *crtc_state, + const struct link_config_limits *limits) { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + bool is_uhbr_sink = connector->mst_port && + drm_dp_128b132b_supported(connector->mst_port->dpcd); + int hblank_limit = is_uhbr_sink ? 500 : 300; if (!connector->dp.dsc_hblank_expansion_quirk) return false; - if (mode_hblank_period_ns(adjusted_mode) > 300) + if (is_uhbr_sink && !drm_dp_is_uhbr_rate(limits->max_rate)) + return false; + + if (mode_hblank_period_ns(adjusted_mode) > hblank_limit) return false; return true; @@ -428,7 +452,7 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct intel_connector *conne const struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); int min_bpp_x16 = limits->link.min_bpp_x16; - if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state)) + if (!hblank_expansion_quirk_needs_dsc(connector, crtc_state, limits)) return true; if (!dsc) { @@ -525,14 +549,15 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_atomic_state *state = to_intel_atomic_state(conn_state->state); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder); struct intel_dp *intel_dp = &intel_mst->primary->dp; - const struct intel_connector *connector = + struct intel_connector *connector = to_intel_connector(conn_state->connector); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct link_config_limits limits; - bool dsc_needed; + bool dsc_needed, joiner_needs_dsc; int ret = 0; if (pipe_config->fec_enable && @@ -542,11 +567,18 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; + if (intel_dp_need_bigjoiner(intel_dp, connector, + adjusted_mode->crtc_hdisplay, + adjusted_mode->crtc_clock)) + pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); + pipe_config->sink_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_pch_encoder = false; - dsc_needed = intel_dp->force_dsc_en || + joiner_needs_dsc = intel_dp_joiner_needs_dsc(dev_priv, pipe_config->bigjoiner_pipes); + + dsc_needed = joiner_needs_dsc || intel_dp->force_dsc_en || !intel_dp_mst_compute_config_limits(intel_dp, connector, pipe_config, @@ -566,8 +598,8 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, /* enable compression if the mode doesn't fit available BW */ if (dsc_needed) { - drm_dbg_kms(&dev_priv->drm, "Try DSC (fallback=%s, force=%s)\n", - str_yes_no(ret), + drm_dbg_kms(&dev_priv->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n", + str_yes_no(ret), str_yes_no(joiner_needs_dsc), str_yes_no(intel_dp->force_dsc_en)); if (!intel_dp_mst_dsc_source_support(pipe_config)) @@ -613,7 +645,7 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder, if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = - bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); + bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); intel_dp_audio_compute_config(encoder, pipe_config, conn_state); @@ -954,6 +986,7 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, struct drm_dp_mst_atomic_payload *new_payload = drm_atomic_get_mst_payload_state(new_mst_state, connector->port); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_crtc *pipe_crtc; bool last_mst_stream; intel_dp->active_mst_links--; @@ -962,7 +995,13 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, DISPLAY_VER(dev_priv) >= 12 && last_mst_stream && !intel_dp_mst_is_master_trans(old_crtc_state)); - intel_crtc_vblank_off(old_crtc_state); + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); + + intel_crtc_vblank_off(old_pipe_crtc_state); + } intel_disable_transcoder(old_crtc_state); @@ -980,12 +1019,18 @@ static void intel_mst_post_disable_dp(struct intel_atomic_state *state, intel_ddi_disable_transcoder_func(old_crtc_state); - intel_dsc_disable(old_crtc_state); + for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(old_crtc_state)) { + const struct intel_crtc_state *old_pipe_crtc_state = + intel_atomic_get_old_crtc_state(state, pipe_crtc); - if (DISPLAY_VER(dev_priv) >= 9) - skl_scaler_disable(old_crtc_state); - else - ilk_pfit_disable(old_crtc_state); + intel_dsc_disable(old_pipe_crtc_state); + + if (DISPLAY_VER(dev_priv) >= 9) + skl_scaler_disable(old_pipe_crtc_state); + else + ilk_pfit_disable(old_pipe_crtc_state); + } /* * Power down mst path before disabling the port, otherwise we end @@ -1117,6 +1162,39 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state, intel_ddi_set_dp_msa(pipe_config, conn_state); } +static void enable_bs_jitter_was(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + u32 clear = 0; + u32 set = 0; + + if (!IS_ALDERLAKE_P(i915)) + return; + + if (!IS_DISPLAY_STEP(i915, STEP_D0, STEP_FOREVER)) + return; + + /* Wa_14013163432:adlp */ + if (crtc_state->fec_enable || intel_dp_is_uhbr(crtc_state)) + set |= DP_MST_FEC_BS_JITTER_WA(crtc_state->cpu_transcoder); + + /* Wa_14014143976:adlp */ + if (IS_DISPLAY_STEP(i915, STEP_E0, STEP_FOREVER)) { + if (intel_dp_is_uhbr(crtc_state)) + set |= DP_MST_SHORT_HBLANK_WA(crtc_state->cpu_transcoder); + else if (crtc_state->fec_enable) + clear |= DP_MST_SHORT_HBLANK_WA(crtc_state->cpu_transcoder); + + if (crtc_state->fec_enable || intel_dp_is_uhbr(crtc_state)) + set |= DP_MST_DPT_DPTP_ALIGN_WA(crtc_state->cpu_transcoder); + } + + if (!clear && !set) + return; + + intel_de_rmw(i915, CHICKEN_MISC_3, clear, set); +} + static void intel_mst_enable_dp(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, @@ -1131,6 +1209,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, drm_atomic_get_new_mst_topology_state(&state->base, &intel_dp->mst_mgr); enum transcoder trans = pipe_config->cpu_transcoder; bool first_mst_stream = intel_dp->active_mst_links == 1; + struct intel_crtc *pipe_crtc; drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder); @@ -1145,6 +1224,8 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, TRANS_DP2_VFREQ_PIXEL_CLOCK(crtc_clock_hz & 0xffffff)); } + enable_bs_jitter_was(pipe_config); + intel_ddi_enable_transcoder_func(encoder, pipe_config); clear_act_sent(encoder, pipe_config); @@ -1172,7 +1253,13 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, intel_enable_transcoder(pipe_config); - intel_crtc_vblank_on(pipe_config); + for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc, + intel_crtc_joined_pipe_mask(pipe_config)) { + const struct intel_crtc_state *pipe_crtc_state = + intel_atomic_get_new_crtc_state(state, pipe_crtc); + + intel_crtc_vblank_on(pipe_crtc_state); + } intel_hdcp_enable(state, encoder, pipe_config, conn_state); } @@ -1285,7 +1372,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, struct drm_dp_mst_topology_mgr *mgr = &intel_dp->mst_mgr; struct drm_dp_mst_port *port = intel_connector->port; const int min_bpp = 18; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; int ret; bool dsc = false, bigjoiner = false; @@ -1302,8 +1389,13 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, if (*status != MODE_OK) return 0; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { - *status = MODE_NO_DBLESCAN; + if (mode->flags & DRM_MODE_FLAG_DBLCLK) { + *status = MODE_H_ILLEGAL; + return 0; + } + + if (mode->clock < 10000) { + *status = MODE_CLOCK_LOW; return 0; } @@ -1314,10 +1406,6 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, max_link_clock, max_lanes); mode_rate = intel_dp_link_required(mode->clock, min_bpp); - ret = drm_modeset_lock(&mgr->base.lock, ctx); - if (ret) - return ret; - /* * TODO: * - Also check if compression would allow for the mode @@ -1330,32 +1418,23 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, * corresponding link capabilities of the sink) in case the * stream is uncompressed for it by the last branch device. */ + if (intel_dp_need_bigjoiner(intel_dp, intel_connector, + mode->hdisplay, target_clock)) { + bigjoiner = true; + max_dotclk *= 2; + } + + ret = drm_modeset_lock(&mgr->base.lock, ctx); + if (ret) + return ret; + if (mode_rate > max_rate || mode->clock > max_dotclk || drm_dp_calc_pbn_mode(mode->clock, min_bpp << 4) > port->full_pbn) { *status = MODE_CLOCK_HIGH; return 0; } - if (mode->clock < 10000) { - *status = MODE_CLOCK_LOW; - return 0; - } - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) { - *status = MODE_H_ILLEGAL; - return 0; - } - - if (intel_dp_need_bigjoiner(intel_dp, mode->hdisplay, target_clock)) { - bigjoiner = true; - max_dotclk *= 2; - - /* TODO: add support for bigjoiner */ - *status = MODE_CLOCK_HIGH; - return 0; - } - - if (DISPLAY_VER(dev_priv) >= 10 && + if (HAS_DSC_MST(dev_priv) && drm_dp_sink_supports_dsc(intel_connector->dp.dsc_dpcd)) { /* * TBD pass the connector BPC, @@ -1383,11 +1462,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, dsc = dsc_max_compressed_bpp && dsc_slice_count; } - /* - * Big joiner configuration needs DSC for TGL which is not true for - * XE_LPD where uncompressed joiner is supported. - */ - if (DISPLAY_VER(dev_priv) < 13 && bigjoiner && !dsc) { + if (intel_dp_joiner_needs_dsc(dev_priv, bigjoiner) && !dsc) { *status = MODE_CLOCK_HIGH; return 0; } @@ -1397,7 +1472,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector, return 0; } - *status = intel_mode_valid_max_plane_size(dev_priv, mode, false); + *status = intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner); return 0; } @@ -1509,24 +1584,41 @@ intel_dp_mst_read_decompression_port_dsc_caps(struct intel_dp *intel_dp, static bool detect_dsc_hblank_expansion_quirk(const struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_dp_aux *aux = connector->dp.dsc_decompression_aux; struct drm_dp_desc desc; u8 dpcd[DP_RECEIVER_CAP_SIZE]; - if (!connector->dp.dsc_decompression_aux) + if (!aux) return false; - if (drm_dp_read_desc(connector->dp.dsc_decompression_aux, - &desc, true) < 0) + /* + * A logical port's OUI (at least for affected sinks) is all 0, so + * instead of that the parent port's OUI is used for identification. + */ + if (drm_dp_mst_port_is_logical(connector->port)) { + aux = drm_dp_mst_aux_for_parent(connector->port); + if (!aux) + aux = &connector->mst_port->aux; + } + + if (drm_dp_read_dpcd_caps(aux, dpcd) < 0) + return false; + + if (drm_dp_read_desc(aux, &desc, drm_dp_is_branch(dpcd)) < 0) return false; if (!drm_dp_has_quirk(&desc, DP_DPCD_QUIRK_HBLANK_EXPANSION_REQUIRES_DSC)) return false; - if (drm_dp_read_dpcd_caps(connector->dp.dsc_decompression_aux, dpcd) < 0) - return false; - - if (!(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE)) + /* + * UHBR (MST sink) devices requiring this quirk don't advertise the + * HBLANK expansion support. Presuming that they perform HBLANK + * expansion internally, or are affected by this issue on modes with a + * short HBLANK for other reasons. + */ + if (!drm_dp_128b132b_supported(dpcd) && + !(dpcd[DP_RECEIVE_PORT_0_CAP_0] & DP_HBLANK_EXPANSION_CAPABLE)) return false; drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c index 75d76f91ecbd..6503abdc2b98 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_tunnel.c +++ b/drivers/gpu/drm/i915/display/intel_dp_tunnel.c @@ -348,7 +348,7 @@ void intel_dp_tunnel_resume(struct intel_dp *intel_dp, out_err: drm_dbg_kms(&i915->drm, - "[DPTUN %s][CONNECTOR:%d:%s][ENCODER:%d:%s] Tunnel can't be resumed, will drop and redect it (err %pe)\n", + "[DPTUN %s][CONNECTOR:%d:%s][ENCODER:%d:%s] Tunnel can't be resumed, will drop and reject it (err %pe)\n", drm_dp_tunnel_name(intel_dp->tunnel), connector->base.base.id, connector->base.name, encoder->base.base.id, encoder->base.name, diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 4ca910874a4f..c72b76b61dff 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include "bxt_dpio_phy_regs.h" #include "i915_reg.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" @@ -123,9 +124,9 @@ */ /** - * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy + * struct bxt_dpio_phy_info - Hold info for a broxton DDI phy */ -struct bxt_ddi_phy_info { +struct bxt_dpio_phy_info { /** * @dual_channel: true if this phy has a second channel. */ @@ -161,7 +162,7 @@ struct bxt_ddi_phy_info { } channel[2]; }; -static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { +static const struct bxt_dpio_phy_info bxt_dpio_phy_info[] = { [DPIO_PHY0] = { .dual_channel = true, .rcomp_phy = DPIO_PHY1, @@ -183,7 +184,7 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { }, }; -static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = { +static const struct bxt_dpio_phy_info glk_dpio_phy_info[] = { [DPIO_PHY0] = { .dual_channel = false, .rcomp_phy = DPIO_PHY1, @@ -216,23 +217,23 @@ static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = { }, }; -static const struct bxt_ddi_phy_info * +static const struct bxt_dpio_phy_info * bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count) { if (IS_GEMINILAKE(dev_priv)) { - *count = ARRAY_SIZE(glk_ddi_phy_info); - return glk_ddi_phy_info; + *count = ARRAY_SIZE(glk_dpio_phy_info); + return glk_dpio_phy_info; } else { - *count = ARRAY_SIZE(bxt_ddi_phy_info); - return bxt_ddi_phy_info; + *count = ARRAY_SIZE(bxt_dpio_phy_info); + return bxt_dpio_phy_info; } } -static const struct bxt_ddi_phy_info * +static const struct bxt_dpio_phy_info * bxt_get_phy_info(struct drm_i915_private *dev_priv, enum dpio_phy phy) { int count; - const struct bxt_ddi_phy_info *phy_list = + const struct bxt_dpio_phy_info *phy_list = bxt_get_phy_list(dev_priv, &count); return &phy_list[phy]; @@ -241,7 +242,7 @@ bxt_get_phy_info(struct drm_i915_private *dev_priv, enum dpio_phy phy) void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, enum dpio_phy *phy, enum dpio_channel *ch) { - const struct bxt_ddi_phy_info *phy_info, *phys; + const struct bxt_dpio_phy_info *phy_info, *phys; int i, count; phys = bxt_get_phy_list(dev_priv, &count); @@ -269,16 +270,32 @@ void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, *ch = DPIO_CH0; } -void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +/* + * Like intel_de_rmw() but reads from a single per-lane register and + * writes to the group register to write the same value to all the lanes. + */ +static u32 bxt_dpio_phy_rmw_grp(struct drm_i915_private *i915, + i915_reg_t reg_single, + i915_reg_t reg_group, + u32 clear, u32 set) +{ + u32 old, val; + + old = intel_de_read(i915, reg_single); + val = (old & ~clear) | set; + intel_de_write(i915, reg_group, val); + + return old; +} + +void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - int level = intel_ddi_level(encoder, crtc_state, 0); const struct intel_ddi_buf_trans *trans; enum dpio_channel ch; enum dpio_phy phy; - int n_entries; - u32 val; + int lane, n_entries; trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans)) @@ -290,41 +307,51 @@ void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, * While we write to the group register to program all lanes at once we * can read only lane registers and we pick lanes 0/1 for that. */ - val = intel_de_read(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch)); - val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); - intel_de_write(dev_priv, BXT_PORT_PCS_DW10_GRP(phy, ch), val); + bxt_dpio_phy_rmw_grp(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch), + BXT_PORT_PCS_DW10_GRP(phy, ch), + TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT, 0); - val = intel_de_read(dev_priv, BXT_PORT_TX_DW2_LN0(phy, ch)); - val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); - val |= trans->entries[level].bxt.margin << MARGIN_000_SHIFT | - trans->entries[level].bxt.scale << UNIQ_TRANS_SCALE_SHIFT; - intel_de_write(dev_priv, BXT_PORT_TX_DW2_GRP(phy, ch), val); + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); - val = intel_de_read(dev_priv, BXT_PORT_TX_DW3_LN0(phy, ch)); - val &= ~SCALE_DCOMP_METHOD; - if (trans->entries[level].bxt.enable) - val |= SCALE_DCOMP_METHOD; + intel_de_rmw(dev_priv, BXT_PORT_TX_DW2_LN(phy, ch, lane), + MARGIN_000_MASK | UNIQ_TRANS_SCALE_MASK, + MARGIN_000(trans->entries[level].bxt.margin) | + UNIQ_TRANS_SCALE(trans->entries[level].bxt.scale)); + } - if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) - drm_err(&dev_priv->drm, - "Disabled scaling while ouniqetrangenmethod was set"); + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); + u32 val; - intel_de_write(dev_priv, BXT_PORT_TX_DW3_GRP(phy, ch), val); + intel_de_rmw(dev_priv, BXT_PORT_TX_DW3_LN(phy, ch, lane), + SCALE_DCOMP_METHOD, + trans->entries[level].bxt.enable ? + SCALE_DCOMP_METHOD : 0); - val = intel_de_read(dev_priv, BXT_PORT_TX_DW4_LN0(phy, ch)); - val &= ~DE_EMPHASIS; - val |= trans->entries[level].bxt.deemphasis << DEEMPH_SHIFT; - intel_de_write(dev_priv, BXT_PORT_TX_DW4_GRP(phy, ch), val); + val = intel_de_read(dev_priv, BXT_PORT_TX_DW3_LN(phy, ch, lane)); + if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) + drm_err(&dev_priv->drm, + "Disabled scaling while ouniqetrangenmethod was set"); + } - val = intel_de_read(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch)); - val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; - intel_de_write(dev_priv, BXT_PORT_PCS_DW10_GRP(phy, ch), val); + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); + + intel_de_rmw(dev_priv, BXT_PORT_TX_DW4_LN(phy, ch, lane), + DE_EMPHASIS_MASK, + DE_EMPHASIS(trans->entries[level].bxt.deemphasis)); + } + + bxt_dpio_phy_rmw_grp(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch), + BXT_PORT_PCS_DW10_GRP(phy, ch), + 0, TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); } -bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; phy_info = bxt_get_phy_info(dev_priv, phy); @@ -353,7 +380,7 @@ static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) { u32 val = intel_de_read(dev_priv, BXT_PORT_REF_DW6(phy)); - return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; + return REG_FIELD_GET(GRC_CODE_MASK, val); } static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, @@ -365,20 +392,20 @@ static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, phy); } -static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +static void _bxt_dpio_phy_init(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; u32 val; phy_info = bxt_get_phy_info(dev_priv, phy); - if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { + if (bxt_dpio_phy_is_enabled(dev_priv, phy)) { /* Still read out the GRC value for state verification */ if (phy_info->rcomp_phy != -1) dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy); - if (bxt_ddi_phy_verify_state(dev_priv, phy)) { + if (bxt_dpio_phy_verify_state(dev_priv, phy)) { drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, " "won't reprogram it\n", phy); return; @@ -399,20 +426,17 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, * The flag should get set in 100us according to the HW team, but * use 1ms due to occasional timeouts observed with that. */ - if (intel_wait_for_register_fw(&dev_priv->uncore, - BXT_PORT_CL1CM_DW0(phy), - PHY_RESERVED | PHY_POWER_GOOD, - PHY_POWER_GOOD, - 1)) + if (intel_de_wait_fw(dev_priv, BXT_PORT_CL1CM_DW0(phy), + PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1)) drm_err(&dev_priv->drm, "timeout during PHY%d power on\n", phy); /* Program PLL Rcomp code offset */ - intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW9(phy), IREF0RC_OFFSET_MASK, - 0xE4 << IREF0RC_OFFSET_SHIFT); + intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW9(phy), + IREF0RC_OFFSET_MASK, IREF0RC_OFFSET(0xE4)); - intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW10(phy), IREF1RC_OFFSET_MASK, - 0xE4 << IREF1RC_OFFSET_SHIFT); + intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW10(phy), + IREF1RC_OFFSET_MASK, IREF1RC_OFFSET(0xE4)); /* Program power gating */ intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW28(phy), 0, @@ -435,9 +459,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, val = bxt_get_grc(dev_priv, phy_info->rcomp_phy); dev_priv->display.state.bxt_phy_grc = val; - grc_code = val << GRC_CODE_FAST_SHIFT | - val << GRC_CODE_SLOW_SHIFT | - val; + grc_code = GRC_CODE_FAST(val) | + GRC_CODE_SLOW(val) | + GRC_CODE_NOM(val); intel_de_write(dev_priv, BXT_PORT_REF_DW6(phy), grc_code); intel_de_rmw(dev_priv, BXT_PORT_REF_DW8(phy), 0, GRC_DIS | GRC_RDY_OVRD); @@ -449,9 +473,9 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, intel_de_rmw(dev_priv, BXT_PHY_CTL_FAMILY(phy), 0, COMMON_RESET_DIS); } -void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) +void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; phy_info = bxt_get_phy_info(dev_priv, phy); @@ -460,9 +484,9 @@ void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, phy_info->pwron_mask, 0); } -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info = + const struct bxt_dpio_phy_info *phy_info = bxt_get_phy_info(dev_priv, phy); enum dpio_phy rcomp_phy = phy_info->rcomp_phy; bool was_enabled; @@ -471,19 +495,19 @@ void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) was_enabled = true; if (rcomp_phy != -1) - was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy); + was_enabled = bxt_dpio_phy_is_enabled(dev_priv, rcomp_phy); /* * We need to copy the GRC calibration value from rcomp_phy, * so make sure it's powered up. */ if (!was_enabled) - _bxt_ddi_phy_init(dev_priv, rcomp_phy); + _bxt_dpio_phy_init(dev_priv, rcomp_phy); - _bxt_ddi_phy_init(dev_priv, phy); + _bxt_dpio_phy_init(dev_priv, phy); if (!was_enabled) - bxt_ddi_phy_uninit(dev_priv, rcomp_phy); + bxt_dpio_phy_uninit(dev_priv, rcomp_phy); } static bool __printf(6, 7) @@ -513,10 +537,10 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, return false; } -bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; u32 mask; bool ok; @@ -526,23 +550,23 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ ## __VA_ARGS__) - if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) + if (!bxt_dpio_phy_is_enabled(dev_priv, phy)) return false; ok = true; /* PLL Rcomp code offset */ ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), - IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW9(%d)", phy); + IREF0RC_OFFSET_MASK, IREF0RC_OFFSET(0xe4), + "BXT_PORT_CL1CM_DW9(%d)", phy); ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), - IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW10(%d)", phy); + IREF1RC_OFFSET_MASK, IREF1RC_OFFSET(0xe4), + "BXT_PORT_CL1CM_DW10(%d)", phy); /* Power gating */ mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, - "BXT_PORT_CL1CM_DW28(%d)", phy); + "BXT_PORT_CL1CM_DW28(%d)", phy); if (phy_info->dual_channel) ok &= _CHK(BXT_PORT_CL2CM_DW6(phy), @@ -552,9 +576,9 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, if (phy_info->rcomp_phy != -1) { u32 grc_code = dev_priv->display.state.bxt_phy_grc; - grc_code = grc_code << GRC_CODE_FAST_SHIFT | - grc_code << GRC_CODE_SLOW_SHIFT | - grc_code; + grc_code = GRC_CODE_FAST(grc_code) | + GRC_CODE_SLOW(grc_code) | + GRC_CODE_NOM(grc_code); mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | GRC_CODE_NOM_MASK; ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code, @@ -562,7 +586,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, mask = GRC_DIS | GRC_RDY_OVRD; ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask, - "BXT_PORT_REF_DW8(%d)", phy); + "BXT_PORT_REF_DW8(%d)", phy); } return ok; @@ -570,7 +594,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, } u8 -bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count) +bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count) { switch (lane_count) { case 1: @@ -586,8 +610,8 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count) } } -void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, - u8 lane_lat_optim_mask) +void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder, + u8 lane_lat_optim_mask) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -598,24 +622,18 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, bxt_port_to_phy_channel(dev_priv, port, &phy, &ch); for (lane = 0; lane < 4; lane++) { - u32 val = intel_de_read(dev_priv, - BXT_PORT_TX_DW14_LN(phy, ch, lane)); - /* * Note that on CHV this flag is called UPAR, but has * the same function. */ - val &= ~LATENCY_OPTIM; - if (lane_lat_optim_mask & BIT(lane)) - val |= LATENCY_OPTIM; - - intel_de_write(dev_priv, BXT_PORT_TX_DW14_LN(phy, ch, lane), - val); + intel_de_rmw(dev_priv, BXT_PORT_TX_DW14_LN(phy, ch, lane), + LATENCY_OPTIM, + lane_lat_optim_mask & BIT(lane) ? LATENCY_OPTIM : 0); } } u8 -bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) +bxt_dpio_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = encoder->port; diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h index 9adc4e8c1738..226994dcb89b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h @@ -29,18 +29,18 @@ enum dpio_phy { #ifdef I915 void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, enum dpio_phy *phy, enum dpio_channel *ch); -void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state); -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy); -void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy); -bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy); -bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy); -u8 bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count); -void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, - u8 lane_lat_optim_mask); -u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder); +void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state); +void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy); +void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy); +bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv, + enum dpio_phy phy); +bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv, + enum dpio_phy phy); +u8 bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count); +void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder, + u8 lane_lat_optim_mask); +u8 bxt_dpio_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder); enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port); enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port); @@ -77,35 +77,35 @@ static inline void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, en enum dpio_phy *phy, enum dpio_channel *ch) { } -static inline void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +static inline void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) { } -static inline void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +static inline void bxt_dpio_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) { } -static inline void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) +static inline void bxt_dpio_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) { } -static inline bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +static inline bool bxt_dpio_phy_is_enabled(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { return false; } -static inline bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +static inline bool bxt_dpio_phy_verify_state(struct drm_i915_private *dev_priv, + enum dpio_phy phy) { return true; } -static inline u8 bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count) +static inline u8 bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count) { return 0; } -static inline void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, - u8 lane_lat_optim_mask) +static inline void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder, + u8 lane_lat_optim_mask) { } -static inline u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) +static inline u8 bxt_dpio_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) { return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 3038655377ea..49274d632716 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -369,38 +369,68 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock) return clock->dot; } -static int i9xx_pll_refclk(struct drm_device *dev, - const struct intel_crtc_state *pipe_config) +static int i9xx_pll_refclk(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(dev); - u32 dpll = pipe_config->dpll_hw_state.dpll; + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; - if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) - return dev_priv->display.vbt.lvds_ssc_freq; - else if (HAS_PCH_SPLIT(dev_priv)) + if ((hw_state->dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) + return i915->display.vbt.lvds_ssc_freq; + else if (HAS_PCH_SPLIT(i915)) return 120000; - else if (DISPLAY_VER(dev_priv) != 2) + else if (DISPLAY_VER(i915) != 2) return 96000; else return 48000; } -/* Returns the clock of the currently programmed mode of the given pipe. */ -void i9xx_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +void i9xx_dpll_get_hw_state(struct intel_crtc *crtc, + struct intel_dpll_hw_state *dpll_hw_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - u32 dpll = pipe_config->dpll_hw_state.dpll; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; + + if (DISPLAY_VER(dev_priv) >= 4) { + u32 tmp; + + /* No way to read it out on pipes B and C */ + if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) + tmp = dev_priv->display.state.chv_dpll_md[crtc->pipe]; + else + tmp = intel_de_read(dev_priv, DPLL_MD(crtc->pipe)); + + hw_state->dpll_md = tmp; + } + + hw_state->dpll = intel_de_read(dev_priv, DPLL(crtc->pipe)); + + if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { + hw_state->fp0 = intel_de_read(dev_priv, FP0(crtc->pipe)); + hw_state->fp1 = intel_de_read(dev_priv, FP1(crtc->pipe)); + } else { + /* Mask out read-only status bits. */ + hw_state->dpll &= ~(DPLL_LOCK_VLV | + DPLL_PORTC_READY_MASK | + DPLL_PORTB_READY_MASK); + } +} + +/* Returns the clock of the currently programmed mode of the given pipe. */ +void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; + u32 dpll = hw_state->dpll; u32 fp; struct dpll clock; int port_clock; - int refclk = i9xx_pll_refclk(dev, pipe_config); + int refclk = i9xx_pll_refclk(crtc_state); if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) - fp = pipe_config->dpll_hw_state.fp0; + fp = hw_state->fp0; else - fp = pipe_config->dpll_hw_state.fp1; + fp = hw_state->fp1; clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; if (IS_PINEVIEW(dev_priv)) { @@ -475,21 +505,21 @@ void i9xx_crtc_clock_get(struct intel_crtc *crtc, * port_clock to compute adjusted_mode.crtc_clock in the * encoder's get_config() function. */ - pipe_config->port_clock = port_clock; + crtc_state->port_clock = port_clock; } -void vlv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; struct dpll clock; u32 mdiv; int refclk = 100000; /* In case of DSI, DPLL will not be used */ - if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0) + if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; vlv_dpio_get(dev_priv); @@ -502,22 +532,22 @@ void vlv_crtc_clock_get(struct intel_crtc *crtc, clock.p1 = (mdiv >> DPIO_P1_SHIFT) & 7; clock.p2 = (mdiv >> DPIO_P2_SHIFT) & 0x1f; - pipe_config->port_clock = vlv_calc_dpll_params(refclk, &clock); + crtc_state->port_clock = vlv_calc_dpll_params(refclk, &clock); } -void chv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) +void chv_crtc_clock_get(struct intel_crtc_state *crtc_state) { - struct drm_device *dev = crtc->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum dpio_channel port = vlv_pipe_to_channel(crtc->pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; struct dpll clock; u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3; int refclk = 100000; /* In case of DSI, DPLL will not be used */ - if ((pipe_config->dpll_hw_state.dpll & DPLL_VCO_ENABLE) == 0) + if ((hw_state->dpll & DPLL_VCO_ENABLE) == 0) return; vlv_dpio_get(dev_priv); @@ -536,7 +566,7 @@ void chv_crtc_clock_get(struct intel_crtc *crtc, clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; - pipe_config->port_clock = chv_calc_dpll_params(refclk, &clock); + crtc_state->port_clock = chv_calc_dpll_params(refclk, &clock); } /* @@ -958,37 +988,20 @@ static u32 pnv_dpll_compute_fp(const struct dpll *dpll) return (1 << dpll->n) << 16 | dpll->m2; } -static void i9xx_update_pll_dividers(struct intel_crtc_state *crtc_state, - const struct dpll *clock, - const struct dpll *reduced_clock) +static u32 i965_dpll_md(const struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 fp, fp2; - - if (IS_PINEVIEW(dev_priv)) { - fp = pnv_dpll_compute_fp(clock); - fp2 = pnv_dpll_compute_fp(reduced_clock); - } else { - fp = i9xx_dpll_compute_fp(clock); - fp2 = i9xx_dpll_compute_fp(reduced_clock); - } - - crtc_state->dpll_hw_state.fp0 = fp; - crtc_state->dpll_hw_state.fp1 = fp2; + return (crtc_state->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; } -static void i9xx_compute_dpll(struct intel_crtc_state *crtc_state, - const struct dpll *clock, - const struct dpll *reduced_clock) +static u32 i9xx_dpll(const struct intel_crtc_state *crtc_state, + const struct dpll *clock, + const struct dpll *reduced_clock) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; - i9xx_update_pll_dividers(crtc_state, clock, reduced_clock); - - dpll = DPLL_VGA_MODE_DIS; + dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) dpll |= DPLLB_MODE_LVDS; @@ -1047,27 +1060,40 @@ static void i9xx_compute_dpll(struct intel_crtc_state *crtc_state, else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= DPLL_VCO_ENABLE; - crtc_state->dpll_hw_state.dpll = dpll; - - if (DISPLAY_VER(dev_priv) >= 4) { - u32 dpll_md = (crtc_state->pixel_multiplier - 1) - << DPLL_MD_UDI_MULTIPLIER_SHIFT; - crtc_state->dpll_hw_state.dpll_md = dpll_md; - } + return dpll; } -static void i8xx_compute_dpll(struct intel_crtc_state *crtc_state, +static void i9xx_compute_dpll(struct intel_crtc_state *crtc_state, const struct dpll *clock, const struct dpll *reduced_clock) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; + + if (IS_PINEVIEW(dev_priv)) { + hw_state->fp0 = pnv_dpll_compute_fp(clock); + hw_state->fp1 = pnv_dpll_compute_fp(reduced_clock); + } else { + hw_state->fp0 = i9xx_dpll_compute_fp(clock); + hw_state->fp1 = i9xx_dpll_compute_fp(reduced_clock); + } + + hw_state->dpll = i9xx_dpll(crtc_state, clock, reduced_clock); + + if (DISPLAY_VER(dev_priv) >= 4) + hw_state->dpll_md = i965_dpll_md(crtc_state); +} + +static u32 i8xx_dpll(const struct intel_crtc_state *crtc_state, + const struct dpll *clock, + const struct dpll *reduced_clock) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; - i9xx_update_pll_dividers(crtc_state, clock, reduced_clock); - - dpll = DPLL_VGA_MODE_DIS; + dpll = DPLL_VCO_ENABLE | DPLL_VGA_MODE_DIS; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; @@ -1104,8 +1130,19 @@ static void i8xx_compute_dpll(struct intel_crtc_state *crtc_state, else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= DPLL_VCO_ENABLE; - crtc_state->dpll_hw_state.dpll = dpll; + return dpll; +} + +static void i8xx_compute_dpll(struct intel_crtc_state *crtc_state, + const struct dpll *clock, + const struct dpll *reduced_clock) +{ + struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; + + hw_state->fp0 = i9xx_dpll_compute_fp(clock); + hw_state->fp1 = i9xx_dpll_compute_fp(reduced_clock); + + hw_state->dpll = i8xx_dpll(crtc_state, clock, reduced_clock); } static int hsw_crtc_compute_clock(struct intel_atomic_state *state, @@ -1185,62 +1222,54 @@ static int mtl_crtc_compute_clock(struct intel_atomic_state *state, return ret; /* TODO: Do the readback via intel_compute_shared_dplls() */ - crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->cx0pll_state); + crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); crtc_state->hw.adjusted_mode.crtc_clock = intel_crtc_dotclock(crtc_state); return 0; } +static int ilk_fb_cb_factor(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && + ((intel_panel_use_ssc(i915) && i915->display.vbt.lvds_ssc_freq == 100000) || + (HAS_PCH_IBX(i915) && intel_is_dual_link_lvds(i915)))) + return 25; + + if (crtc_state->sdvo_tv_clock) + return 20; + + return 21; +} + static bool ilk_needs_fb_cb_tune(const struct dpll *dpll, int factor) { return dpll->m < factor * dpll->n; } -static void ilk_update_pll_dividers(struct intel_crtc_state *crtc_state, - const struct dpll *clock, - const struct dpll *reduced_clock) +static u32 ilk_dpll_compute_fp(const struct dpll *clock, int factor) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 fp, fp2; - int factor; - - /* Enable autotuning of the PLL clock (if permissible) */ - factor = 21; - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { - if ((intel_panel_use_ssc(dev_priv) && - dev_priv->display.vbt.lvds_ssc_freq == 100000) || - (HAS_PCH_IBX(dev_priv) && - intel_is_dual_link_lvds(dev_priv))) - factor = 25; - } else if (crtc_state->sdvo_tv_clock) { - factor = 20; - } + u32 fp; fp = i9xx_dpll_compute_fp(clock); if (ilk_needs_fb_cb_tune(clock, factor)) fp |= FP_CB_TUNE; - fp2 = i9xx_dpll_compute_fp(reduced_clock); - if (ilk_needs_fb_cb_tune(reduced_clock, factor)) - fp2 |= FP_CB_TUNE; - - crtc_state->dpll_hw_state.fp0 = fp; - crtc_state->dpll_hw_state.fp1 = fp2; + return fp; } -static void ilk_compute_dpll(struct intel_crtc_state *crtc_state, - const struct dpll *clock, - const struct dpll *reduced_clock) +static u32 ilk_dpll(const struct intel_crtc_state *crtc_state, + const struct dpll *clock, + const struct dpll *reduced_clock) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dpll; - ilk_update_pll_dividers(crtc_state, clock, reduced_clock); - - dpll = 0; + dpll = DPLL_VCO_ENABLE; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) dpll |= DPLLB_MODE_LVDS; @@ -1302,9 +1331,20 @@ static void ilk_compute_dpll(struct intel_crtc_state *crtc_state, else dpll |= PLL_REF_INPUT_DREFCLK; - dpll |= DPLL_VCO_ENABLE; + return dpll; +} - crtc_state->dpll_hw_state.dpll = dpll; +static void ilk_compute_dpll(struct intel_crtc_state *crtc_state, + const struct dpll *clock, + const struct dpll *reduced_clock) +{ + struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; + int factor = ilk_fb_cb_factor(crtc_state); + + hw_state->fp0 = ilk_dpll_compute_fp(clock, factor); + hw_state->fp1 = ilk_dpll_compute_fp(reduced_clock, factor); + + hw_state->dpll = ilk_dpll(crtc_state, clock, reduced_clock); } static int ilk_crtc_compute_clock(struct intel_atomic_state *state, @@ -1377,39 +1417,56 @@ static int ilk_crtc_get_shared_dpll(struct intel_atomic_state *state, return intel_reserve_shared_dplls(state, crtc, NULL); } -void vlv_compute_dpll(struct intel_crtc_state *crtc_state) +static u32 vlv_dpll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 dpll; - crtc_state->dpll_hw_state.dpll = DPLL_INTEGRATED_REF_CLK_VLV | + dpll = DPLL_INTEGRATED_REF_CLK_VLV | DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; + if (crtc->pipe != PIPE_A) - crtc_state->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; + dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; /* DPLL not used with DSI, but still need the rest set up */ if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) - crtc_state->dpll_hw_state.dpll |= DPLL_VCO_ENABLE | - DPLL_EXT_BUFFER_ENABLE_VLV; + dpll |= DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV; - crtc_state->dpll_hw_state.dpll_md = - (crtc_state->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; + return dpll; +} + +void vlv_compute_dpll(struct intel_crtc_state *crtc_state) +{ + struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; + + hw_state->dpll = vlv_dpll(crtc_state); + hw_state->dpll_md = i965_dpll_md(crtc_state); +} + +static u32 chv_dpll(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + u32 dpll; + + dpll = DPLL_SSC_REF_CLK_CHV | + DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; + + if (crtc->pipe != PIPE_A) + dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; + + /* DPLL not used with DSI, but still need the rest set up */ + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) + dpll |= DPLL_VCO_ENABLE; + + return dpll; } void chv_compute_dpll(struct intel_crtc_state *crtc_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; - crtc_state->dpll_hw_state.dpll = DPLL_SSC_REF_CLK_CHV | - DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS; - if (crtc->pipe != PIPE_A) - crtc_state->dpll_hw_state.dpll |= DPLL_INTEGRATED_CRI_CLK_VLV; - - /* DPLL not used with DSI, but still need the rest set up */ - if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) - crtc_state->dpll_hw_state.dpll |= DPLL_VCO_ENABLE; - - crtc_state->dpll_hw_state.dpll_md = - (crtc_state->pixel_multiplier - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; + hw_state->dpll = chv_dpll(crtc_state); + hw_state->dpll_md = i965_dpll_md(crtc_state); } static int chv_crtc_compute_clock(struct intel_atomic_state *state, @@ -1765,7 +1822,7 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 dpll = crtc_state->dpll_hw_state.dpll; + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; int i; @@ -1775,36 +1832,35 @@ void i9xx_enable_pll(const struct intel_crtc_state *crtc_state) if (i9xx_has_pps(dev_priv)) assert_pps_unlocked(dev_priv, pipe); - intel_de_write(dev_priv, FP0(pipe), crtc_state->dpll_hw_state.fp0); - intel_de_write(dev_priv, FP1(pipe), crtc_state->dpll_hw_state.fp1); + intel_de_write(dev_priv, FP0(pipe), hw_state->fp0); + intel_de_write(dev_priv, FP1(pipe), hw_state->fp1); /* * Apparently we need to have VGA mode enabled prior to changing * the P1/P2 dividers. Otherwise the DPLL will keep using the old * dividers, even though the register value does change. */ - intel_de_write(dev_priv, DPLL(pipe), dpll & ~DPLL_VGA_MODE_DIS); - intel_de_write(dev_priv, DPLL(pipe), dpll); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll & ~DPLL_VGA_MODE_DIS); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); /* Wait for the clocks to stabilize. */ intel_de_posting_read(dev_priv, DPLL(pipe)); udelay(150); if (DISPLAY_VER(dev_priv) >= 4) { - intel_de_write(dev_priv, DPLL_MD(pipe), - crtc_state->dpll_hw_state.dpll_md); + intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); } else { /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. * * So write it again. */ - intel_de_write(dev_priv, DPLL(pipe), dpll); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); } /* We do this three times for luck */ for (i = 0; i < 3; i++) { - intel_de_write(dev_priv, DPLL(pipe), dpll); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); intel_de_posting_read(dev_priv, DPLL(pipe)); udelay(150); /* wait for warmup */ } @@ -1934,9 +1990,10 @@ static void _vlv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; - intel_de_write(dev_priv, DPLL(pipe), crtc_state->dpll_hw_state.dpll); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); intel_de_posting_read(dev_priv, DPLL(pipe)); udelay(150); @@ -1948,6 +2005,7 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder); @@ -1957,16 +2015,14 @@ void vlv_enable_pll(const struct intel_crtc_state *crtc_state) /* Enable Refclk */ intel_de_write(dev_priv, DPLL(pipe), - crtc_state->dpll_hw_state.dpll & - ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV)); + hw_state->dpll & ~(DPLL_VCO_ENABLE | DPLL_EXT_BUFFER_ENABLE_VLV)); - if (crtc_state->dpll_hw_state.dpll & DPLL_VCO_ENABLE) { + if (hw_state->dpll & DPLL_VCO_ENABLE) { vlv_prepare_pll(crtc_state); _vlv_enable_pll(crtc_state); } - intel_de_write(dev_priv, DPLL_MD(pipe), - crtc_state->dpll_hw_state.dpll_md); + intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); intel_de_posting_read(dev_priv, DPLL_MD(pipe)); } @@ -2069,6 +2125,7 @@ static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; enum dpio_channel port = vlv_pipe_to_channel(pipe); enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); @@ -2089,7 +2146,7 @@ static void _chv_enable_pll(const struct intel_crtc_state *crtc_state) udelay(1); /* Enable PLL */ - intel_de_write(dev_priv, DPLL(pipe), crtc_state->dpll_hw_state.dpll); + intel_de_write(dev_priv, DPLL(pipe), hw_state->dpll); /* Check PLL is locked */ if (intel_de_wait_for_set(dev_priv, DPLL(pipe), DPLL_LOCK_VLV, 1)) @@ -2100,6 +2157,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct i9xx_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.i9xx; enum pipe pipe = crtc->pipe; assert_transcoder_disabled(dev_priv, crtc_state->cpu_transcoder); @@ -2109,9 +2167,9 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) /* Enable Refclk and SSC */ intel_de_write(dev_priv, DPLL(pipe), - crtc_state->dpll_hw_state.dpll & ~DPLL_VCO_ENABLE); + hw_state->dpll & ~DPLL_VCO_ENABLE); - if (crtc_state->dpll_hw_state.dpll & DPLL_VCO_ENABLE) { + if (hw_state->dpll & DPLL_VCO_ENABLE) { chv_prepare_pll(crtc_state); _chv_enable_pll(crtc_state); } @@ -2124,10 +2182,9 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) * the value from DPLLBMD to either pipe B or C. */ intel_de_write(dev_priv, CBR4_VLV, CBR_DPLLBMD_PIPE(pipe)); - intel_de_write(dev_priv, DPLL_MD(PIPE_B), - crtc_state->dpll_hw_state.dpll_md); + intel_de_write(dev_priv, DPLL_MD(PIPE_B), hw_state->dpll_md); intel_de_write(dev_priv, CBR4_VLV, 0); - dev_priv->display.state.chv_dpll_md[pipe] = crtc_state->dpll_hw_state.dpll_md; + dev_priv->display.state.chv_dpll_md[pipe] = hw_state->dpll_md; /* * DPLLB VGA mode also seems to cause problems. @@ -2137,8 +2194,7 @@ void chv_enable_pll(const struct intel_crtc_state *crtc_state) (intel_de_read(dev_priv, DPLL(PIPE_B)) & DPLL_VGA_MODE_DIS) == 0); } else { - intel_de_write(dev_priv, DPLL_MD(pipe), - crtc_state->dpll_hw_state.dpll_md); + intel_de_write(dev_priv, DPLL_MD(pipe), hw_state->dpll_md); intel_de_posting_read(dev_priv, DPLL_MD(pipe)); } } diff --git a/drivers/gpu/drm/i915/display/intel_dpll.h b/drivers/gpu/drm/i915/display/intel_dpll.h index ac01bb19cc6c..a86a79408af0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.h +++ b/drivers/gpu/drm/i915/display/intel_dpll.h @@ -13,6 +13,7 @@ struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; +struct intel_dpll_hw_state; enum pipe; void intel_dpll_init_clock_hook(struct drm_i915_private *dev_priv); @@ -22,6 +23,8 @@ int intel_dpll_crtc_get_shared_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc); int i9xx_calc_dpll_params(int refclk, struct dpll *clock); u32 i9xx_dpll_compute_fp(const struct dpll *dpll); +void i9xx_dpll_get_hw_state(struct intel_crtc *crtc, + struct intel_dpll_hw_state *dpll_hw_state); void vlv_compute_dpll(struct intel_crtc_state *crtc_state); void chv_compute_dpll(struct intel_crtc_state *crtc_state); @@ -39,12 +42,9 @@ bool bxt_find_best_dpll(struct intel_crtc_state *crtc_state, struct dpll *best_clock); int chv_calc_dpll_params(int refclk, struct dpll *pll_clock); -void i9xx_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config); -void vlv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config); -void chv_crtc_clock_get(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config); +void i9xx_crtc_clock_get(struct intel_crtc_state *crtc_state); +void vlv_crtc_clock_get(struct intel_crtc_state *crtc_state); +void chv_crtc_clock_get(struct intel_crtc_state *crtc_state); void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe); void assert_pll_disabled(struct drm_i915_private *i915, enum pipe pipe); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index b6d24410740f..90998b037349 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -24,6 +24,7 @@ #include #include +#include "bxt_dpio_phy_regs.h" #include "i915_reg.h" #include "intel_de.h" #include "intel_display_types.h" @@ -64,7 +65,8 @@ struct intel_shared_dpll_funcs { * the pll is not already enabled. */ void (*enable)(struct drm_i915_private *i915, - struct intel_shared_dpll *pll); + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state); /* * Hook for disabling the pll, called from intel_disable_shared_dpll() @@ -81,7 +83,7 @@ struct intel_shared_dpll_funcs { */ bool (*get_hw_state)(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state); + struct intel_dpll_hw_state *dpll_hw_state); /* * Hook for calculating the pll's output frequency based on its passed @@ -89,7 +91,7 @@ struct intel_shared_dpll_funcs { */ int (*get_freq)(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state); + const struct intel_dpll_hw_state *dpll_hw_state); }; struct intel_dpll_mgr { @@ -107,8 +109,8 @@ struct intel_dpll_mgr { struct intel_crtc *crtc, struct intel_encoder *encoder); void (*update_ref_clks)(struct drm_i915_private *i915); - void (*dump_hw_state)(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state); + void (*dump_hw_state)(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state); bool (*compare_hw_state)(const struct intel_dpll_hw_state *a, const struct intel_dpll_hw_state *b); }; @@ -227,7 +229,7 @@ static void _intel_enable_shared_dpll(struct drm_i915_private *i915, if (pll->info->power_domain) pll->wakeref = intel_display_power_get(i915, pll->info->power_domain); - pll->info->funcs->enable(i915, pll); + pll->info->funcs->enable(i915, pll, &pll->state.hw_state); pll->on = true; } @@ -352,7 +354,7 @@ intel_dpll_mask_all(struct drm_i915_private *i915) static struct intel_shared_dpll * intel_find_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, - const struct intel_dpll_hw_state *pll_state, + const struct intel_dpll_hw_state *dpll_hw_state, unsigned long dpll_mask) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); @@ -379,9 +381,9 @@ intel_find_shared_dpll(struct intel_atomic_state *state, continue; } - if (memcmp(pll_state, + if (memcmp(dpll_hw_state, &shared_dpll[pll->index].hw_state, - sizeof(*pll_state)) == 0) { + sizeof(*dpll_hw_state)) == 0) { drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n", crtc->base.base.id, crtc->base.name, @@ -430,14 +432,14 @@ static void intel_reference_shared_dpll(struct intel_atomic_state *state, const struct intel_crtc *crtc, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { struct intel_shared_dpll_state *shared_dpll; shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); if (shared_dpll[pll->index].pipe_mask == 0) - shared_dpll[pll->index].hw_state = *pll_state; + shared_dpll[pll->index].hw_state = *dpll_hw_state; intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[pll->index]); } @@ -519,8 +521,9 @@ void intel_shared_dpll_swap_state(struct intel_atomic_state *state) static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; const enum intel_dpll_id id = pll->info->id; intel_wakeref_t wakeref; u32 val; @@ -553,17 +556,19 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *i915) } static void ibx_pch_dpll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; const enum intel_dpll_id id = pll->info->id; /* PCH refclock must be enabled first */ ibx_assert_pch_refclk_enabled(i915); - intel_de_write(i915, PCH_FP0(id), pll->state.hw_state.fp0); - intel_de_write(i915, PCH_FP1(id), pll->state.hw_state.fp1); + intel_de_write(i915, PCH_FP0(id), hw_state->fp0); + intel_de_write(i915, PCH_FP1(id), hw_state->fp1); - intel_de_write(i915, PCH_DPLL(id), pll->state.hw_state.dpll); + intel_de_write(i915, PCH_DPLL(id), hw_state->dpll); /* Wait for the clocks to stabilize. */ intel_de_posting_read(i915, PCH_DPLL(id)); @@ -574,7 +579,7 @@ static void ibx_pch_dpll_enable(struct drm_i915_private *i915, * * So write it again. */ - intel_de_write(i915, PCH_DPLL(id), pll->state.hw_state.dpll); + intel_de_write(i915, PCH_DPLL(id), hw_state->dpll); intel_de_posting_read(i915, PCH_DPLL(id)); udelay(200); } @@ -634,21 +639,25 @@ static int ibx_get_dpll(struct intel_atomic_state *state, return 0; } -static void ibx_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) +static void ibx_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { - drm_dbg_kms(&i915->drm, - "dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, " - "fp0: 0x%x, fp1: 0x%x\n", - hw_state->dpll, - hw_state->dpll_md, - hw_state->fp0, - hw_state->fp1); + const struct i9xx_dpll_hw_state *hw_state = &dpll_hw_state->i9xx; + + drm_printf(p, "dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, " + "fp0: 0x%x, fp1: 0x%x\n", + hw_state->dpll, + hw_state->dpll_md, + hw_state->fp0, + hw_state->fp1); } -static bool ibx_compare_hw_state(const struct intel_dpll_hw_state *a, - const struct intel_dpll_hw_state *b) +static bool ibx_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) { + const struct i9xx_dpll_hw_state *a = &_a->i9xx; + const struct i9xx_dpll_hw_state *b = &_b->i9xx; + return a->dpll == b->dpll && a->dpll_md == b->dpll_md && a->fp0 == b->fp0 && @@ -677,19 +686,24 @@ static const struct intel_dpll_mgr pch_pll_mgr = { }; static void hsw_ddi_wrpll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; const enum intel_dpll_id id = pll->info->id; - intel_de_write(i915, WRPLL_CTL(id), pll->state.hw_state.wrpll); + intel_de_write(i915, WRPLL_CTL(id), hw_state->wrpll); intel_de_posting_read(i915, WRPLL_CTL(id)); udelay(20); } static void hsw_ddi_spll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { - intel_de_write(i915, SPLL_CTL, pll->state.hw_state.spll); + const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; + + intel_de_write(i915, SPLL_CTL, hw_state->spll); intel_de_posting_read(i915, SPLL_CTL); udelay(20); } @@ -728,8 +742,9 @@ static void hsw_ddi_spll_disable(struct drm_i915_private *i915, static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; const enum intel_dpll_id id = pll->info->id; intel_wakeref_t wakeref; u32 val; @@ -749,8 +764,9 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *i915, static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; intel_wakeref_t wakeref; u32 val; @@ -975,11 +991,12 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; int refclk; int n, p, r; - u32 wrpll = pll_state->wrpll; + u32 wrpll = hw_state->wrpll; switch (wrpll & WRPLL_REF_MASK) { case WRPLL_REF_SPECIAL_HSW: @@ -1020,11 +1037,12 @@ hsw_ddi_wrpll_compute_dpll(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct hsw_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.hsw; unsigned int p, n2, r2; hsw_ddi_calculate_wrpll(crtc_state->port_clock * 1000, &r2, &n2, &p); - crtc_state->dpll_hw_state.wrpll = + hw_state->wrpll = WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL | WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | WRPLL_DIVIDER_POST(p); @@ -1099,7 +1117,7 @@ hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) static int hsw_ddi_lcpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { int link_clock = 0; @@ -1127,11 +1145,12 @@ hsw_ddi_spll_compute_dpll(struct intel_atomic_state *state, { struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct hsw_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.hsw; if (drm_WARN_ON(crtc->base.dev, crtc_state->port_clock / 2 != 135000)) return -EINVAL; - crtc_state->dpll_hw_state.spll = + hw_state->spll = SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC; return 0; @@ -1150,11 +1169,12 @@ hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, static int hsw_ddi_spll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; int link_clock = 0; - switch (pll_state->spll & SPLL_FREQ_MASK) { + switch (hw_state->spll & SPLL_FREQ_MASK) { case SPLL_FREQ_810MHz: link_clock = 81000; break; @@ -1225,16 +1245,21 @@ static void hsw_update_dpll_ref_clks(struct drm_i915_private *i915) i915->display.dpll.ref_clks.nssc = 135000; } -static void hsw_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) +static void hsw_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { - drm_dbg_kms(&i915->drm, "dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", - hw_state->wrpll, hw_state->spll); + const struct hsw_dpll_hw_state *hw_state = &dpll_hw_state->hsw; + + drm_printf(p, "dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", + hw_state->wrpll, hw_state->spll); } -static bool hsw_compare_hw_state(const struct intel_dpll_hw_state *a, - const struct intel_dpll_hw_state *b) +static bool hsw_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) { + const struct hsw_dpll_hw_state *a = &_a->hsw; + const struct hsw_dpll_hw_state *b = &_b->hsw; + return a->wrpll == b->wrpll && a->spll == b->spll; } @@ -1254,7 +1279,8 @@ static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { }; static void hsw_ddi_lcpll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *hw_state) { } @@ -1265,7 +1291,7 @@ static void hsw_ddi_lcpll_disable(struct drm_i915_private *i915, static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { return true; } @@ -1332,26 +1358,31 @@ static const struct skl_dpll_regs skl_dpll_regs[4] = { }; static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct skl_dpll_hw_state *hw_state) { const enum intel_dpll_id id = pll->info->id; intel_de_rmw(i915, DPLL_CTRL1, - DPLL_CTRL1_HDMI_MODE(id) | DPLL_CTRL1_SSC(id) | DPLL_CTRL1_LINK_RATE_MASK(id), - pll->state.hw_state.ctrl1 << (id * 6)); + DPLL_CTRL1_HDMI_MODE(id) | + DPLL_CTRL1_SSC(id) | + DPLL_CTRL1_LINK_RATE_MASK(id), + hw_state->ctrl1 << (id * 6)); intel_de_posting_read(i915, DPLL_CTRL1); } static void skl_ddi_pll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; const struct skl_dpll_regs *regs = skl_dpll_regs; const enum intel_dpll_id id = pll->info->id; - skl_ddi_pll_write_ctrl1(i915, pll); + skl_ddi_pll_write_ctrl1(i915, pll, hw_state); - intel_de_write(i915, regs[id].cfgcr1, pll->state.hw_state.cfgcr1); - intel_de_write(i915, regs[id].cfgcr2, pll->state.hw_state.cfgcr2); + intel_de_write(i915, regs[id].cfgcr1, hw_state->cfgcr1); + intel_de_write(i915, regs[id].cfgcr2, hw_state->cfgcr2); intel_de_posting_read(i915, regs[id].cfgcr1); intel_de_posting_read(i915, regs[id].cfgcr2); @@ -1363,9 +1394,12 @@ static void skl_ddi_pll_enable(struct drm_i915_private *i915, } static void skl_ddi_dpll0_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { - skl_ddi_pll_write_ctrl1(i915, pll); + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; + + skl_ddi_pll_write_ctrl1(i915, pll, hw_state); } static void skl_ddi_pll_disable(struct drm_i915_private *i915, @@ -1386,13 +1420,14 @@ static void skl_ddi_dpll0_disable(struct drm_i915_private *i915, static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { - u32 val; + struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; const struct skl_dpll_regs *regs = skl_dpll_regs; const enum intel_dpll_id id = pll->info->id; intel_wakeref_t wakeref; bool ret; + u32 val; wakeref = intel_display_power_get_if_enabled(i915, POWER_DOMAIN_DISPLAY_CORE); @@ -1423,8 +1458,9 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *i915, static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; const struct skl_dpll_regs *regs = skl_dpll_regs; const enum intel_dpll_id id = pll->info->id; intel_wakeref_t wakeref; @@ -1695,16 +1731,17 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; int ref_clock = i915->display.dpll.ref_clks.nssc; u32 p0, p1, p2, dco_freq; - p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK; - p2 = pll_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK; + p0 = hw_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK; + p2 = hw_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK; - if (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_MODE(1)) - p1 = (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8; + if (hw_state->cfgcr2 & DPLL_CFGCR2_QDIV_MODE(1)) + p1 = (hw_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8; else p1 = 1; @@ -1752,10 +1789,10 @@ static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, return 0; } - dco_freq = (pll_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK) * + dco_freq = (hw_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK) * ref_clock; - dco_freq += ((pll_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * + dco_freq += ((hw_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * ref_clock / 0x8000; if (drm_WARN_ON(&i915->drm, p0 == 0 || p1 == 0 || p2 == 0)) @@ -1767,37 +1804,35 @@ static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct skl_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.skl; struct skl_wrpll_params wrpll_params = {}; - u32 ctrl1, cfgcr1, cfgcr2; int ret; - /* - * See comment in intel_dpll_hw_state to understand why we always use 0 - * as the DPLL id in this function. - */ - ctrl1 = DPLL_CTRL1_OVERRIDE(0); - - ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); - ret = skl_ddi_calculate_wrpll(crtc_state->port_clock * 1000, i915->display.dpll.ref_clks.nssc, &wrpll_params); if (ret) return ret; - cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | + /* + * See comment in intel_dpll_hw_state to understand why we always use 0 + * as the DPLL id in this function. + */ + hw_state->ctrl1 = + DPLL_CTRL1_OVERRIDE(0) | + DPLL_CTRL1_HDMI_MODE(0); + + hw_state->cfgcr1 = + DPLL_CFGCR1_FREQ_ENABLE | DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | wrpll_params.dco_integer; - cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | + hw_state->cfgcr2 = + DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | wrpll_params.central_freq; - crtc_state->dpll_hw_state.ctrl1 = ctrl1; - crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; - crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; - crtc_state->port_clock = skl_ddi_wrpll_get_freq(i915, NULL, &crtc_state->dpll_hw_state); @@ -1807,6 +1842,7 @@ static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) static int skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) { + struct skl_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.skl; u32 ctrl1; /* @@ -1836,18 +1872,19 @@ skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) break; } - crtc_state->dpll_hw_state.ctrl1 = ctrl1; + hw_state->ctrl1 = ctrl1; return 0; } static int skl_ddi_lcpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; int link_clock = 0; - switch ((pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0)) >> + switch ((hw_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0)) >> DPLL_CTRL1_LINK_RATE_SHIFT(0)) { case DPLL_CTRL1_LINK_RATE_810: link_clock = 81000; @@ -1921,16 +1958,18 @@ static int skl_get_dpll(struct intel_atomic_state *state, static int skl_ddi_pll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; + /* * ctrl1 register is already shifted for each pll, just use 0 to get * the internal shift for each field */ - if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) - return skl_ddi_wrpll_get_freq(i915, pll, pll_state); + if (hw_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) + return skl_ddi_wrpll_get_freq(i915, pll, dpll_hw_state); else - return skl_ddi_lcpll_get_freq(i915, pll, pll_state); + return skl_ddi_lcpll_get_freq(i915, pll, dpll_hw_state); } static void skl_update_dpll_ref_clks(struct drm_i915_private *i915) @@ -1939,19 +1978,21 @@ static void skl_update_dpll_ref_clks(struct drm_i915_private *i915) i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref; } -static void skl_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) +static void skl_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { - drm_dbg_kms(&i915->drm, "dpll_hw_state: " - "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", - hw_state->ctrl1, - hw_state->cfgcr1, - hw_state->cfgcr2); + const struct skl_dpll_hw_state *hw_state = &dpll_hw_state->skl; + + drm_printf(p, "dpll_hw_state: ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", + hw_state->ctrl1, hw_state->cfgcr1, hw_state->cfgcr2); } -static bool skl_compare_hw_state(const struct intel_dpll_hw_state *a, - const struct intel_dpll_hw_state *b) +static bool skl_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) { + const struct skl_dpll_hw_state *a = &_a->skl; + const struct skl_dpll_hw_state *b = &_b->skl; + return a->ctrl1 == b->ctrl1 && a->cfgcr1 == b->cfgcr1 && a->cfgcr2 == b->cfgcr2; @@ -1991,12 +2032,14 @@ static const struct intel_dpll_mgr skl_pll_mgr = { }; static void bxt_ddi_pll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { - u32 temp; + const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ enum dpio_phy phy; enum dpio_channel ch; + u32 temp; bxt_port_to_phy_channel(i915, port, &phy, &ch); @@ -2019,43 +2062,43 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *i915, /* Write P1 & P2 */ intel_de_rmw(i915, BXT_PORT_PLL_EBB_0(phy, ch), - PORT_PLL_P1_MASK | PORT_PLL_P2_MASK, pll->state.hw_state.ebb0); + PORT_PLL_P1_MASK | PORT_PLL_P2_MASK, hw_state->ebb0); /* Write M2 integer */ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 0), - PORT_PLL_M2_INT_MASK, pll->state.hw_state.pll0); + PORT_PLL_M2_INT_MASK, hw_state->pll0); /* Write N */ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 1), - PORT_PLL_N_MASK, pll->state.hw_state.pll1); + PORT_PLL_N_MASK, hw_state->pll1); /* Write M2 fraction */ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 2), - PORT_PLL_M2_FRAC_MASK, pll->state.hw_state.pll2); + PORT_PLL_M2_FRAC_MASK, hw_state->pll2); /* Write M2 fraction enable */ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 3), - PORT_PLL_M2_FRAC_ENABLE, pll->state.hw_state.pll3); + PORT_PLL_M2_FRAC_ENABLE, hw_state->pll3); /* Write coeff */ temp = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 6)); temp &= ~PORT_PLL_PROP_COEFF_MASK; temp &= ~PORT_PLL_INT_COEFF_MASK; temp &= ~PORT_PLL_GAIN_CTL_MASK; - temp |= pll->state.hw_state.pll6; + temp |= hw_state->pll6; intel_de_write(i915, BXT_PORT_PLL(phy, ch, 6), temp); /* Write calibration val */ intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 8), - PORT_PLL_TARGET_CNT_MASK, pll->state.hw_state.pll8); + PORT_PLL_TARGET_CNT_MASK, hw_state->pll8); intel_de_rmw(i915, BXT_PORT_PLL(phy, ch, 9), - PORT_PLL_LOCK_THRESHOLD_MASK, pll->state.hw_state.pll9); + PORT_PLL_LOCK_THRESHOLD_MASK, hw_state->pll9); temp = intel_de_read(i915, BXT_PORT_PLL(phy, ch, 10)); temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; temp &= ~PORT_PLL_DCO_AMP_MASK; - temp |= pll->state.hw_state.pll10; + temp |= hw_state->pll10; intel_de_write(i915, BXT_PORT_PLL(phy, ch, 10), temp); /* Recalibrate with new settings */ @@ -2063,7 +2106,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *i915, temp |= PORT_PLL_RECALIBRATE; intel_de_write(i915, BXT_PORT_PLL_EBB_4(phy, ch), temp); temp &= ~PORT_PLL_10BIT_CLK_ENABLE; - temp |= pll->state.hw_state.ebb4; + temp |= hw_state->ebb4; intel_de_write(i915, BXT_PORT_PLL_EBB_4(phy, ch), temp); /* Enable PLL */ @@ -2075,7 +2118,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *i915, drm_err(&i915->drm, "PLL %d not locked\n", port); if (IS_GEMINILAKE(i915)) { - temp = intel_de_read(i915, BXT_PORT_TX_DW5_LN0(phy, ch)); + temp = intel_de_read(i915, BXT_PORT_TX_DW5_LN(phy, ch, 0)); temp |= DCC_DELAY_RANGE_2; intel_de_write(i915, BXT_PORT_TX_DW5_GRP(phy, ch), temp); } @@ -2087,7 +2130,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *i915, temp = intel_de_read(i915, BXT_PORT_PCS_DW12_LN01(phy, ch)); temp &= ~LANE_STAGGER_MASK; temp &= ~LANESTAGGER_STRAP_OVRD; - temp |= pll->state.hw_state.pcsdw12; + temp |= hw_state->pcsdw12; intel_de_write(i915, BXT_PORT_PCS_DW12_GRP(phy, ch), temp); } @@ -2112,8 +2155,9 @@ static void bxt_ddi_pll_disable(struct drm_i915_private *i915, static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ intel_wakeref_t wakeref; enum dpio_phy phy; @@ -2245,7 +2289,7 @@ static int bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, const struct dpll *clk_div) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state; + struct bxt_dpll_hw_state *hw_state = &crtc_state->dpll_hw_state.bxt; int clock = crtc_state->port_clock; int vco = clk_div->vco; u32 prop_coef, int_coef, gain_ctl, targ_cnt; @@ -2283,45 +2327,47 @@ static int bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, else lanestagger = 0x02; - dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); - dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22); - dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); - dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff); + hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); + hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22); + hw_state->pll1 = PORT_PLL_N(clk_div->n); + hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff); if (clk_div->m2 & 0x3fffff) - dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; + hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; - dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) | + hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) | PORT_PLL_INT_COEFF(int_coef) | PORT_PLL_GAIN_CTL(gain_ctl); - dpll_hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt); + hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt); - dpll_hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5); + hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5); - dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(15) | + hw_state->pll10 = PORT_PLL_DCO_AMP(15) | PORT_PLL_DCO_AMP_OVR_EN_H; - dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE; + hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE; - dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; + hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; return 0; } static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; struct dpll clock; clock.m1 = 2; - clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, pll_state->pll0) << 22; - if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE) - clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, pll_state->pll2); - clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, pll_state->pll1); - clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0); - clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0); + clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, hw_state->pll0) << 22; + if (hw_state->pll3 & PORT_PLL_M2_FRAC_ENABLE) + clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, + hw_state->pll2); + clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, hw_state->pll1); + clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, hw_state->ebb0); + clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, hw_state->ebb0); return chv_calc_dpll_params(i915->display.dpll.ref_clks.nssc, &clock); } @@ -2402,28 +2448,26 @@ static void bxt_update_dpll_ref_clks(struct drm_i915_private *i915) /* DSI non-SSC ref 19.2MHz */ } -static void bxt_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) +static void bxt_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { - drm_dbg_kms(&i915->drm, "dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," - "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " - "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", - hw_state->ebb0, - hw_state->ebb4, - hw_state->pll0, - hw_state->pll1, - hw_state->pll2, - hw_state->pll3, - hw_state->pll6, - hw_state->pll8, - hw_state->pll9, - hw_state->pll10, - hw_state->pcsdw12); + const struct bxt_dpll_hw_state *hw_state = &dpll_hw_state->bxt; + + drm_printf(p, "dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," + "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " + "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", + hw_state->ebb0, hw_state->ebb4, + hw_state->pll0, hw_state->pll1, hw_state->pll2, hw_state->pll3, + hw_state->pll6, hw_state->pll8, hw_state->pll9, hw_state->pll10, + hw_state->pcsdw12); } -static bool bxt_compare_hw_state(const struct intel_dpll_hw_state *a, - const struct intel_dpll_hw_state *b) +static bool bxt_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) { + const struct bxt_dpll_hw_state *a = &_a->bxt; + const struct bxt_dpll_hw_state *b = &_b->bxt; + return a->ebb0 == b->ebb0 && a->ebb4 == b->ebb4 && a->pll0 == b->pll0 && @@ -2706,7 +2750,7 @@ static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, static int icl_ddi_tbt_pll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { /* * The PLL outputs multiple frequencies at the same time, selection is @@ -2777,17 +2821,18 @@ icl_calc_wrpll(struct intel_crtc_state *crtc_state, static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; int ref_clock = icl_wrpll_ref_clock(i915); u32 dco_fraction; u32 p0, p1, p2, dco_freq; - p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK; - p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK; + p0 = hw_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK; + p2 = hw_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK; - if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1)) - p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >> + if (hw_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1)) + p1 = (hw_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >> DPLL_CFGCR1_QDIV_RATIO_SHIFT; else p1 = 1; @@ -2819,10 +2864,10 @@ static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, break; } - dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * + dco_freq = (hw_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock; - dco_fraction = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> + dco_fraction = (hw_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> DPLL_CFGCR0_DCO_FRACTION_SHIFT; if (ehl_combo_pll_div_frac_wa_needed(i915)) @@ -2838,33 +2883,34 @@ static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, static void icl_calc_dpll_state(struct drm_i915_private *i915, const struct skl_wrpll_params *pll_params, - struct intel_dpll_hw_state *pll_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; u32 dco_fraction = pll_params->dco_fraction; if (ehl_combo_pll_div_frac_wa_needed(i915)) dco_fraction = DIV_ROUND_CLOSEST(dco_fraction, 2); - pll_state->cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(dco_fraction) | + hw_state->cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(dco_fraction) | pll_params->dco_integer; - pll_state->cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params->qdiv_ratio) | + hw_state->cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params->qdiv_ratio) | DPLL_CFGCR1_QDIV_MODE(pll_params->qdiv_mode) | DPLL_CFGCR1_KDIV(pll_params->kdiv) | DPLL_CFGCR1_PDIV(pll_params->pdiv); if (DISPLAY_VER(i915) >= 12) - pll_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL; + hw_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL; else - pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400; + hw_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400; if (i915->display.vbt.override_afc_startup) - pll_state->div0 = TGL_DPLL0_DIV0_AFC_STARTUP(i915->display.vbt.override_afc_startup_val); + hw_state->div0 = TGL_DPLL0_DIV0_AFC_STARTUP(i915->display.vbt.override_afc_startup_val); } static int icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, u32 *target_dco_khz, - struct intel_dpll_hw_state *state, + struct icl_dpll_hw_state *hw_state, bool is_dkl) { static const u8 div1_vals[] = { 7, 5, 3, 2 }; @@ -2920,12 +2966,12 @@ static int icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, *target_dco_khz = dco; - state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1); + hw_state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1); - state->mg_clktop2_coreclkctl1 = + hw_state->mg_clktop2_coreclkctl1 = MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(a_divratio); - state->mg_clktop2_hsclkctl = + hw_state->mg_clktop2_hsclkctl = MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(tlinedrv) | MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(inputsel) | hsdiv | @@ -2943,9 +2989,10 @@ static int icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, * adapted to integer-only calculation, that's why it looks so different. */ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, - struct intel_dpll_hw_state *pll_state) + struct intel_dpll_hw_state *dpll_hw_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; int refclk_khz = i915->display.dpll.ref_clks.nssc; int clock = crtc_state->port_clock; u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; @@ -2960,7 +3007,7 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, int ret; ret = icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz, - pll_state, is_dkl); + hw_state, is_dkl); if (ret) return ret; @@ -3050,61 +3097,61 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, /* write pll_state calculations */ if (is_dkl) { - pll_state->mg_pll_div0 = DKL_PLL_DIV0_INTEG_COEFF(int_coeff) | + hw_state->mg_pll_div0 = DKL_PLL_DIV0_INTEG_COEFF(int_coeff) | DKL_PLL_DIV0_PROP_COEFF(prop_coeff) | DKL_PLL_DIV0_FBPREDIV(m1div) | DKL_PLL_DIV0_FBDIV_INT(m2div_int); if (i915->display.vbt.override_afc_startup) { u8 val = i915->display.vbt.override_afc_startup_val; - pll_state->mg_pll_div0 |= DKL_PLL_DIV0_AFC_STARTUP(val); + hw_state->mg_pll_div0 |= DKL_PLL_DIV0_AFC_STARTUP(val); } - pll_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) | + hw_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) | DKL_PLL_DIV1_TDC_TARGET_CNT(tdc_targetcnt); - pll_state->mg_pll_ssc = DKL_PLL_SSC_IREF_NDIV_RATIO(iref_ndiv) | + hw_state->mg_pll_ssc = DKL_PLL_SSC_IREF_NDIV_RATIO(iref_ndiv) | DKL_PLL_SSC_STEP_LEN(ssc_steplen) | DKL_PLL_SSC_STEP_NUM(ssc_steplog) | (use_ssc ? DKL_PLL_SSC_EN : 0); - pll_state->mg_pll_bias = (m2div_frac ? DKL_PLL_BIAS_FRAC_EN_H : 0) | + hw_state->mg_pll_bias = (m2div_frac ? DKL_PLL_BIAS_FRAC_EN_H : 0) | DKL_PLL_BIAS_FBDIV_FRAC(m2div_frac); - pll_state->mg_pll_tdc_coldst_bias = + hw_state->mg_pll_tdc_coldst_bias = DKL_PLL_TDC_SSC_STEP_SIZE(ssc_stepsize) | DKL_PLL_TDC_FEED_FWD_GAIN(feedfwgain); } else { - pll_state->mg_pll_div0 = + hw_state->mg_pll_div0 = (m2div_rem > 0 ? MG_PLL_DIV0_FRACNEN_H : 0) | MG_PLL_DIV0_FBDIV_FRAC(m2div_frac) | MG_PLL_DIV0_FBDIV_INT(m2div_int); - pll_state->mg_pll_div1 = + hw_state->mg_pll_div1 = MG_PLL_DIV1_IREF_NDIVRATIO(iref_ndiv) | MG_PLL_DIV1_DITHER_DIV_2 | MG_PLL_DIV1_NDIVRATIO(1) | MG_PLL_DIV1_FBPREDIV(m1div); - pll_state->mg_pll_lf = + hw_state->mg_pll_lf = MG_PLL_LF_TDCTARGETCNT(tdc_targetcnt) | MG_PLL_LF_AFCCNTSEL_512 | MG_PLL_LF_GAINCTRL(1) | MG_PLL_LF_INT_COEFF(int_coeff) | MG_PLL_LF_PROP_COEFF(prop_coeff); - pll_state->mg_pll_frac_lock = + hw_state->mg_pll_frac_lock = MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 | MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 | MG_PLL_FRAC_LOCK_LOCKTHRESH(10) | MG_PLL_FRAC_LOCK_DCODITHEREN | MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(feedfwgain); if (use_ssc || m2div_rem > 0) - pll_state->mg_pll_frac_lock |= + hw_state->mg_pll_frac_lock |= MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN; - pll_state->mg_pll_ssc = + hw_state->mg_pll_ssc = (use_ssc ? MG_PLL_SSC_EN : 0) | MG_PLL_SSC_TYPE(2) | MG_PLL_SSC_STEPLENGTH(ssc_steplen) | @@ -3112,14 +3159,14 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, MG_PLL_SSC_FLLEN | MG_PLL_SSC_STEPSIZE(ssc_stepsize); - pll_state->mg_pll_tdc_coldst_bias = + hw_state->mg_pll_tdc_coldst_bias = MG_PLL_TDC_COLDST_COLDSTART | MG_PLL_TDC_COLDST_IREFINT_EN | MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(iref_pulse_w) | MG_PLL_TDC_TDCOVCCORR_EN | MG_PLL_TDC_TDCSEL(3); - pll_state->mg_pll_bias = + hw_state->mg_pll_bias = MG_PLL_BIAS_BIAS_GB_SEL(3) | MG_PLL_BIAS_INIT_DCOAMP(0x3F) | MG_PLL_BIAS_BIAS_BONUS(10) | @@ -3129,17 +3176,17 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, MG_PLL_BIAS_IREFTRIM(iref_trim); if (refclk_khz == 38400) { - pll_state->mg_pll_tdc_coldst_bias_mask = + hw_state->mg_pll_tdc_coldst_bias_mask = MG_PLL_TDC_COLDST_COLDSTART; - pll_state->mg_pll_bias_mask = 0; + hw_state->mg_pll_bias_mask = 0; } else { - pll_state->mg_pll_tdc_coldst_bias_mask = -1U; - pll_state->mg_pll_bias_mask = -1U; + hw_state->mg_pll_tdc_coldst_bias_mask = -1U; + hw_state->mg_pll_bias_mask = -1U; } - pll_state->mg_pll_tdc_coldst_bias &= - pll_state->mg_pll_tdc_coldst_bias_mask; - pll_state->mg_pll_bias &= pll_state->mg_pll_bias_mask; + hw_state->mg_pll_tdc_coldst_bias &= + hw_state->mg_pll_tdc_coldst_bias_mask; + hw_state->mg_pll_bias &= hw_state->mg_pll_bias_mask; } return 0; @@ -3147,31 +3194,32 @@ static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; u32 m1, m2_int, m2_frac, div1, div2, ref_clock; u64 tmp; ref_clock = i915->display.dpll.ref_clks.nssc; if (DISPLAY_VER(i915) >= 12) { - m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK; + m1 = hw_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK; m1 = m1 >> DKL_PLL_DIV0_FBPREDIV_SHIFT; - m2_int = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK; + m2_int = hw_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK; - if (pll_state->mg_pll_bias & DKL_PLL_BIAS_FRAC_EN_H) { - m2_frac = pll_state->mg_pll_bias & + if (hw_state->mg_pll_bias & DKL_PLL_BIAS_FRAC_EN_H) { + m2_frac = hw_state->mg_pll_bias & DKL_PLL_BIAS_FBDIV_FRAC_MASK; m2_frac = m2_frac >> DKL_PLL_BIAS_FBDIV_SHIFT; } else { m2_frac = 0; } } else { - m1 = pll_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK; - m2_int = pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK; + m1 = hw_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK; + m2_int = hw_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK; - if (pll_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) { - m2_frac = pll_state->mg_pll_div0 & + if (hw_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) { + m2_frac = hw_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_FRAC_MASK; m2_frac = m2_frac >> MG_PLL_DIV0_FBDIV_FRAC_SHIFT; } else { @@ -3179,7 +3227,7 @@ static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *i915, } } - switch (pll_state->mg_clktop2_hsclkctl & + switch (hw_state->mg_clktop2_hsclkctl & MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) { case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2: div1 = 2; @@ -3194,11 +3242,11 @@ static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *i915, div1 = 7; break; default: - MISSING_CASE(pll_state->mg_clktop2_hsclkctl); + MISSING_CASE(hw_state->mg_clktop2_hsclkctl); return 0; } - div2 = (pll_state->mg_clktop2_hsclkctl & + div2 = (hw_state->mg_clktop2_hsclkctl & MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >> MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_SHIFT; @@ -3389,7 +3437,6 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct icl_port_dpll *port_dpll = @@ -3408,8 +3455,7 @@ static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; - dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(i915, - encoder->port)); + dpll_id = icl_tc_port_to_pll_id(intel_encoder_to_tc(encoder)); port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, BIT(dpll_id)); @@ -3435,15 +3481,12 @@ static int icl_compute_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(state->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_phy_is_combo(i915, phy)) + if (intel_encoder_is_combo(encoder)) return icl_compute_combo_phy_dpll(state, crtc); - else if (intel_phy_is_tc(i915, phy)) + else if (intel_encoder_is_tc(encoder)) return icl_compute_tc_phy_dplls(state, crtc); - MISSING_CASE(phy); + MISSING_CASE(encoder->port); return 0; } @@ -3452,15 +3495,12 @@ static int icl_get_dplls(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(state->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); - - if (intel_phy_is_combo(i915, phy)) + if (intel_encoder_is_combo(encoder)) return icl_get_combo_phy_dpll(state, crtc, encoder); - else if (intel_phy_is_tc(i915, phy)) + else if (intel_encoder_is_tc(encoder)) return icl_get_tc_phy_dplls(state, crtc, encoder); - MISSING_CASE(phy); + MISSING_CASE(encoder->port); return -EINVAL; } @@ -3493,8 +3533,9 @@ static void icl_put_dplls(struct intel_atomic_state *state, static bool mg_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; const enum intel_dpll_id id = pll->info->id; enum tc_port tc_port = icl_pll_id_to_tc_port(id); intel_wakeref_t wakeref; @@ -3559,8 +3600,9 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *i915, static bool dkl_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { + struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; const enum intel_dpll_id id = pll->info->id; enum tc_port tc_port = icl_pll_id_to_tc_port(id); intel_wakeref_t wakeref; @@ -3630,9 +3672,10 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *i915, static bool icl_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state, + struct intel_dpll_hw_state *dpll_hw_state, i915_reg_t enable_reg) { + struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; const enum intel_dpll_id id = pll->info->id; intel_wakeref_t wakeref; bool ret = false; @@ -3690,24 +3733,24 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *i915, static bool combo_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { i915_reg_t enable_reg = intel_combo_pll_enable_reg(i915, pll); - return icl_pll_get_hw_state(i915, pll, hw_state, enable_reg); + return icl_pll_get_hw_state(i915, pll, dpll_hw_state, enable_reg); } static bool tbt_pll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { - return icl_pll_get_hw_state(i915, pll, hw_state, TBT_PLL_ENABLE); + return icl_pll_get_hw_state(i915, pll, dpll_hw_state, TBT_PLL_ENABLE); } static void icl_dpll_write(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct icl_dpll_hw_state *hw_state) { - struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; const enum intel_dpll_id id = pll->info->id; i915_reg_t cfgcr0_reg, cfgcr1_reg, div0_reg = INVALID_MMIO_REG; @@ -3747,9 +3790,9 @@ static void icl_dpll_write(struct drm_i915_private *i915, } static void icl_mg_pll_write(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct icl_dpll_hw_state *hw_state) { - struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); /* @@ -3790,9 +3833,9 @@ static void icl_mg_pll_write(struct drm_i915_private *i915, } static void dkl_pll_write(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct icl_dpll_hw_state *hw_state) { - struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); u32 val; @@ -3905,13 +3948,15 @@ static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct inte } static void combo_pll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; i915_reg_t enable_reg = intel_combo_pll_enable_reg(i915, pll); icl_pll_power_enable(i915, pll, enable_reg); - icl_dpll_write(i915, pll); + icl_dpll_write(i915, pll, hw_state); /* * DVFS pre sequence would be here, but in our driver the cdclk code @@ -3927,11 +3972,14 @@ static void combo_pll_enable(struct drm_i915_private *i915, } static void tbt_pll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; + icl_pll_power_enable(i915, pll, TBT_PLL_ENABLE); - icl_dpll_write(i915, pll); + icl_dpll_write(i915, pll, hw_state); /* * DVFS pre sequence would be here, but in our driver the cdclk code @@ -3945,16 +3993,18 @@ static void tbt_pll_enable(struct drm_i915_private *i915, } static void mg_pll_enable(struct drm_i915_private *i915, - struct intel_shared_dpll *pll) + struct intel_shared_dpll *pll, + const struct intel_dpll_hw_state *dpll_hw_state) { + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; i915_reg_t enable_reg = intel_tc_pll_enable_reg(i915, pll); icl_pll_power_enable(i915, pll, enable_reg); if (DISPLAY_VER(i915) >= 12) - dkl_pll_write(i915, pll); + dkl_pll_write(i915, pll, hw_state); else - icl_mg_pll_write(i915, pll); + icl_mg_pll_write(i915, pll, hw_state); /* * DVFS pre sequence would be here, but in our driver the cdclk code @@ -4026,33 +4076,36 @@ static void icl_update_dpll_ref_clks(struct drm_i915_private *i915) i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref; } -static void icl_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) +static void icl_dump_hw_state(struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { - drm_dbg_kms(&i915->drm, - "dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, div0: 0x%x, " - "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, " - "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, " - "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, " - "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, " - "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n", - hw_state->cfgcr0, hw_state->cfgcr1, - hw_state->div0, - hw_state->mg_refclkin_ctl, - hw_state->mg_clktop2_coreclkctl1, - hw_state->mg_clktop2_hsclkctl, - hw_state->mg_pll_div0, - hw_state->mg_pll_div1, - hw_state->mg_pll_lf, - hw_state->mg_pll_frac_lock, - hw_state->mg_pll_ssc, - hw_state->mg_pll_bias, - hw_state->mg_pll_tdc_coldst_bias); + const struct icl_dpll_hw_state *hw_state = &dpll_hw_state->icl; + + drm_printf(p, "dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, div0: 0x%x, " + "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, " + "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, " + "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, " + "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, " + "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n", + hw_state->cfgcr0, hw_state->cfgcr1, hw_state->div0, + hw_state->mg_refclkin_ctl, + hw_state->mg_clktop2_coreclkctl1, + hw_state->mg_clktop2_hsclkctl, + hw_state->mg_pll_div0, + hw_state->mg_pll_div1, + hw_state->mg_pll_lf, + hw_state->mg_pll_frac_lock, + hw_state->mg_pll_ssc, + hw_state->mg_pll_bias, + hw_state->mg_pll_tdc_coldst_bias); } -static bool icl_compare_hw_state(const struct intel_dpll_hw_state *a, - const struct intel_dpll_hw_state *b) +static bool icl_compare_hw_state(const struct intel_dpll_hw_state *_a, + const struct intel_dpll_hw_state *_b) { + const struct icl_dpll_hw_state *a = &_a->icl; + const struct icl_dpll_hw_state *b = &_b->icl; + /* FIXME split combo vs. mg more thoroughly */ return a->cfgcr0 == b->cfgcr0 && a->cfgcr1 == b->cfgcr1 && @@ -4417,33 +4470,33 @@ void intel_update_active_dpll(struct intel_atomic_state *state, * intel_dpll_get_freq - calculate the DPLL's output frequency * @i915: i915 device * @pll: DPLL for which to calculate the output frequency - * @pll_state: DPLL state from which to calculate the output frequency + * @dpll_hw_state: DPLL state from which to calculate the output frequency * - * Return the output frequency corresponding to @pll's passed in @pll_state. + * Return the output frequency corresponding to @pll's passed in @dpll_hw_state. */ int intel_dpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state) + const struct intel_dpll_hw_state *dpll_hw_state) { if (drm_WARN_ON(&i915->drm, !pll->info->funcs->get_freq)) return 0; - return pll->info->funcs->get_freq(i915, pll, pll_state); + return pll->info->funcs->get_freq(i915, pll, dpll_hw_state); } /** * intel_dpll_get_hw_state - readout the DPLL's hardware state * @i915: i915 device * @pll: DPLL for which to calculate the output frequency - * @hw_state: DPLL's hardware state + * @dpll_hw_state: DPLL's hardware state * - * Read out @pll's hardware state into @hw_state. + * Read out @pll's hardware state into @dpll_hw_state. */ bool intel_dpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state) + struct intel_dpll_hw_state *dpll_hw_state) { - return pll->info->funcs->get_hw_state(i915, pll, hw_state); + return pll->info->funcs->get_hw_state(i915, pll, dpll_hw_state); } static void readout_dpll_hw_state(struct drm_i915_private *i915, @@ -4514,22 +4567,24 @@ void intel_dpll_sanitize_state(struct drm_i915_private *i915) } /** - * intel_dpll_dump_hw_state - write hw_state to dmesg + * intel_dpll_dump_hw_state - dump hw_state * @i915: i915 drm device - * @hw_state: hw state to be written to the log + * @p: where to print the state to + * @dpll_hw_state: hw state to be dumped * - * Write the relevant values in @hw_state to dmesg using drm_dbg_kms. + * Dumo out the relevant values in @dpll_hw_state. */ void intel_dpll_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state) + struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state) { if (i915->display.dpll.mgr) { - i915->display.dpll.mgr->dump_hw_state(i915, hw_state); + i915->display.dpll.mgr->dump_hw_state(p, dpll_hw_state); } else { /* fallback for platforms that don't use the shared dpll * infrastructure */ - ibx_dump_hw_state(i915, hw_state); + ibx_dump_hw_state(p, dpll_hw_state); } } diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h index cc0e1386309d..f09e513ce05b 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h @@ -36,6 +36,7 @@ enum tc_port; struct drm_i915_private; +struct drm_printer; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -180,18 +181,19 @@ enum icl_port_dpll_id { ICL_PORT_DPLL_COUNT, }; -struct intel_dpll_hw_state { - /* i9xx, pch plls */ +struct i9xx_dpll_hw_state { u32 dpll; u32 dpll_md; u32 fp0; u32 fp1; +}; - /* hsw, bdw */ +struct hsw_dpll_hw_state { u32 wrpll; u32 spll; +}; - /* skl */ +struct skl_dpll_hw_state { /* * DPLL_CTRL1 has 6 bits for each each this DPLL. We store those in * lower part of ctrl1 and they get shifted into position when writing @@ -201,20 +203,18 @@ struct intel_dpll_hw_state { u32 ctrl1; /* HDMI only, 0 when used for DP */ u32 cfgcr1, cfgcr2; +}; - /* icl */ - u32 cfgcr0; +struct bxt_dpll_hw_state { + u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12; +}; + +struct icl_dpll_hw_state { + u32 cfgcr0, cfgcr1; /* tgl */ u32 div0; - /* bxt */ - u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12; - - /* - * ICL uses the following, already defined: - * u32 cfgcr0, cfgcr1; - */ u32 mg_refclkin_ctl; u32 mg_clktop2_coreclkctl1; u32 mg_clktop2_hsclkctl; @@ -229,6 +229,55 @@ struct intel_dpll_hw_state { u32 mg_pll_tdc_coldst_bias_mask; }; +struct intel_mpllb_state { + u32 clock; /* in KHz */ + u32 ref_control; + u32 mpllb_cp; + u32 mpllb_div; + u32 mpllb_div2; + u32 mpllb_fracn1; + u32 mpllb_fracn2; + u32 mpllb_sscen; + u32 mpllb_sscstep; +}; + +struct intel_c10pll_state { + u32 clock; /* in KHz */ + u8 tx; + u8 cmn; + u8 pll[20]; +}; + +struct intel_c20pll_state { + u32 clock; /* in kHz */ + u16 tx[3]; + u16 cmn[4]; + union { + u16 mplla[10]; + u16 mpllb[11]; + }; +}; + +struct intel_cx0pll_state { + union { + struct intel_c10pll_state c10; + struct intel_c20pll_state c20; + }; + bool ssc_enabled; +}; + +struct intel_dpll_hw_state { + union { + struct i9xx_dpll_hw_state i9xx; + struct hsw_dpll_hw_state hsw; + struct skl_dpll_hw_state skl; + struct bxt_dpll_hw_state bxt; + struct icl_dpll_hw_state icl; + struct intel_mpllb_state mpllb; + struct intel_cx0pll_state cx0pll; + }; +}; + /** * struct intel_shared_dpll_state - hold the DPLL atomic state * @@ -364,10 +413,10 @@ void intel_update_active_dpll(struct intel_atomic_state *state, struct intel_encoder *encoder); int intel_dpll_get_freq(struct drm_i915_private *i915, const struct intel_shared_dpll *pll, - const struct intel_dpll_hw_state *pll_state); + const struct intel_dpll_hw_state *dpll_hw_state); bool intel_dpll_get_hw_state(struct drm_i915_private *i915, struct intel_shared_dpll *pll, - struct intel_dpll_hw_state *hw_state); + struct intel_dpll_hw_state *dpll_hw_state); void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state); void intel_shared_dpll_swap_state(struct intel_atomic_state *state); @@ -377,7 +426,8 @@ void intel_dpll_readout_hw_state(struct drm_i915_private *i915); void intel_dpll_sanitize_state(struct drm_i915_private *i915); void intel_dpll_dump_hw_state(struct drm_i915_private *i915, - const struct intel_dpll_hw_state *hw_state); + struct drm_printer *p, + const struct intel_dpll_hw_state *dpll_hw_state); bool intel_dpll_compare_hw_state(struct drm_i915_private *i915, const struct intel_dpll_hw_state *a, const struct intel_dpll_hw_state *b); diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index e4515bf92038..4baaa92ceaec 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -343,12 +343,13 @@ static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state) static u32 dsb_chicken(struct intel_crtc *crtc) { if (crtc->mode_flags & I915_MODE_FLAG_VRR) - return DSB_CTRL_WAIT_SAFE_WINDOW | + return DSB_SKIP_WAITS_EN | + DSB_CTRL_WAIT_SAFE_WINDOW | DSB_CTRL_NO_WAIT_VBLANK | DSB_INST_WAIT_SAFE_WINDOW | DSB_INST_NO_WAIT_VBLANK; else - return 0; + return DSB_SKIP_WAITS_EN; } static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index d3cf6a652221..bd5888ce4852 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -64,14 +64,11 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, struct intel_connector *intel_connector = to_intel_connector(connector); const struct drm_display_mode *fixed_mode = intel_panel_fixed_mode(intel_connector, mode); - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; enum drm_mode_status status; drm_dbg_kms(&dev_priv->drm, "\n"); - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - status = intel_panel_mode_valid(intel_connector, mode); if (status != MODE_OK) return status; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index c076da75b066..1840f5b59229 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -223,7 +223,7 @@ intel_dvo_mode_valid(struct drm_connector *_connector, struct intel_dvo *intel_dvo = intel_attached_dvo(connector); const struct drm_display_mode *fixed_mode = intel_panel_fixed_mode(connector, mode); - int max_dotclk = to_i915(connector->base.dev)->max_dotclk_freq; + int max_dotclk = to_i915(connector->base.dev)->display.cdclk.max_dotclk_freq; int target_clock = mode->clock; enum drm_mode_status status; @@ -231,9 +231,6 @@ intel_dvo_mode_valid(struct drm_connector *_connector, if (status != MODE_OK) return status; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - /* XXX: Validate clock range */ if (fixed_mode) { diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 3ea6470d6d92..86b443433e8b 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1106,7 +1106,7 @@ static int intel_fb_offset_to_xy(int *x, int *y, { struct drm_i915_private *i915 = to_i915(fb->dev); unsigned int height; - u32 alignment; + u32 alignment, unused; if (DISPLAY_VER(i915) >= 12 && !intel_fb_needs_pot_stride_remap(to_intel_framebuffer(fb)) && @@ -1128,8 +1128,8 @@ static int intel_fb_offset_to_xy(int *x, int *y, height = ALIGN(height, intel_tile_height(fb, color_plane)); /* Catch potential overflows early */ - if (add_overflows_t(u32, mul_u32_u32(height, fb->pitches[color_plane]), - fb->offsets[color_plane])) { + if (check_add_overflow(mul_u32_u32(height, fb->pitches[color_plane]), + fb->offsets[color_plane], &unused)) { drm_dbg_kms(&i915->drm, "Bad offset 0x%08x or pitch %d for color plane %d\n", fb->offsets[color_plane], fb->pitches[color_plane], diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index b453fcbd67da..7c4d2b2bf20b 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -826,10 +826,36 @@ static void intel_fbc_program_cfb(struct intel_fbc *fbc) static void intel_fbc_program_workarounds(struct intel_fbc *fbc) { + struct drm_i915_private *i915 = fbc->i915; + + if (IS_SKYLAKE(i915) || IS_BROXTON(i915)) { + /* + * WaFbcHighMemBwCorruptionAvoidance:skl,bxt + * Display WA #0883: skl,bxt + */ + intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + 0, DPFC_DISABLE_DUMMY0); + } + + if (IS_SKYLAKE(i915) || IS_KABYLAKE(i915) || + IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) { + /* + * WaFbcNukeOnHostModify:skl,kbl,cfl + * Display WA #0873: skl,kbl,cfl + */ + intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + 0, DPFC_NUKE_ON_ANY_MODIFICATION); + } + + /* Wa_1409120013:icl,jsl,tgl,dg1 */ + if (IS_DISPLAY_VER(i915, 11, 12)) + intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + 0, DPFC_CHICKEN_COMP_DUMMY_PIXEL); + /* Wa_22014263786:icl,jsl,tgl,dg1,rkl,adls,adlp,mtl */ - if (DISPLAY_VER(fbc->i915) >= 11 && !IS_DG2(fbc->i915)) - intel_de_rmw(fbc->i915, ILK_DPFC_CHICKEN(fbc->id), 0, - DPFC_CHICKEN_FORCE_SLB_INVALIDATION); + if (DISPLAY_VER(i915) >= 11 && !IS_DG2(i915)) + intel_de_rmw(i915, ILK_DPFC_CHICKEN(fbc->id), + 0, DPFC_CHICKEN_FORCE_SLB_INVALIDATION); } static void __intel_fbc_cleanup_cfb(struct intel_fbc *fbc) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 99894a855ef0..43855c6c3509 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -135,6 +135,9 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) return i915_gem_fb_mmap(obj, vma); } +__diag_push(); +__diag_ignore_all("-Woverride-init", "Allow field initialization overrides for fb ops"); + static const struct fb_ops intelfb_ops = { .owner = THIS_MODULE, __FB_DEFAULT_DEFERRED_OPS_RDWR(intel_fbdev), @@ -146,6 +149,8 @@ static const struct fb_ops intelfb_ops = { .fb_mmap = intel_fbdev_mmap, }; +__diag_pop(); + static int intelfb_create(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { diff --git a/drivers/gpu/drm/i915/i915_fixed.h b/drivers/gpu/drm/i915/display/intel_fixed.h similarity index 100% rename from drivers/gpu/drm/i915/i915_fixed.h rename to drivers/gpu/drm/i915/display/intel_fixed.h diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index d3e03ed5b79c..9c8e1e91ff1c 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -411,7 +411,7 @@ gmbus_wait_idle(struct drm_i915_private *i915) add_wait_queue(&i915->display.gmbus.wait_queue, &wait); intel_de_write_fw(i915, GMBUS4(i915), irq_enable); - ret = intel_de_wait_for_register_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10); + ret = intel_de_wait_fw(i915, GMBUS2(i915), GMBUS_ACTIVE, 0, 10); intel_de_write_fw(i915, GMBUS4(i915), 0); remove_wait_queue(&i915->display.gmbus.wait_queue, &wait); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 9edac27bab26..d5ed4c7dfbc0 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -369,9 +369,9 @@ static int intel_hdcp_load_keys(struct drm_i915_private *i915) } /* Wait for the keys to load (500us) */ - ret = __intel_wait_for_register(&i915->uncore, HDCP_KEY_STATUS, - HDCP_KEY_LOAD_DONE, HDCP_KEY_LOAD_DONE, - 10, 1, &val); + ret = intel_de_wait_custom(i915, HDCP_KEY_STATUS, + HDCP_KEY_LOAD_DONE, HDCP_KEY_LOAD_DONE, + 10, 1, &val); if (ret) return ret; else if (!(val & HDCP_KEY_LOAD_STATUS)) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 90d2236fede3..5f6deceaf8ba 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -114,6 +114,8 @@ static u32 g4x_infoframe_enable(unsigned int type) return VIDEO_DIP_ENABLE_GAMUT; case DP_SDP_VSC: return 0; + case DP_SDP_ADAPTIVE_SYNC: + return 0; case HDMI_INFOFRAME_TYPE_AVI: return VIDEO_DIP_ENABLE_AVI; case HDMI_INFOFRAME_TYPE_SPD: @@ -137,6 +139,8 @@ static u32 hsw_infoframe_enable(unsigned int type) return VIDEO_DIP_ENABLE_GMP_HSW; case DP_SDP_VSC: return VIDEO_DIP_ENABLE_VSC_HSW; + case DP_SDP_ADAPTIVE_SYNC: + return VIDEO_DIP_ENABLE_AS_ADL; case DP_SDP_PPS: return VDIP_ENABLE_PPS; case HDMI_INFOFRAME_TYPE_AVI: @@ -164,6 +168,8 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv, return HSW_TVIDEO_DIP_GMP_DATA(cpu_transcoder, i); case DP_SDP_VSC: return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i); + case DP_SDP_ADAPTIVE_SYNC: + return ADL_TVIDEO_DIP_AS_SDP_DATA(cpu_transcoder, i); case DP_SDP_PPS: return ICL_VIDEO_DIP_PPS_DATA(cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_AVI: @@ -186,6 +192,8 @@ static int hsw_dip_data_size(struct drm_i915_private *dev_priv, switch (type) { case DP_SDP_VSC: return VIDEO_DIP_VSC_DATA_SIZE; + case DP_SDP_ADAPTIVE_SYNC: + return VIDEO_DIP_ASYNC_DATA_SIZE; case DP_SDP_PPS: return VIDEO_DIP_PPS_DATA_SIZE; case HDMI_PACKET_TYPE_GAMUT_METADATA: @@ -563,6 +571,9 @@ static u32 hsw_infoframes_enabled(struct intel_encoder *encoder, if (DISPLAY_VER(dev_priv) >= 10) mask |= VIDEO_DIP_ENABLE_DRM_GLK; + if (HAS_AS_SDP(dev_priv)) + mask |= VIDEO_DIP_ENABLE_AS_ADL; + return val & mask; } @@ -570,6 +581,7 @@ static const u8 infoframe_type_to_idx[] = { HDMI_PACKET_TYPE_GENERAL_CONTROL, HDMI_PACKET_TYPE_GAMUT_METADATA, DP_SDP_VSC, + DP_SDP_ADAPTIVE_SYNC, HDMI_INFOFRAME_TYPE_AVI, HDMI_INFOFRAME_TYPE_SPD, HDMI_INFOFRAME_TYPE_VENDOR, @@ -1212,7 +1224,7 @@ static void hsw_set_infoframes(struct intel_encoder *encoder, val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW | - VIDEO_DIP_ENABLE_DRM_GLK); + VIDEO_DIP_ENABLE_DRM_GLK | VIDEO_DIP_ENABLE_AS_ADL); if (!enable) { intel_de_write(dev_priv, reg, val); @@ -1832,7 +1844,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, bool has_hdmi_sink) { struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); - enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port); + struct intel_encoder *encoder = &hdmi_to_dig_port(hdmi)->base; if (clock < 25000) return MODE_CLOCK_LOW; @@ -1854,11 +1866,11 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, return MODE_CLOCK_RANGE; /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */ - if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200) + if (intel_encoder_is_combo(encoder) && clock > 500000 && clock < 533200) return MODE_CLOCK_RANGE; /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */ - if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800) + if (intel_encoder_is_tc(encoder) && clock > 500000 && clock < 532800) return MODE_CLOCK_RANGE; /* @@ -1981,7 +1993,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); enum drm_mode_status status; int clock = mode->clock; - int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + int max_dotclk = to_i915(connector->dev)->display.cdclk.max_dotclk_freq; bool has_hdmi_sink = intel_has_hdmi_sink(hdmi, connector->state); bool ycbcr_420_only; enum intel_output_format sink_format; @@ -2664,8 +2676,9 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, drm_scdc_set_scrambling(connector, scrambling); } -static u8 chv_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 chv_encoder_to_ddc_pin(struct intel_encoder *encoder) { + enum port port = encoder->port; u8 ddc_pin; switch (port) { @@ -2686,8 +2699,9 @@ static u8 chv_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) return ddc_pin; } -static u8 bxt_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 bxt_encoder_to_ddc_pin(struct intel_encoder *encoder) { + enum port port = encoder->port; u8 ddc_pin; switch (port) { @@ -2705,9 +2719,9 @@ static u8 bxt_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) return ddc_pin; } -static u8 cnp_port_to_ddc_pin(struct drm_i915_private *dev_priv, - enum port port) +static u8 cnp_encoder_to_ddc_pin(struct intel_encoder *encoder) { + enum port port = encoder->port; u8 ddc_pin; switch (port) { @@ -2731,22 +2745,23 @@ static u8 cnp_port_to_ddc_pin(struct drm_i915_private *dev_priv, return ddc_pin; } -static u8 icl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 icl_encoder_to_ddc_pin(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(dev_priv, port); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = encoder->port; - if (intel_phy_is_combo(dev_priv, phy)) + if (intel_encoder_is_combo(encoder)) return GMBUS_PIN_1_BXT + port; - else if (intel_phy_is_tc(dev_priv, phy)) - return GMBUS_PIN_9_TC1_ICP + intel_port_to_tc(dev_priv, port); + else if (intel_encoder_is_tc(encoder)) + return GMBUS_PIN_9_TC1_ICP + intel_encoder_to_tc(encoder); drm_WARN(&dev_priv->drm, 1, "Unknown port:%c\n", port_name(port)); return GMBUS_PIN_2_BXT; } -static u8 mcc_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 mcc_encoder_to_ddc_pin(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(dev_priv, port); + enum phy phy = intel_encoder_to_phy(encoder); u8 ddc_pin; switch (phy) { @@ -2767,11 +2782,12 @@ static u8 mcc_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) return ddc_pin; } -static u8 rkl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 rkl_encoder_to_ddc_pin(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(dev_priv, port); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); - WARN_ON(port == PORT_C); + WARN_ON(encoder->port == PORT_C); /* * Pin mapping for RKL depends on which PCH is present. With TGP, the @@ -2785,11 +2801,12 @@ static u8 rkl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) return GMBUS_PIN_1_BXT + phy; } -static u8 gen9bc_tgp_port_to_ddc_pin(struct drm_i915_private *i915, enum port port) +static u8 gen9bc_tgp_encoder_to_ddc_pin(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(i915, port); + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); - drm_WARN_ON(&i915->drm, port == PORT_A); + drm_WARN_ON(&i915->drm, encoder->port == PORT_A); /* * Pin mapping for GEN9 BC depends on which PCH is present. With TGP, @@ -2803,16 +2820,16 @@ static u8 gen9bc_tgp_port_to_ddc_pin(struct drm_i915_private *i915, enum port po return GMBUS_PIN_1_BXT + phy; } -static u8 dg1_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 dg1_encoder_to_ddc_pin(struct intel_encoder *encoder) { - return intel_port_to_phy(dev_priv, port) + 1; + return intel_encoder_to_phy(encoder) + 1; } -static u8 adls_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port) +static u8 adls_encoder_to_ddc_pin(struct intel_encoder *encoder) { - enum phy phy = intel_port_to_phy(dev_priv, port); + enum phy phy = intel_encoder_to_phy(encoder); - WARN_ON(port == PORT_B || port == PORT_C); + WARN_ON(encoder->port == PORT_B || encoder->port == PORT_C); /* * Pin mapping for ADL-S requires TC pins for all combo phy outputs @@ -2824,9 +2841,9 @@ static u8 adls_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port return GMBUS_PIN_9_TC1_ICP + phy - PHY_B; } -static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv, - enum port port) +static u8 g4x_encoder_to_ddc_pin(struct intel_encoder *encoder) { + enum port port = encoder->port; u8 ddc_pin; switch (port) { @@ -2850,30 +2867,29 @@ static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv, static u8 intel_hdmi_default_ddc_pin(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum port port = encoder->port; u8 ddc_pin; if (IS_ALDERLAKE_S(dev_priv)) - ddc_pin = adls_port_to_ddc_pin(dev_priv, port); + ddc_pin = adls_encoder_to_ddc_pin(encoder); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) - ddc_pin = dg1_port_to_ddc_pin(dev_priv, port); + ddc_pin = dg1_encoder_to_ddc_pin(encoder); else if (IS_ROCKETLAKE(dev_priv)) - ddc_pin = rkl_port_to_ddc_pin(dev_priv, port); + ddc_pin = rkl_encoder_to_ddc_pin(encoder); else if (DISPLAY_VER(dev_priv) == 9 && HAS_PCH_TGP(dev_priv)) - ddc_pin = gen9bc_tgp_port_to_ddc_pin(dev_priv, port); + ddc_pin = gen9bc_tgp_encoder_to_ddc_pin(encoder); else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && HAS_PCH_TGP(dev_priv)) - ddc_pin = mcc_port_to_ddc_pin(dev_priv, port); + ddc_pin = mcc_encoder_to_ddc_pin(encoder); else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - ddc_pin = icl_port_to_ddc_pin(dev_priv, port); + ddc_pin = icl_encoder_to_ddc_pin(encoder); else if (HAS_PCH_CNP(dev_priv)) - ddc_pin = cnp_port_to_ddc_pin(dev_priv, port); + ddc_pin = cnp_encoder_to_ddc_pin(encoder); else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - ddc_pin = bxt_port_to_ddc_pin(dev_priv, port); + ddc_pin = bxt_encoder_to_ddc_pin(encoder); else if (IS_CHERRYVIEW(dev_priv)) - ddc_pin = chv_port_to_ddc_pin(dev_priv, port); + ddc_pin = chv_encoder_to_ddc_pin(encoder); else - ddc_pin = g4x_port_to_ddc_pin(dev_priv, port); + ddc_pin = g4x_encoder_to_ddc_pin(encoder); return ddc_pin; } diff --git a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c index 76076509f771..d270bb7b9462 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug_irq.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug_irq.c @@ -1444,7 +1444,7 @@ void intel_hpd_enable_detection(struct intel_encoder *encoder) void intel_hpd_irq_setup(struct drm_i915_private *i915) { - if (i915->display_irqs_enabled && i915->display.funcs.hotplug) + if (i915->display.irq.display_irqs_enabled && i915->display.funcs.hotplug) i915->display.funcs.hotplug->hpd_irq_setup(i915); } diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 221f5c6c871b..8b8959073466 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -392,16 +392,13 @@ intel_lvds_mode_valid(struct drm_connector *_connector, struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode = intel_panel_fixed_mode(connector, mode); - int max_pixclk = to_i915(connector->base.dev)->max_dotclk_freq; + int max_pixclk = to_i915(connector->base.dev)->display.cdclk.max_dotclk_freq; enum drm_mode_status status; status = intel_cpu_transcoder_mode_valid(i915, mode); if (status != MODE_OK) return status; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - status = intel_panel_mode_valid(connector, mode); if (status != MODE_OK) return status; diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index fcbb083318a7..68bd5101ec89 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -263,7 +262,6 @@ struct intel_opregion { struct opregion_asle *asle; struct opregion_asle_ext *asle_ext; void *rvda; - void *vbt_firmware; const void *vbt; u32 vbt_size; struct work_struct asle_work; @@ -869,46 +867,6 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = { { } }; -static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv) -{ - struct intel_opregion *opregion = dev_priv->display.opregion; - const struct firmware *fw = NULL; - const char *name = dev_priv->display.params.vbt_firmware; - int ret; - - if (!name || !*name) - return -ENOENT; - - ret = request_firmware(&fw, name, dev_priv->drm.dev); - if (ret) { - drm_err(&dev_priv->drm, - "Requesting VBT firmware \"%s\" failed (%d)\n", - name, ret); - return ret; - } - - if (intel_bios_is_valid_vbt(dev_priv, fw->data, fw->size)) { - opregion->vbt_firmware = kmemdup(fw->data, fw->size, GFP_KERNEL); - if (opregion->vbt_firmware) { - drm_dbg_kms(&dev_priv->drm, - "Found valid VBT firmware \"%s\"\n", name); - opregion->vbt = opregion->vbt_firmware; - opregion->vbt_size = fw->size; - ret = 0; - } else { - ret = -ENOMEM; - } - } else { - drm_dbg_kms(&dev_priv->drm, "Invalid VBT firmware \"%s\"\n", - name); - ret = -EINVAL; - } - - release_firmware(fw); - - return ret; -} - int intel_opregion_setup(struct drm_i915_private *dev_priv) { struct intel_opregion *opregion; @@ -1006,9 +964,6 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv) drm_dbg(&dev_priv->drm, "Mailbox #2 for backlight present\n"); } - if (intel_load_vbt_firmware(dev_priv) == 0) - goto out; - if (dmi_check_system(intel_no_opregion_vbt)) goto out; @@ -1176,6 +1131,16 @@ const struct drm_edid *intel_opregion_get_edid(struct intel_connector *intel_con return drm_edid; } +bool intel_opregion_vbt_present(struct drm_i915_private *i915) +{ + struct intel_opregion *opregion = i915->display.opregion; + + if (!opregion || !opregion->vbt) + return false; + + return true; +} + const void *intel_opregion_get_vbt(struct drm_i915_private *i915, size_t *size) { struct intel_opregion *opregion = i915->display.opregion; @@ -1186,7 +1151,7 @@ const void *intel_opregion_get_vbt(struct drm_i915_private *i915, size_t *size) if (size) *size = opregion->vbt_size; - return opregion->vbt; + return kmemdup(opregion->vbt, opregion->vbt_size, GFP_KERNEL); } bool intel_opregion_headless_sku(struct drm_i915_private *i915) @@ -1312,7 +1277,6 @@ void intel_opregion_cleanup(struct drm_i915_private *i915) memunmap(opregion->header); if (opregion->rvda) memunmap(opregion->rvda); - kfree(opregion->vbt_firmware); kfree(opregion); i915->display.opregion = NULL; } diff --git a/drivers/gpu/drm/i915/display/intel_opregion.h b/drivers/gpu/drm/i915/display/intel_opregion.h index 0bec224f711f..4b2b8e752632 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.h +++ b/drivers/gpu/drm/i915/display/intel_opregion.h @@ -53,6 +53,7 @@ int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv, int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv); const struct drm_edid *intel_opregion_get_edid(struct intel_connector *connector); +bool intel_opregion_vbt_present(struct drm_i915_private *i915); const void *intel_opregion_get_vbt(struct drm_i915_private *i915, size_t *size); bool intel_opregion_headless_sku(struct drm_i915_private *i915); @@ -119,6 +120,11 @@ intel_opregion_get_edid(struct intel_connector *connector) return NULL; } +static inline bool intel_opregion_vbt_present(struct drm_i915_private *i915) +{ + return false; +} + static inline const void * intel_opregion_get_vbt(struct drm_i915_private *i915, size_t *size) { diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 2b1392d5a902..1c2099ed5514 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -972,10 +972,11 @@ static int check_overlay_dst(struct intel_overlay *overlay, rec->dst_width, rec->dst_height); clipped = req; - drm_rect_intersect(&clipped, &crtc_state->pipe_src); - if (!drm_rect_visible(&clipped) || - !drm_rect_equals(&clipped, &req)) + if (!drm_rect_intersect(&clipped, &crtc_state->pipe_src)) + return -EINVAL; + + if (!drm_rect_equals(&clipped, &req)) return -EINVAL; return 0; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 073ea3166c36..6f4ff6a89c32 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -47,10 +47,12 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915) { - if (i915->display.params.panel_use_ssc >= 0) - return i915->display.params.panel_use_ssc != 0; - return i915->display.vbt.lvds_use_ssc && - !intel_has_quirk(i915, QUIRK_LVDS_SSC_DISABLE); + struct intel_display *display = &i915->display; + + if (display->params.panel_use_ssc >= 0) + return display->params.panel_use_ssc != 0; + return display->vbt.lvds_use_ssc && + !intel_has_quirk(display, QUIRK_LVDS_SSC_DISABLE); } const struct drm_display_mode * diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index baf679759e00..826e38a9e6a4 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -474,7 +474,7 @@ static void ilk_pch_clock_get(struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); /* read out port_clock from the DPLL */ - i9xx_crtc_clock_get(crtc, crtc_state); + i9xx_crtc_clock_get(crtc_state); /* * In case there is an active pipe without active ports, @@ -529,7 +529,7 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) &crtc_state->dpll_hw_state); drm_WARN_ON(&dev_priv->drm, !pll_active); - tmp = crtc_state->dpll_hw_state.dpll; + tmp = crtc_state->dpll_hw_state.i9xx.dpll; crtc_state->pixel_multiplier = ((tmp & PLL_REF_SDVO_HDMI_MULTIPLIER_MASK) >> PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) + 1; diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.c b/drivers/gpu/drm/i915/display/intel_pmdemand.c index 744e332fa2af..9ca981b7a12c 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.c +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.c @@ -119,10 +119,11 @@ intel_pmdemand_update_phys_mask(struct drm_i915_private *i915, if (!encoder) return; - phy = intel_port_to_phy(i915, encoder->port); - if (intel_phy_is_tc(i915, phy)) + if (intel_encoder_is_tc(encoder)) return; + phy = intel_encoder_to_phy(encoder); + if (set_bit) pmdemand_state->active_combo_phys_mask |= BIT(phy); else @@ -222,14 +223,7 @@ static bool intel_pmdemand_encoder_has_tc_phy(struct drm_i915_private *i915, struct intel_encoder *encoder) { - enum phy phy; - - if (!encoder) - return false; - - phy = intel_port_to_phy(i915, encoder->port); - - return intel_phy_is_tc(i915, phy); + return encoder && intel_encoder_is_tc(encoder); } static bool diff --git a/drivers/gpu/drm/i915/display/intel_pmdemand.h b/drivers/gpu/drm/i915/display/intel_pmdemand.h index 2941a1a18b72..128fd61f8f14 100644 --- a/drivers/gpu/drm/i915/display/intel_pmdemand.h +++ b/drivers/gpu/drm/i915/display/intel_pmdemand.h @@ -43,9 +43,8 @@ struct intel_pmdemand_state { struct pmdemand_params params; }; -#define to_intel_pmdemand_state(x) container_of((x), \ - struct intel_pmdemand_state, \ - base) +#define to_intel_pmdemand_state(global_state) \ + container_of_const((global_state), struct intel_pmdemand_state, base) void intel_pmdemand_init_early(struct drm_i915_private *i915); int intel_pmdemand_init(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 2d65a538f83e..0ccbf9a85914 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -605,8 +605,7 @@ static void wait_panel_status(struct intel_dp *intel_dp, intel_de_read(dev_priv, pp_stat_reg), intel_de_read(dev_priv, pp_ctrl_reg)); - if (intel_de_wait_for_register(dev_priv, pp_stat_reg, - mask, value, 5000)) + if (intel_de_wait(dev_priv, pp_stat_reg, mask, value, 5000)) drm_err(&dev_priv->drm, "[ENCODER:%d:%s] %s panel status timeout: PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n", dig_port->base.base.base.id, dig_port->base.base.name, @@ -1351,7 +1350,7 @@ static void pps_init_delays_bios(struct intel_dp *intel_dp, static void pps_init_delays_vbt(struct intel_dp *intel_dp, struct edp_power_seq *vbt) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; *vbt = connector->panel.vbt.edp.pps; @@ -1364,9 +1363,9 @@ static void pps_init_delays_vbt(struct intel_dp *intel_dp, * just fails to power back on. Increasing the delay to 800ms * seems sufficient to avoid this problem. */ - if (intel_has_quirk(dev_priv, QUIRK_INCREASE_T12_DELAY)) { + if (intel_has_quirk(display, QUIRK_INCREASE_T12_DELAY)) { vbt->t11_t12 = max_t(u16, vbt->t11_t12, 1300 * 10); - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(display->drm, "Increasing T12 panel delay as per the quirk to %d\n", vbt->t11_t12); } @@ -1671,6 +1670,37 @@ void intel_pps_setup(struct drm_i915_private *i915) i915->display.pps.mmio_base = PPS_BASE; } +static int intel_pps_show(struct seq_file *m, void *data) +{ + struct intel_connector *connector = m->private; + struct intel_dp *intel_dp = intel_attached_dp(connector); + + if (connector->base.status != connector_status_connected) + return -ENODEV; + + seq_printf(m, "Panel power up delay: %d\n", + intel_dp->pps.panel_power_up_delay); + seq_printf(m, "Panel power down delay: %d\n", + intel_dp->pps.panel_power_down_delay); + seq_printf(m, "Backlight on delay: %d\n", + intel_dp->pps.backlight_on_delay); + seq_printf(m, "Backlight off delay: %d\n", + intel_dp->pps.backlight_off_delay); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(intel_pps); + +void intel_pps_connector_debugfs_add(struct intel_connector *connector) +{ + struct dentry *root = connector->base.debugfs_entry; + int connector_type = connector->base.connector_type; + + if (connector_type == DRM_MODE_CONNECTOR_eDP) + debugfs_create_file("i915_panel_timings", 0444, root, + connector, &intel_pps_fops); +} + void assert_pps_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) { i915_reg_t pp_reg; diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h index a2c2467e3c22..07ef96ca8da2 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.h +++ b/drivers/gpu/drm/i915/display/intel_pps.h @@ -51,6 +51,8 @@ void vlv_pps_init(struct intel_encoder *encoder, void intel_pps_unlock_regs_wa(struct drm_i915_private *i915); void intel_pps_setup(struct drm_i915_private *i915); +void intel_pps_connector_debugfs_add(struct intel_connector *connector); + void assert_pps_unlocked(struct drm_i915_private *i915, enum pipe pipe); #endif /* __INTEL_PPS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 6927785fd6ff..f5b33335a9ae 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -171,14 +171,27 @@ * * The rest of the bits are more self-explanatory and/or * irrelevant for normal operation. + * + * Description of intel_crtc_state variables. has_psr, has_panel_replay and + * has_sel_update: + * + * has_psr (alone): PSR1 + * has_psr + has_sel_update: PSR2 + * has_psr + has_panel_replay: Panel Replay + * has_psr + has_panel_replay + has_sel_update: Panel Replay Selective Update + * + * Description of some intel_psr varibles. enabled, panel_replay_enabled, + * sel_update_enabled + * + * enabled (alone): PSR1 + * enabled + sel_update_enabled: PSR2 + * enabled + panel_replay_enabled: Panel Replay + * enabled + panel_replay_enabled + sel_update_enabled: Panel Replay SU */ #define CAN_PSR(intel_dp) ((intel_dp)->psr.sink_support && \ (intel_dp)->psr.source_support) -#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support && \ - (intel_dp)->psr.source_panel_replay_support) - bool intel_encoder_can_psr(struct intel_encoder *encoder) { if (intel_encoder_is_dp(encoder) || encoder->type == INTEL_OUTPUT_DP_MST) @@ -330,6 +343,9 @@ static void psr_irq_control(struct intel_dp *intel_dp) enum transcoder cpu_transcoder = intel_dp->psr.transcoder; u32 mask; + if (intel_dp->psr.panel_replay_enabled) + return; + mask = psr_irq_psr_error_bit_get(intel_dp); if (intel_dp->psr.debug & I915_PSR_DEBUG_IRQ) mask |= psr_irq_post_exit_bit_get(intel_dp) | @@ -619,40 +635,59 @@ static bool psr2_su_region_et_valid(struct intel_dp *intel_dp) return false; } -static void intel_psr_enable_sink(struct intel_dp *intel_dp) +static unsigned int intel_psr_get_enable_sink_offset(struct intel_dp *intel_dp) +{ + return intel_dp->psr.panel_replay_enabled ? + PANEL_REPLAY_CONFIG : DP_PSR_EN_CFG; +} + +/* + * Note: Most of the bits are same in PANEL_REPLAY_CONFIG and DP_PSR_EN_CFG. We + * are relying on PSR definitions on these "common" bits. + */ +void intel_psr_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u8 dpcd_val = DP_PSR_ENABLE; - if (intel_dp->psr.panel_replay_enabled) - return; - - if (intel_dp->psr.psr2_enabled) { + if (crtc_state->has_psr2) { /* Enable ALPM at sink for psr2 */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, - DP_ALPM_ENABLE | - DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); + if (!crtc_state->has_panel_replay) { + drm_dp_dpcd_writeb(&intel_dp->aux, + DP_RECEIVER_ALPM_CONFIG, + DP_ALPM_ENABLE | + DP_ALPM_LOCK_ERROR_IRQ_HPD_ENABLE); + + if (psr2_su_region_et_valid(intel_dp)) + dpcd_val |= DP_PSR_ENABLE_SU_REGION_ET; + } dpcd_val |= DP_PSR_ENABLE_PSR2 | DP_PSR_IRQ_HPD_WITH_CRC_ERRORS; - if (psr2_su_region_et_valid(intel_dp)) - dpcd_val |= DP_PSR_ENABLE_SU_REGION_ET; } else { if (intel_dp->psr.link_standby) dpcd_val |= DP_PSR_MAIN_LINK_ACTIVE; - if (DISPLAY_VER(dev_priv) >= 8) + if (!crtc_state->has_panel_replay && DISPLAY_VER(dev_priv) >= 8) dpcd_val |= DP_PSR_CRC_VERIFICATION; } - if (intel_dp->psr.req_psr2_sdp_prior_scanline) + if (crtc_state->has_panel_replay) + dpcd_val |= DP_PANEL_REPLAY_UNRECOVERABLE_ERROR_EN | + DP_PANEL_REPLAY_RFB_STORAGE_ERROR_EN; + + if (crtc_state->req_psr2_sdp_prior_scanline) dpcd_val |= DP_PSR_SU_REGION_SCANLINE_CAPTURE; if (intel_dp->psr.entry_setup_frames > 0) dpcd_val |= DP_PSR_FRAME_CAPTURE; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, dpcd_val); + drm_dp_dpcd_writeb(&intel_dp->aux, + intel_psr_get_enable_sink_offset(intel_dp), + dpcd_val); - drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + if (intel_dp_is_edp(intel_dp)) + drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) @@ -1126,6 +1161,141 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d return true; } +/* + * See Bspec: 71632 for the table + * + * Silence_period = tSilence,Min + ((tSilence,Max - tSilence,Min) / 2) + * + * Half cycle duration: + * + * Link rates 1.62 - 4.32 and tLFPS_Cycle = 70 ns + * FLOOR( (Link Rate * tLFPS_Cycle) / (2 * 10) ) + * + * Link rates 5.4 - 8.1 + * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ] = 10 + * LFPS Period chosen is the mid-point of the min:max values from the table + * FLOOR( LFPS Period in Symbol clocks / + * (2 * PORT_ALPM_LFPS_CTL[ LFPS Cycle Count ]) ) + */ +static bool _lnl_get_silence_period_and_lfps_half_cycle(int link_rate, + int *silence_period, + int *lfps_half_cycle) +{ + switch (link_rate) { + case 162000: + *silence_period = 20; + *lfps_half_cycle = 5; + break; + case 216000: + *silence_period = 27; + *lfps_half_cycle = 7; + break; + case 243000: + *silence_period = 31; + *lfps_half_cycle = 8; + break; + case 270000: + *silence_period = 34; + *lfps_half_cycle = 9; + break; + case 324000: + *silence_period = 41; + *lfps_half_cycle = 11; + break; + case 432000: + *silence_period = 56; + *lfps_half_cycle = 15; + break; + case 540000: + *silence_period = 69; + *lfps_half_cycle = 12; + break; + case 648000: + *silence_period = 84; + *lfps_half_cycle = 15; + break; + case 675000: + *silence_period = 87; + *lfps_half_cycle = 15; + break; + case 810000: + *silence_period = 104; + *lfps_half_cycle = 19; + break; + default: + *silence_period = *lfps_half_cycle = -1; + return false; + } + return true; +} + +/* + * AUX-Less Wake Time = CEILING( ((PHY P2 to P0) + tLFPS_Period, Max+ + * tSilence, Max+ tPHY Establishment + tCDS) / tline) + * For the "PHY P2 to P0" latency see the PHY Power Control page + * (PHY P2 to P0) : https://gfxspecs.intel.com/Predator/Home/Index/68965 + * : 12 us + * The tLFPS_Period, Max term is 800ns + * The tSilence, Max term is 180ns + * The tPHY Establishment (a.k.a. t1) term is 50us + * The tCDS term is 1 or 2 times t2 + * t2 = Number ML_PHY_LOCK * tML_PHY_LOCK + * Number ML_PHY_LOCK = ( 7 + CEILING( 6.5us / tML_PHY_LOCK ) + 1) + * Rounding up the 6.5us padding to the next ML_PHY_LOCK boundary and + * adding the "+ 1" term ensures all ML_PHY_LOCK sequences that start + * within the CDS period complete within the CDS period regardless of + * entry into the period + * tML_PHY_LOCK = TPS4 Length * ( 10 / (Link Rate in MHz) ) + * TPS4 Length = 252 Symbols + */ +static int _lnl_compute_aux_less_wake_time(int port_clock) +{ + int tphy2_p2_to_p0 = 12 * 1000; + int tlfps_period_max = 800; + int tsilence_max = 180; + int t1 = 50 * 1000; + int tps4 = 252; + int tml_phy_lock = 1000 * 1000 * tps4 * 10 / port_clock; + int num_ml_phy_lock = 7 + DIV_ROUND_UP(6500, tml_phy_lock) + 1; + int t2 = num_ml_phy_lock * tml_phy_lock; + int tcds = 1 * t2; + + return DIV_ROUND_UP(tphy2_p2_to_p0 + tlfps_period_max + tsilence_max + + t1 + tcds, 1000); +} + +static int _lnl_compute_aux_less_alpm_params(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + int aux_less_wake_time, aux_less_wake_lines, silence_period, + lfps_half_cycle; + + aux_less_wake_time = + _lnl_compute_aux_less_wake_time(crtc_state->port_clock); + aux_less_wake_lines = intel_usecs_to_scanlines(&crtc_state->hw.adjusted_mode, + aux_less_wake_time); + + if (!_lnl_get_silence_period_and_lfps_half_cycle(crtc_state->port_clock, + &silence_period, + &lfps_half_cycle)) + return false; + + if (aux_less_wake_lines > ALPM_CTL_AUX_LESS_WAKE_TIME_MASK || + silence_period > PORT_ALPM_CTL_SILENCE_PERIOD_MASK || + lfps_half_cycle > PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK) + return false; + + if (i915->display.params.psr_safest_params) + aux_less_wake_lines = ALPM_CTL_AUX_LESS_WAKE_TIME_MASK; + + intel_dp->psr.alpm_parameters.fast_wake_lines = aux_less_wake_lines; + intel_dp->psr.alpm_parameters.silence_period_sym_clocks = silence_period; + intel_dp->psr.alpm_parameters.lfps_half_cycle_num_of_syms = lfps_half_cycle; + + return true; +} + static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -1142,6 +1312,9 @@ static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, if (check_entry_lines > 15) return false; + if (!_lnl_compute_aux_less_alpm_params(intel_dp, crtc_state)) + return false; + if (i915->display.params.psr_safest_params) check_entry_lines = 15; @@ -1150,28 +1323,52 @@ static bool _lnl_compute_alpm_params(struct intel_dp *intel_dp, return true; } +/* + * IO wake time for DISPLAY_VER < 12 is not directly mentioned in Bspec. There + * are 50 us io wake time and 32 us fast wake time. Clearly preharge pulses are + * not (improperly) included in 32 us fast wake time. 50 us - 32 us = 18 us. + */ +static int skl_io_buffer_wake_time(void) +{ + return 18; +} + +static int tgl_io_buffer_wake_time(void) +{ + return 10; +} + +static int io_buffer_wake_time(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + + if (DISPLAY_VER(i915) >= 12) + return tgl_io_buffer_wake_time(); + else + return skl_io_buffer_wake_time(); +} + static bool _compute_alpm_params(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = dp_to_i915(intel_dp); int io_wake_lines, io_wake_time, fast_wake_lines, fast_wake_time; + int tfw_exit_latency = 20; /* eDP spec */ + int phy_wake = 4; /* eDP spec */ + int preamble = 8; /* eDP spec */ + int precharge = intel_dp_aux_fw_sync_len() - preamble; u8 max_wake_lines; - if (DISPLAY_VER(i915) >= 12) { - io_wake_time = 42; - /* - * According to Bspec it's 42us, but based on testing - * it is not enough -> use 45 us. - */ - fast_wake_time = 45; + io_wake_time = max(precharge, io_buffer_wake_time(crtc_state)) + + preamble + phy_wake + tfw_exit_latency; + fast_wake_time = precharge + preamble + phy_wake + + tfw_exit_latency; + if (DISPLAY_VER(i915) >= 12) /* TODO: Check how we can use ALPM_CTL fast wake extended field */ max_wake_lines = 12; - } else { - io_wake_time = 50; - fast_wake_time = 32; + else max_wake_lines = 8; - } io_wake_lines = intel_usecs_to_scanlines( &crtc_state->hw.adjusted_mode, io_wake_time); @@ -1422,12 +1619,24 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, return; } + /* + * FIXME figure out what is wrong with PSR+bigjoiner and + * fix it. Presumably something related to the fact that + * PSR is a transcoder level feature. + */ + if (crtc_state->bigjoiner_pipes) { + drm_dbg_kms(&dev_priv->drm, + "PSR disabled due to bigjoiner\n"); + return; + } + if (CAN_PANEL_REPLAY(intel_dp)) crtc_state->has_panel_replay = true; - else - crtc_state->has_psr = _psr_compute_config(intel_dp, crtc_state); - if (!(crtc_state->has_panel_replay || crtc_state->has_psr)) + crtc_state->has_psr = crtc_state->has_panel_replay ? true : + _psr_compute_config(intel_dp, crtc_state); + + if (!crtc_state->has_psr) return; crtc_state->has_psr2 = intel_psr2_config_valid(intel_dp, crtc_state); @@ -1454,7 +1663,7 @@ void intel_psr_get_config(struct intel_encoder *encoder, goto unlock; if (intel_dp->psr.panel_replay_enabled) { - pipe_config->has_panel_replay = true; + pipe_config->has_psr = pipe_config->has_panel_replay = true; } else { /* * Not possible to read EDP_PSR/PSR2_CTL registers as it is @@ -1559,14 +1768,44 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; struct intel_psr *psr = &intel_dp->psr; + u32 alpm_ctl; - if (DISPLAY_VER(dev_priv) < 20) + if (DISPLAY_VER(dev_priv) < 20 || (!intel_dp->psr.psr2_enabled && + !intel_dp_is_edp(intel_dp))) return; - intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), - ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | - ALPM_CTL_ALPM_ENTRY_CHECK(psr->alpm_parameters.check_entry_lines) | - ALPM_CTL_EXTENDED_FAST_WAKE_TIME(psr->alpm_parameters.fast_wake_lines)); + /* + * Panel Replay on eDP is always using ALPM aux less. I.e. no need to + * check panel support at this point. + */ + if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) { + alpm_ctl = ALPM_CTL_ALPM_ENABLE | + ALPM_CTL_ALPM_AUX_LESS_ENABLE | + ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS; + + intel_de_write(dev_priv, PORT_ALPM_CTL(cpu_transcoder), + PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE | + PORT_ALPM_CTL_MAX_PHY_SWING_SETUP(15) | + PORT_ALPM_CTL_MAX_PHY_SWING_HOLD(0) | + PORT_ALPM_CTL_SILENCE_PERIOD( + psr->alpm_parameters.silence_period_sym_clocks)); + + intel_de_write(dev_priv, PORT_ALPM_LFPS_CTL(cpu_transcoder), + PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(10) | + PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION( + psr->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION( + psr->alpm_parameters.lfps_half_cycle_num_of_syms) | + PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION( + psr->alpm_parameters.lfps_half_cycle_num_of_syms)); + } else { + alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | + ALPM_CTL_EXTENDED_FAST_WAKE_TIME(psr->alpm_parameters.fast_wake_lines); + } + + alpm_ctl |= ALPM_CTL_ALPM_ENTRY_CHECK(psr->alpm_parameters.check_entry_lines); + + intel_de_write(dev_priv, ALPM_CTL(cpu_transcoder), alpm_ctl); } static void intel_psr_enable_source(struct intel_dp *intel_dp, @@ -1574,7 +1813,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; - u32 mask; + u32 mask = 0; /* * Only HSW and BDW have PSR AUX registers that need to be setup. @@ -1588,34 +1827,46 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, * mask LPSP to avoid dependency on other drivers that might block * runtime_pm besides preventing other hw tracking issues now we * can rely on frontbuffer tracking. + * + * From bspec prior LunarLake: + * Only PSR_MASK[Mask FBC modify] and PSR_MASK[Mask Hotplug] are used in + * panel replay mode. + * + * From bspec beyod LunarLake: + * Panel Replay on DP: No bits are applicable + * Panel Replay on eDP: All bits are applicable */ - mask = EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD; + if (DISPLAY_VER(dev_priv) < 20 || intel_dp_is_edp(intel_dp)) + mask = EDP_PSR_DEBUG_MASK_HPD; - /* - * For some unknown reason on HSW non-ULT (or at least on - * Dell Latitude E6540) external displays start to flicker - * when PSR is enabled on the eDP. SR/PC6 residency is much - * higher than should be possible with an external display. - * As a workaround leave LPSP unmasked to prevent PSR entry - * when external displays are active. - */ - if (DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL_ULT(dev_priv)) - mask |= EDP_PSR_DEBUG_MASK_LPSP; + if (intel_dp_is_edp(intel_dp)) { + mask |= EDP_PSR_DEBUG_MASK_MEMUP; - if (DISPLAY_VER(dev_priv) < 20) - mask |= EDP_PSR_DEBUG_MASK_MAX_SLEEP; + /* + * For some unknown reason on HSW non-ULT (or at least on + * Dell Latitude E6540) external displays start to flicker + * when PSR is enabled on the eDP. SR/PC6 residency is much + * higher than should be possible with an external display. + * As a workaround leave LPSP unmasked to prevent PSR entry + * when external displays are active. + */ + if (DISPLAY_VER(dev_priv) >= 8 || IS_HASWELL_ULT(dev_priv)) + mask |= EDP_PSR_DEBUG_MASK_LPSP; - /* - * No separate pipe reg write mask on hsw/bdw, so have to unmask all - * registers in order to keep the CURSURFLIVE tricks working :( - */ - if (IS_DISPLAY_VER(dev_priv, 9, 10)) - mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE; + if (DISPLAY_VER(dev_priv) < 20) + mask |= EDP_PSR_DEBUG_MASK_MAX_SLEEP; - /* allow PSR with sprite enabled */ - if (IS_HASWELL(dev_priv)) - mask |= EDP_PSR_DEBUG_MASK_SPRITE_ENABLE; + /* + * No separate pipe reg write mask on hsw/bdw, so have to unmask all + * registers in order to keep the CURSURFLIVE tricks working :( + */ + if (IS_DISPLAY_VER(dev_priv, 9, 10)) + mask |= EDP_PSR_DEBUG_MASK_DISP_REG_WRITE; + + /* allow PSR with sprite enabled */ + if (IS_HASWELL(dev_priv)) + mask |= EDP_PSR_DEBUG_MASK_SPRITE_ENABLE; + } intel_de_write(dev_priv, psr_debug_reg(dev_priv, cpu_transcoder), mask); @@ -1634,7 +1885,8 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, intel_dp->psr.psr2_sel_fetch_enabled ? IGNORE_PSR2_HW_TRACKING : 0); - lnl_alpm_configure(intel_dp); + if (intel_dp_is_edp(intel_dp)) + lnl_alpm_configure(intel_dp); /* * Wa_16013835468 @@ -1675,6 +1927,9 @@ static bool psr_interrupt_error_check(struct intel_dp *intel_dp) enum transcoder cpu_transcoder = intel_dp->psr.transcoder; u32 val; + if (intel_dp->psr.panel_replay_enabled) + goto no_err; + /* * If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR * will still keep the error set even after the reset done in the @@ -1692,6 +1947,7 @@ static bool psr_interrupt_error_check(struct intel_dp *intel_dp) return false; } +no_err: return true; } @@ -1700,7 +1956,6 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); u32 val; drm_WARN_ON(&dev_priv->drm, intel_dp->psr.enabled); @@ -1722,14 +1977,22 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, if (!psr_interrupt_error_check(intel_dp)) return; - if (intel_dp->psr.panel_replay_enabled) + if (intel_dp->psr.panel_replay_enabled) { drm_dbg_kms(&dev_priv->drm, "Enabling Panel Replay\n"); - else + } else { drm_dbg_kms(&dev_priv->drm, "Enabling PSR%s\n", intel_dp->psr.psr2_enabled ? "2" : "1"); - intel_snps_phy_update_psr_power_state(dev_priv, phy, true); - intel_psr_enable_sink(intel_dp); + /* + * Panel replay has to be enabled before link training: doing it + * only for PSR here. + */ + intel_psr_enable_sink(intel_dp, crtc_state); + } + + if (intel_dp_is_edp(intel_dp)) + intel_snps_phy_update_psr_power_state(&dig_port->base, true); + intel_psr_enable_source(intel_dp, crtc_state); intel_dp->psr.enabled = true; intel_dp->psr.paused = false; @@ -1799,8 +2062,6 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); enum transcoder cpu_transcoder = intel_dp->psr.transcoder; - enum phy phy = intel_port_to_phy(dev_priv, - dp_to_dig_port(intel_dp)->base.port); lockdep_assert_held(&intel_dp->psr.lock); @@ -1835,12 +2096,25 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) CLKGATE_DIS_MISC_DMASC_GATING_DIS, 0); } - intel_snps_phy_update_psr_power_state(dev_priv, phy, false); + if (intel_dp_is_edp(intel_dp)) + intel_snps_phy_update_psr_power_state(&dp_to_dig_port(intel_dp)->base, false); + + /* Panel Replay on eDP is always using ALPM aux less. */ + if (intel_dp->psr.panel_replay_enabled && intel_dp_is_edp(intel_dp)) { + intel_de_rmw(dev_priv, ALPM_CTL(cpu_transcoder), + ALPM_CTL_ALPM_ENABLE | + ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); + + intel_de_rmw(dev_priv, PORT_ALPM_CTL(cpu_transcoder), + PORT_ALPM_CTL_ALPM_AUX_LESS_ENABLE, 0); + } /* Disable PSR on Sink */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); + drm_dp_dpcd_writeb(&intel_dp->aux, + intel_psr_get_enable_sink_offset(intel_dp), 0); - if (intel_dp->psr.psr2_enabled) + if (!intel_dp->psr.panel_replay_enabled && + intel_dp->psr.psr2_enabled) drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, 0); intel_dp->psr.enabled = false; @@ -1888,7 +2162,7 @@ void intel_psr_pause(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct intel_psr *psr = &intel_dp->psr; - if (!CAN_PSR(intel_dp)) + if (!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp)) return; mutex_lock(&psr->lock); @@ -1921,7 +2195,7 @@ void intel_psr_resume(struct intel_dp *intel_dp) { struct intel_psr *psr = &intel_dp->psr; - if (!CAN_PSR(intel_dp)) + if (!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp)) return; mutex_lock(&psr->lock); @@ -1994,6 +2268,7 @@ static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; struct intel_encoder *encoder; @@ -2013,6 +2288,12 @@ void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_st intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(cpu_transcoder), crtc_state->psr2_man_track_ctl); + + if (!crtc_state->enable_psr2_su_region_et) + return; + + intel_de_write(dev_priv, PIPE_SRCSZ_ERLY_TPT(crtc->pipe), + crtc_state->pipe_srcsz_early_tpt); } static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, @@ -2051,6 +2332,25 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, crtc_state->psr2_man_track_ctl = val; } +static u32 +psr2_pipe_srcsz_early_tpt_calc(struct intel_crtc_state *crtc_state, + bool full_update, bool cursor_in_su_area) +{ + int width, height; + + if (!crtc_state->enable_psr2_su_region_et || full_update) + return 0; + + if (!cursor_in_su_area) + return PIPESRC_WIDTH(0) | + PIPESRC_HEIGHT(drm_rect_height(&crtc_state->pipe_src)); + + width = drm_rect_width(&crtc_state->psr2_su_area); + height = drm_rect_height(&crtc_state->psr2_su_area); + + return PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1); +} + static void clip_area_update(struct drm_rect *overlap_damage_area, struct drm_rect *damage_area, struct drm_rect *pipe_src) @@ -2095,21 +2395,38 @@ static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st * cursor fully when cursor is in SU area. */ static void -intel_psr2_sel_fetch_et_alignment(struct intel_crtc_state *crtc_state, - struct intel_plane_state *cursor_state) +intel_psr2_sel_fetch_et_alignment(struct intel_atomic_state *state, + struct intel_crtc *crtc, + bool *cursor_in_su_area) { - struct drm_rect inter; + struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + int i; - if (!crtc_state->enable_psr2_su_region_et || - !cursor_state->uapi.visible) + if (!crtc_state->enable_psr2_su_region_et) return; - inter = crtc_state->psr2_su_area; - if (!drm_rect_intersect(&inter, &cursor_state->uapi.dst)) - return; + for_each_new_intel_plane_in_state(state, plane, new_plane_state, i) { + struct drm_rect inter; - clip_area_update(&crtc_state->psr2_su_area, &cursor_state->uapi.dst, - &crtc_state->pipe_src); + if (new_plane_state->uapi.crtc != crtc_state->uapi.crtc) + continue; + + if (plane->id != PLANE_CURSOR) + continue; + + if (!new_plane_state->uapi.visible) + continue; + + inter = crtc_state->psr2_su_area; + if (!drm_rect_intersect(&inter, &new_plane_state->uapi.dst)) + continue; + + clip_area_update(&crtc_state->psr2_su_area, &new_plane_state->uapi.dst, + &crtc_state->pipe_src); + *cursor_in_su_area = true; + } } /* @@ -2152,10 +2469,9 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct intel_plane_state *new_plane_state, *old_plane_state, - *cursor_plane_state = NULL; + struct intel_plane_state *new_plane_state, *old_plane_state; struct intel_plane *plane; - bool full_update = false; + bool full_update = false, cursor_in_su_area = false; int i, ret; if (!crtc_state->enable_psr2_sel_fetch) @@ -2238,13 +2554,6 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, damaged_area.x2 += new_plane_state->uapi.dst.x1 - src.x1; clip_area_update(&crtc_state->psr2_su_area, &damaged_area, &crtc_state->pipe_src); - - /* - * Cursor plane new state is stored to adjust su area to cover - * cursor are fully. - */ - if (plane->id == PLANE_CURSOR) - cursor_plane_state = new_plane_state; } /* @@ -2273,9 +2582,13 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, if (ret) return ret; - /* Adjust su area to cover cursor fully as necessary */ - if (cursor_plane_state) - intel_psr2_sel_fetch_et_alignment(crtc_state, cursor_plane_state); + /* + * Adjust su area to cover cursor fully as necessary (early + * transport). This needs to be done after + * drm_atomic_add_affected_planes to ensure visible cursor is added into + * affected planes even when cursor is not updated by itself. + */ + intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); intel_psr2_sel_fetch_pipe_alignment(crtc_state); @@ -2338,6 +2651,9 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, skip_sel_fetch_set_loop: psr2_man_trk_ctl_calc(crtc_state, full_update); + crtc_state->pipe_srcsz_early_tpt = + psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update, + cursor_in_su_area); return 0; } @@ -2394,7 +2710,7 @@ void intel_psr_post_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); struct intel_encoder *encoder; - if (!(crtc_state->has_psr || crtc_state->has_panel_replay)) + if (!crtc_state->has_psr) return; for_each_intel_encoder_mask_with_psr(state->base.dev, encoder, @@ -2994,6 +3310,13 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) } } +/* + * On common bits: + * DP_PSR_RFB_STORAGE_ERROR == DP_PANEL_REPLAY_RFB_STORAGE_ERROR + * DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR == DP_PANEL_REPLAY_VSC_SDP_UNCORRECTABLE_ERROR + * DP_PSR_LINK_CRC_ERROR == DP_PANEL_REPLAY_LINK_CRC_ERROR + * this function is relying on PSR definitions + */ void intel_psr_short_pulse(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -3003,7 +3326,7 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) DP_PSR_VSC_SDP_UNCORRECTABLE_ERROR | DP_PSR_LINK_CRC_ERROR; - if (!CAN_PSR(intel_dp)) + if (!CAN_PSR(intel_dp) && !CAN_PANEL_REPLAY(intel_dp)) return; mutex_lock(&psr->lock); @@ -3017,12 +3340,14 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) goto exit; } - if (status == DP_PSR_SINK_INTERNAL_ERROR || (error_status & errors)) { + if ((!psr->panel_replay_enabled && status == DP_PSR_SINK_INTERNAL_ERROR) || + (error_status & errors)) { intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; } - if (status == DP_PSR_SINK_INTERNAL_ERROR && !error_status) + if (!psr->panel_replay_enabled && status == DP_PSR_SINK_INTERNAL_ERROR && + !error_status) drm_dbg_kms(&dev_priv->drm, "PSR sink internal error, disabling PSR\n"); if (error_status & DP_PSR_RFB_STORAGE_ERROR) @@ -3042,8 +3367,10 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) /* clear status register */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ERROR_STATUS, error_status); - psr_alpm_check(intel_dp); - psr_capability_changed_check(intel_dp); + if (!psr->panel_replay_enabled) { + psr_alpm_check(intel_dp); + psr_capability_changed_check(intel_dp); + } exit: mutex_unlock(&psr->lock); diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index cde781df84d5..d483c85870e1 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -21,8 +21,13 @@ struct intel_encoder; struct intel_plane; struct intel_plane_state; +#define CAN_PANEL_REPLAY(intel_dp) ((intel_dp)->psr.sink_panel_replay_support && \ + (intel_dp)->psr.source_panel_replay_support) + bool intel_encoder_can_psr(struct intel_encoder *encoder); void intel_psr_init_dpcd(struct intel_dp *intel_dp); +void intel_psr_enable_sink(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_psr_pre_plane_update(struct intel_atomic_state *state, struct intel_crtc *crtc); void intel_psr_post_plane_update(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 8427a736f639..b004672d1deb 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -348,9 +348,13 @@ #define PORT_ALPM_LFPS_CTL(tran) _MMIO_TRANS2(tran, _PORT_ALPM_LFPS_CTL_A) #define PORT_ALPM_LFPS_CTL_LFPS_START_POLARITY REG_BIT(31) #define PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MASK REG_GENMASK(27, 24) -#define ALPM_CTL_EXTENDED_FAST_WAKE_MIN_LINES 5 -#define ALPM_CTL_EXTENDED_FAST_WAKE_TIME(lines) REG_FIELD_PREP(ALPM_CTL_EXTENDED_FAST_WAKE_TIME_MASK, (lines) - ALPM_CTL_EXTENDED_FAST_WAKE_MIN_LINES) -#define ALPM_CTL_AUX_LESS_WAKE_TIME_MASK REG_GENMASK(5, 0) -#define ALPM_CTL_AUX_LESS_WAKE_TIME(val) REG_FIELD_PREP(ALPM_CTL_AUX_LESS_WAKE_TIME_MASK, val) +#define PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MIN 7 +#define PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MASK, (val) - PORT_ALPM_LFPS_CTL_LFPS_CYCLE_COUNT_MIN) +#define PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(20, 16) +#define PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) +#define PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(12, 8) +#define PORT_ALPM_LFPS_CTL_FIRST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) +#define PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION_MASK REG_GENMASK(4, 0) +#define PORT_ALPM_LFPS_CTL_LAST_LFPS_HALF_CYCLE_DURATION(val) REG_FIELD_PREP(PORT_ALPM_LFPS_CTL_LFPS_HALF_CYCLE_DURATION_MASK, val) #endif /* __INTEL_PSR_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index a280448df771..14d5fefc9c5b 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -9,72 +9,72 @@ #include "intel_display_types.h" #include "intel_quirks.h" -static void intel_set_quirk(struct drm_i915_private *i915, enum intel_quirk_id quirk) +static void intel_set_quirk(struct intel_display *display, enum intel_quirk_id quirk) { - i915->display.quirks.mask |= BIT(quirk); + display->quirks.mask |= BIT(quirk); } /* * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason */ -static void quirk_ssc_force_disable(struct drm_i915_private *i915) +static void quirk_ssc_force_disable(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_LVDS_SSC_DISABLE); - drm_info(&i915->drm, "applying lvds SSC disable quirk\n"); + intel_set_quirk(display, QUIRK_LVDS_SSC_DISABLE); + drm_info(display->drm, "applying lvds SSC disable quirk\n"); } /* * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight * brightness value */ -static void quirk_invert_brightness(struct drm_i915_private *i915) +static void quirk_invert_brightness(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_INVERT_BRIGHTNESS); - drm_info(&i915->drm, "applying inverted panel brightness quirk\n"); + intel_set_quirk(display, QUIRK_INVERT_BRIGHTNESS); + drm_info(display->drm, "applying inverted panel brightness quirk\n"); } /* Some VBT's incorrectly indicate no backlight is present */ -static void quirk_backlight_present(struct drm_i915_private *i915) +static void quirk_backlight_present(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_BACKLIGHT_PRESENT); - drm_info(&i915->drm, "applying backlight present quirk\n"); + intel_set_quirk(display, QUIRK_BACKLIGHT_PRESENT); + drm_info(display->drm, "applying backlight present quirk\n"); } /* Toshiba Satellite P50-C-18C requires T12 delay to be min 800ms * which is 300 ms greater than eDP spec T12 min. */ -static void quirk_increase_t12_delay(struct drm_i915_private *i915) +static void quirk_increase_t12_delay(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_INCREASE_T12_DELAY); - drm_info(&i915->drm, "Applying T12 delay quirk\n"); + intel_set_quirk(display, QUIRK_INCREASE_T12_DELAY); + drm_info(display->drm, "Applying T12 delay quirk\n"); } /* * GeminiLake NUC HDMI outputs require additional off time * this allows the onboard retimer to correctly sync to signal */ -static void quirk_increase_ddi_disabled_time(struct drm_i915_private *i915) +static void quirk_increase_ddi_disabled_time(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_INCREASE_DDI_DISABLED_TIME); - drm_info(&i915->drm, "Applying Increase DDI Disabled quirk\n"); + intel_set_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME); + drm_info(display->drm, "Applying Increase DDI Disabled quirk\n"); } -static void quirk_no_pps_backlight_power_hook(struct drm_i915_private *i915) +static void quirk_no_pps_backlight_power_hook(struct intel_display *display) { - intel_set_quirk(i915, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK); - drm_info(&i915->drm, "Applying no pps backlight power quirk\n"); + intel_set_quirk(display, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK); + drm_info(display->drm, "Applying no pps backlight power quirk\n"); } struct intel_quirk { int device; int subsystem_vendor; int subsystem_device; - void (*hook)(struct drm_i915_private *i915); + void (*hook)(struct intel_display *display); }; /* For systems that don't have a meaningful PCI subdevice/subvendor ID */ struct intel_dmi_quirk { - void (*hook)(struct drm_i915_private *i915); + void (*hook)(struct intel_display *display); const struct dmi_system_id (*dmi_id_list)[]; }; @@ -203,9 +203,9 @@ static struct intel_quirk intel_quirks[] = { { 0x0f31, 0x103c, 0x220f, quirk_invert_brightness }, }; -void intel_init_quirks(struct drm_i915_private *i915) +void intel_init_quirks(struct intel_display *display) { - struct pci_dev *d = to_pci_dev(i915->drm.dev); + struct pci_dev *d = to_pci_dev(display->drm->dev); int i; for (i = 0; i < ARRAY_SIZE(intel_quirks); i++) { @@ -216,15 +216,15 @@ void intel_init_quirks(struct drm_i915_private *i915) q->subsystem_vendor == PCI_ANY_ID) && (d->subsystem_device == q->subsystem_device || q->subsystem_device == PCI_ANY_ID)) - q->hook(i915); + q->hook(display); } for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) - intel_dmi_quirks[i].hook(i915); + intel_dmi_quirks[i].hook(display); } } -bool intel_has_quirk(struct drm_i915_private *i915, enum intel_quirk_id quirk) +bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk) { - return i915->display.quirks.mask & BIT(quirk); + return display->quirks.mask & BIT(quirk); } diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h index 10a4d163149f..151c8f4ae576 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.h +++ b/drivers/gpu/drm/i915/display/intel_quirks.h @@ -8,7 +8,7 @@ #include -struct drm_i915_private; +struct intel_display; enum intel_quirk_id { QUIRK_BACKLIGHT_PRESENT, @@ -19,7 +19,7 @@ enum intel_quirk_id { QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK, }; -void intel_init_quirks(struct drm_i915_private *i915); -bool intel_has_quirk(struct drm_i915_private *i915, enum intel_quirk_id quirk); +void intel_init_quirks(struct intel_display *display); +bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk); #endif /* __INTEL_QUIRKS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 0cd9c183f621..d0d712405129 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -193,7 +193,7 @@ to_intel_sdvo_connector(struct drm_connector *connector) } #define to_intel_sdvo_connector_state(conn_state) \ - container_of((conn_state), struct intel_sdvo_connector_state, base.base) + container_of_const((conn_state), struct intel_sdvo_connector_state, base.base) static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo); @@ -1944,7 +1944,7 @@ intel_sdvo_mode_valid(struct drm_connector *connector, struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); bool has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo_connector, connector->state); - int max_dotclk = i915->max_dotclk_freq; + int max_dotclk = i915->display.cdclk.max_dotclk_freq; enum drm_mode_status status; int clock = mode->clock; @@ -1952,9 +1952,6 @@ intel_sdvo_mode_valid(struct drm_connector *connector, if (status != MODE_OK) return status; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if (clock > max_dotclk) return MODE_CLOCK_HIGH; @@ -2378,7 +2375,7 @@ intel_sdvo_connector_atomic_get_property(struct drm_connector *connector, u64 *val) { struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector); - const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state((void *)state); + const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(state); if (property == intel_sdvo_connector->tv_format) { int i; diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index bc61e736f9b3..e6df1f92def5 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -44,12 +44,14 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) } } -void intel_snps_phy_update_psr_power_state(struct drm_i915_private *i915, - enum phy phy, bool enable) +void intel_snps_phy_update_psr_power_state(struct intel_encoder *encoder, + bool enable) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + enum phy phy = intel_encoder_to_phy(encoder); u32 val; - if (!intel_phy_is_snps(i915, phy)) + if (!intel_encoder_is_snps(encoder)) return; val = REG_FIELD_PREP(SNPS_PHY_TX_REQ_LN_DIS_PWR_STATE_PSR, @@ -63,7 +65,7 @@ void intel_snps_phy_set_signal_levels(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct intel_ddi_buf_trans *trans; - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); int n_entries, ln; trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); @@ -1809,7 +1811,7 @@ int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state, for (i = 0; tables[i]; i++) { if (crtc_state->port_clock == tables[i]->clock) { - crtc_state->mpllb_state = *tables[i]; + crtc_state->dpll_hw_state.mpllb = *tables[i]; return 0; } } @@ -1821,8 +1823,8 @@ void intel_mpllb_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - const struct intel_mpllb_state *pll_state = &crtc_state->mpllb_state; - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + const struct intel_mpllb_state *pll_state = &crtc_state->dpll_hw_state.mpllb; + enum phy phy = intel_encoder_to_phy(encoder); i915_reg_t enable_reg = (phy <= PHY_D ? DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0)); @@ -1879,7 +1881,7 @@ void intel_mpllb_enable(struct intel_encoder *encoder, void intel_mpllb_disable(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(i915, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); i915_reg_t enable_reg = (phy <= PHY_D ? DG2_PLL_ENABLE(phy) : MG_PLL_ENABLE(0)); @@ -1951,7 +1953,7 @@ void intel_mpllb_readout_hw_state(struct intel_encoder *encoder, struct intel_mpllb_state *pll_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + enum phy phy = intel_encoder_to_phy(encoder); pll_state->mpllb_cp = intel_de_read(dev_priv, SNPS_PHY_MPLLB_CP(phy)); pll_state->mpllb_div = intel_de_read(dev_priv, SNPS_PHY_MPLLB_DIV(phy)); @@ -1999,7 +2001,7 @@ void intel_mpllb_state_verify(struct intel_atomic_state *state, const struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_mpllb_state mpllb_hw_state = {}; - const struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->mpllb_state; + const struct intel_mpllb_state *mpllb_sw_state = &new_crtc_state->dpll_hw_state.mpllb; struct intel_encoder *encoder; if (!IS_DG2(i915)) diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.h b/drivers/gpu/drm/i915/display/intel_snps_phy.h index 515abf7c5902..bc08b92a7cd9 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.h +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.h @@ -17,8 +17,8 @@ struct intel_mpllb_state; enum phy; void intel_snps_phy_wait_for_calibration(struct drm_i915_private *dev_priv); -void intel_snps_phy_update_psr_power_state(struct drm_i915_private *dev_priv, - enum phy phy, bool enable); +void intel_snps_phy_update_psr_power_state(struct intel_encoder *encoder, + bool enable); int intel_mpllb_calc_state(struct intel_crtc_state *crtc_state, struct intel_encoder *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 6b374d481cd9..9887967b2ca5 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -100,11 +100,9 @@ static struct drm_i915_private *tc_to_i915(struct intel_tc_port *tc) static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port, enum tc_port_mode mode) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); struct intel_tc_port *tc = to_tc_port(dig_port); - return intel_phy_is_tc(i915, phy) && tc->mode == mode; + return intel_encoder_is_tc(&dig_port->base) && tc->mode == mode; } bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port) @@ -124,11 +122,9 @@ bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port) bool intel_tc_port_handles_hpd_glitches(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); struct intel_tc_port *tc = to_tc_port(dig_port); - return intel_phy_is_tc(i915, phy) && !tc->legacy_port; + return intel_encoder_is_tc(&dig_port->base) && !tc->legacy_port; } /* @@ -254,8 +250,7 @@ assert_tc_cold_blocked(struct intel_tc_port *tc) static enum intel_display_power_domain tc_port_power_domain(struct intel_tc_port *tc) { - struct drm_i915_private *i915 = tc_to_i915(tc); - enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); + enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; } @@ -302,7 +297,7 @@ u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port) static int lnl_tc_port_get_max_lane_count(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); + enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); intel_wakeref_t wakeref; u32 val, pin_assignment; @@ -375,9 +370,8 @@ int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_tc_port *tc = to_tc_port(dig_port); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); - if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT) + if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) return 4; assert_tc_cold_blocked(tc); @@ -458,9 +452,7 @@ static void tc_port_fixup_legacy_flag(struct intel_tc_port *tc, static void tc_phy_load_fia_params(struct intel_tc_port *tc, bool modular_fia) { - struct drm_i915_private *i915 = tc_to_i915(tc); - enum port port = tc->dig_port->base.port; - enum tc_port tc_port = intel_port_to_tc(i915, port); + enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); /* * Each Modular FIA instance houses 2 TC ports. In SOC that has more @@ -812,7 +804,7 @@ static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc) static bool adlp_tc_phy_is_ready(struct intel_tc_port *tc) { struct drm_i915_private *i915 = tc_to_i915(tc); - enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); + enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); u32 val; assert_display_core_power_enabled(tc); @@ -1635,10 +1627,7 @@ static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc) bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); - - if (!intel_phy_is_tc(i915, phy)) + if (!intel_encoder_is_tc(&dig_port->base)) return false; return __intel_tc_port_link_needs_reset(to_tc_port(dig_port)); @@ -1740,11 +1729,9 @@ bool intel_tc_port_link_reset(struct intel_digital_port *dig_port) void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); struct intel_tc_port *tc = to_tc_port(dig_port); - if (!intel_phy_is_tc(i915, phy)) + if (!intel_encoder_is_tc(&dig_port->base)) return; cancel_delayed_work(&tc->link_reset_work); @@ -1861,7 +1848,7 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct intel_tc_port *tc; enum port port = dig_port->base.port; - enum tc_port tc_port = intel_port_to_tc(i915, port); + enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) return -EINVAL; diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 2b77d399f1a1..9df0f1263913 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -885,7 +885,8 @@ struct intel_tv_connector_state { bool bypass_vfilter; }; -#define to_intel_tv_connector_state(x) container_of(x, struct intel_tv_connector_state, base) +#define to_intel_tv_connector_state(conn_state) \ + container_of_const((conn_state), struct intel_tv_connector_state, base) static struct drm_connector_state * intel_tv_connector_duplicate_state(struct drm_connector *connector) @@ -961,16 +962,13 @@ intel_tv_mode_valid(struct drm_connector *connector, { struct drm_i915_private *i915 = to_i915(connector->dev); const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state); - int max_dotclk = i915->max_dotclk_freq; + int max_dotclk = i915->display.cdclk.max_dotclk_freq; enum drm_mode_status status; status = intel_cpu_transcoder_mode_valid(i915, mode); if (status != MODE_OK) return status; - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) - return MODE_NO_DBLESCAN; - if (mode->clock > max_dotclk) return MODE_CLOCK_HIGH; diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index a9f44abfc9fc..3815aa21d19f 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -485,6 +485,7 @@ struct child_device_config { u8 hdmi_iboost_level:4; /* 196+ */ u8 dp_max_link_rate:3; /* 216+ */ u8 dp_max_link_rate_reserved:5; /* 216+ */ + u8 efp_index; /* 256+ */ } __packed; struct bdb_general_definitions { @@ -602,22 +603,22 @@ struct bdb_driver_features { u8 custom_vbt_version; /* 155+ */ /* Driver Feature Flags */ - u16 rmpm_enabled:1; /* 165+ */ - u16 s2ddt_enabled:1; /* 165+ */ - u16 dpst_enabled:1; /* 165-227 */ - u16 bltclt_enabled:1; /* 165+ */ - u16 adb_enabled:1; /* 165-227 */ - u16 drrs_enabled:1; /* 165-227 */ - u16 grs_enabled:1; /* 165+ */ - u16 gpmt_enabled:1; /* 165+ */ - u16 tbt_enabled:1; /* 165+ */ + u16 rmpm_enabled:1; /* 159+ */ + u16 s2ddt_enabled:1; /* 159+ */ + u16 dpst_enabled:1; /* 159-227 */ + u16 bltclt_enabled:1; /* 159+ */ + u16 adb_enabled:1; /* 159-227 */ + u16 drrs_enabled:1; /* 159-227 */ + u16 grs_enabled:1; /* 159+ */ + u16 gpmt_enabled:1; /* 159+ */ + u16 tbt_enabled:1; /* 159+ */ u16 psr_enabled:1; /* 165-227 */ u16 ips_enabled:1; /* 165+ */ - u16 dpfs_enabled:1; /* 165+ */ + u16 dfps_enabled:1; /* 165+ */ u16 dmrrs_enabled:1; /* 174-227 */ u16 adt_enabled:1; /* ???-228 */ u16 hpd_wake:1; /* 201-240 */ - u16 pc_feature_valid:1; + u16 pc_feature_valid:1; /* 159+ */ } __packed; /* @@ -880,11 +881,12 @@ struct bdb_lvds_lfp_data_tail { struct lfp_backlight_data_entry { u8 type:2; u8 active_low_pwm:1; - u8 obsolete1:5; + u8 i2c_pin:3; /* obsolete since ? */ + u8 i2c_speed:2; /* obsolete since ? */ u16 pwm_freq_hz; u8 min_brightness; /* ???-233 */ - u8 obsolete2; - u8 obsolete3; + u8 i2c_address; /* obsolete since ? */ + u8 i2c_command; /* obsolete since ? */ } __packed; struct lfp_backlight_control_method { @@ -905,8 +907,8 @@ struct lfp_brightness_level { struct bdb_lfp_backlight_data { u8 entry_size; struct lfp_backlight_data_entry data[16]; - u8 level[16]; /* ???-233 */ - struct lfp_backlight_control_method backlight_control[16]; + u8 level[16]; /* 162-233 */ + struct lfp_backlight_control_method backlight_control[16]; /* 191+ */ struct lfp_brightness_level brightness_level[16]; /* 234+ */ struct lfp_brightness_level brightness_min_level[16]; /* 234+ */ u8 brightness_precision_bits[16]; /* 236+ */ @@ -917,7 +919,7 @@ struct bdb_lfp_backlight_data { * Block 44 - LFP Power Conservation Features Block */ struct lfp_power_features { - u8 reserved1:1; + u8 dpst_support:1; /* ???-159 */ u8 power_conservation_pref:3; u8 reserved2:1; u8 lace_enabled_status:1; /* 210+ */ diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index eb5bd0743902..894ee97b3e1b 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -9,6 +9,7 @@ #include "intel_de.h" #include "intel_display_types.h" #include "intel_vrr.h" +#include "intel_dp.h" bool intel_vrr_is_capable(struct intel_connector *connector) { @@ -113,10 +114,18 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct drm_display_info *info = &connector->base.display_info; int vmin, vmax; + /* + * FIXME all joined pipes share the same transcoder. + * Need to account for that during VRR toggle/push/etc. + */ + if (crtc_state->bigjoiner_pipes) + return; + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) return; @@ -165,6 +174,14 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, if (crtc_state->uapi.vrr_enabled) { crtc_state->vrr.enable = true; crtc_state->mode_flags |= I915_MODE_FLAG_VRR; + if (intel_dp_as_sdp_supported(intel_dp)) { + crtc_state->vrr.vsync_start = + (crtc_state->hw.adjusted_mode.crtc_vtotal - + crtc_state->hw.adjusted_mode.vsync_start); + crtc_state->vrr.vsync_end = + (crtc_state->hw.adjusted_mode.crtc_vtotal - + crtc_state->hw.adjusted_mode.vsync_end); + } } } @@ -240,6 +257,12 @@ void intel_vrr_enable(const struct intel_crtc_state *crtc_state) return; intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), TRANS_PUSH_EN); + + if (HAS_AS_SDP(dev_priv)) + intel_de_write(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder), + VRR_VSYNC_END(crtc_state->vrr.vsync_end) | + VRR_VSYNC_START(crtc_state->vrr.vsync_start)); + intel_de_write(dev_priv, TRANS_VRR_CTL(cpu_transcoder), VRR_CTL_VRR_ENABLE | trans_vrr_ctl(crtc_state)); } @@ -258,13 +281,16 @@ void intel_vrr_disable(const struct intel_crtc_state *old_crtc_state) intel_de_wait_for_clear(dev_priv, TRANS_VRR_STATUS(cpu_transcoder), VRR_STATUS_VRR_EN_LIVE, 1000); intel_de_write(dev_priv, TRANS_PUSH(cpu_transcoder), 0); + + if (HAS_AS_SDP(dev_priv)) + intel_de_write(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder), 0); } void intel_vrr_get_config(struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 trans_vrr_ctl; + u32 trans_vrr_ctl, trans_vrr_vsync; trans_vrr_ctl = intel_de_read(dev_priv, TRANS_VRR_CTL(cpu_transcoder)); @@ -284,6 +310,16 @@ void intel_vrr_get_config(struct intel_crtc_state *crtc_state) crtc_state->vrr.vmin = intel_de_read(dev_priv, TRANS_VRR_VMIN(cpu_transcoder)) + 1; } - if (crtc_state->vrr.enable) + if (crtc_state->vrr.enable) { crtc_state->mode_flags |= I915_MODE_FLAG_VRR; + + if (HAS_AS_SDP(dev_priv)) { + trans_vrr_vsync = + intel_de_read(dev_priv, TRANS_VRR_VSYNC(cpu_transcoder)); + crtc_state->vrr.vsync_start = + REG_FIELD_GET(VRR_VSYNC_START_MASK, trans_vrr_vsync); + crtc_state->vrr.vsync_end = + REG_FIELD_GET(VRR_VSYNC_END_MASK, trans_vrr_vsync); + } + } } diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 8a934bada624..baa601d27815 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -213,10 +213,11 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach, * The pipe scaler does not use all the bits of PIPESRC, at least * on the earlier platforms. So even when we're scaling a plane * the *pipe* source size must not be too large. For simplicity - * we assume the limits match the scaler source size limits. Might - * not be 100% accurate on all platforms, but good enough for now. + * we assume the limits match the scaler destination size limits. + * Might not be 100% accurate on all platforms, but good enough for + * now. */ - if (pipe_src_w > max_src_w || pipe_src_h > max_src_h) { + if (pipe_src_w > max_dst_w || pipe_src_h > max_dst_h) { drm_dbg_kms(&dev_priv->drm, "scaler_user index %u.%u: pipe src size %ux%u " "is out of scaler range\n", diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c index c6b9be80d83c..7c6187b4479f 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.c +++ b/drivers/gpu/drm/i915/display/skl_watermark.c @@ -6,18 +6,19 @@ #include #include "i915_drv.h" -#include "i915_fixed.h" #include "i915_reg.h" #include "i9xx_wm.h" #include "intel_atomic.h" #include "intel_atomic_plane.h" #include "intel_bw.h" +#include "intel_cdclk.h" #include "intel_crtc.h" #include "intel_de.h" #include "intel_display.h" #include "intel_display_power.h" #include "intel_display_types.h" #include "intel_fb.h" +#include "intel_fixed.h" #include "intel_pcode.h" #include "intel_wm.h" #include "skl_watermark.h" @@ -69,7 +70,7 @@ static bool skl_needs_memory_bw_wa(struct drm_i915_private *i915) return DISPLAY_VER(i915) == 9; } -static bool +bool intel_has_sagv(struct drm_i915_private *i915) { return HAS_SAGV(i915) && @@ -2601,10 +2602,17 @@ skl_compute_ddb(struct intel_atomic_state *state) return ret; } - if (HAS_MBUS_JOINING(i915)) + if (HAS_MBUS_JOINING(i915)) { new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes); + if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { + ret = intel_cdclk_state_set_joined_mbus(state, new_dbuf_state->joined_mbus); + if (ret) + return ret; + } + } + for_each_intel_crtc(&i915->drm, crtc) { enum pipe pipe = crtc->pipe; @@ -2628,13 +2636,6 @@ skl_compute_ddb(struct intel_atomic_state *state) if (ret) return ret; - if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) { - /* TODO: Implement vblank synchronized MBUS joining changes */ - ret = intel_modeset_all_pipes_late(state, "MBUS joining change"); - if (ret) - return ret; - } - drm_dbg_kms(&i915->drm, "Enabled dbuf slices 0x%x -> 0x%x (total dbuf slices 0x%x), mbus joined? %s->%s\n", old_dbuf_state->enabled_slices, @@ -3057,6 +3058,8 @@ static void skl_wm_get_hw_state(struct drm_i915_private *i915) if (HAS_MBUS_JOINING(i915)) dbuf_state->joined_mbus = intel_de_read(i915, MBUS_CTL) & MBUS_JOIN; + dbuf_state->mdclk_cdclk_ratio = intel_mdclk_cdclk_ratio(i915, &i915->display.cdclk.hw); + for_each_intel_crtc(&i915->drm, crtc) { struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); @@ -3530,85 +3533,6 @@ int intel_dbuf_init(struct drm_i915_private *i915) return 0; } -/* - * Configure MBUS_CTL and all DBUF_CTL_S of each slice to join_mbus state before - * update the request state of all DBUS slices. - */ -static void update_mbus_pre_enable(struct intel_atomic_state *state) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - u32 mbus_ctl, dbuf_min_tracker_val; - enum dbuf_slice slice; - const struct intel_dbuf_state *dbuf_state = - intel_atomic_get_new_dbuf_state(state); - - if (!HAS_MBUS_JOINING(i915)) - return; - - /* - * TODO: Implement vblank synchronized MBUS joining changes. - * Must be properly coordinated with dbuf reprogramming. - */ - if (dbuf_state->joined_mbus) { - mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN | - MBUS_JOIN_PIPE_SELECT_NONE; - dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(3); - } else { - mbus_ctl = MBUS_HASHING_MODE_2x2 | - MBUS_JOIN_PIPE_SELECT_NONE; - dbuf_min_tracker_val = DBUF_MIN_TRACKER_STATE_SERVICE(1); - } - - intel_de_rmw(i915, MBUS_CTL, - MBUS_HASHING_MODE_MASK | MBUS_JOIN | - MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); - - for_each_dbuf_slice(i915, slice) - intel_de_rmw(i915, DBUF_CTL_S(slice), - DBUF_MIN_TRACKER_STATE_SERVICE_MASK, - dbuf_min_tracker_val); -} - -void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_dbuf_state *new_dbuf_state = - intel_atomic_get_new_dbuf_state(state); - const struct intel_dbuf_state *old_dbuf_state = - intel_atomic_get_old_dbuf_state(state); - - if (!new_dbuf_state || - (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && - new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) - return; - - WARN_ON(!new_dbuf_state->base.changed); - - update_mbus_pre_enable(state); - gen9_dbuf_slices_update(i915, - old_dbuf_state->enabled_slices | - new_dbuf_state->enabled_slices); -} - -void intel_dbuf_post_plane_update(struct intel_atomic_state *state) -{ - struct drm_i915_private *i915 = to_i915(state->base.dev); - const struct intel_dbuf_state *new_dbuf_state = - intel_atomic_get_new_dbuf_state(state); - const struct intel_dbuf_state *old_dbuf_state = - intel_atomic_get_old_dbuf_state(state); - - if (!new_dbuf_state || - (new_dbuf_state->enabled_slices == old_dbuf_state->enabled_slices && - new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus)) - return; - - WARN_ON(!new_dbuf_state->base.changed); - - gen9_dbuf_slices_update(i915, - new_dbuf_state->enabled_slices); -} - static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) { switch (pipe) { @@ -3628,14 +3552,12 @@ static bool xelpdp_is_only_pipe_per_dbuf_bank(enum pipe pipe, u8 active_pipes) return false; } -void intel_mbus_dbox_update(struct intel_atomic_state *state) +static void intel_mbus_dbox_update(struct intel_atomic_state *state) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; - const struct intel_crtc_state *new_crtc_state; const struct intel_crtc *crtc; u32 val = 0; - int i; if (DISPLAY_VER(i915) < 11) return; @@ -3679,12 +3601,9 @@ void intel_mbus_dbox_update(struct intel_atomic_state *state) val |= MBUS_DBOX_B_CREDIT(8); } - for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, new_dbuf_state->active_pipes) { u32 pipe_val = val; - if (!new_crtc_state->hw.active) - continue; - if (DISPLAY_VER(i915) >= 14) { if (xelpdp_is_only_pipe_per_dbuf_bank(crtc->pipe, new_dbuf_state->active_pipes)) @@ -3697,6 +3616,217 @@ void intel_mbus_dbox_update(struct intel_atomic_state *state) } } +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, + int ratio) +{ + struct intel_dbuf_state *dbuf_state; + + dbuf_state = intel_atomic_get_dbuf_state(state); + if (IS_ERR(dbuf_state)) + return PTR_ERR(dbuf_state); + + dbuf_state->mdclk_cdclk_ratio = ratio; + + return intel_atomic_lock_global_state(&dbuf_state->base); +} + +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, + int ratio, bool joined_mbus) +{ + enum dbuf_slice slice; + + if (!HAS_MBUS_JOINING(i915)) + return; + + if (DISPLAY_VER(i915) >= 20) + intel_de_rmw(i915, MBUS_CTL, MBUS_TRANSLATION_THROTTLE_MIN_MASK, + MBUS_TRANSLATION_THROTTLE_MIN(ratio - 1)); + + if (joined_mbus) + ratio *= 2; + + drm_dbg_kms(&i915->drm, "Updating dbuf ratio to %d (mbus joined: %s)\n", + ratio, str_yes_no(joined_mbus)); + + for_each_dbuf_slice(i915, slice) + intel_de_rmw(i915, DBUF_CTL_S(slice), + DBUF_MIN_TRACKER_STATE_SERVICE_MASK, + DBUF_MIN_TRACKER_STATE_SERVICE(ratio - 1)); +} + +static void intel_dbuf_mdclk_min_tracker_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + int mdclk_cdclk_ratio; + + if (intel_cdclk_is_decreasing_later(state)) { + /* cdclk/mdclk will be changed later by intel_set_cdclk_post_plane_update() */ + mdclk_cdclk_ratio = old_dbuf_state->mdclk_cdclk_ratio; + } else { + /* cdclk/mdclk already changed by intel_set_cdclk_pre_plane_update() */ + mdclk_cdclk_ratio = new_dbuf_state->mdclk_cdclk_ratio; + } + + intel_dbuf_mdclk_cdclk_ratio_update(i915, mdclk_cdclk_ratio, + new_dbuf_state->joined_mbus); +} + +static enum pipe intel_mbus_joined_pipe(struct intel_atomic_state *state, + const struct intel_dbuf_state *dbuf_state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + enum pipe pipe = ffs(dbuf_state->active_pipes) - 1; + const struct intel_crtc_state *new_crtc_state; + struct intel_crtc *crtc; + + drm_WARN_ON(&i915->drm, !dbuf_state->joined_mbus); + drm_WARN_ON(&i915->drm, !is_power_of_2(dbuf_state->active_pipes)); + + crtc = intel_crtc_for_pipe(i915, pipe); + new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + + if (new_crtc_state && !intel_crtc_needs_modeset(new_crtc_state)) + return pipe; + else + return INVALID_PIPE; +} + +static void intel_dbuf_mbus_join_update(struct intel_atomic_state *state, + enum pipe pipe) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + u32 mbus_ctl; + + drm_dbg_kms(&i915->drm, "Changing mbus joined: %s -> %s (pipe: %c)\n", + str_yes_no(old_dbuf_state->joined_mbus), + str_yes_no(new_dbuf_state->joined_mbus), + pipe != INVALID_PIPE ? pipe_name(pipe) : '*'); + + if (new_dbuf_state->joined_mbus) + mbus_ctl = MBUS_HASHING_MODE_1x4 | MBUS_JOIN; + else + mbus_ctl = MBUS_HASHING_MODE_2x2; + + if (pipe != INVALID_PIPE) + mbus_ctl |= MBUS_JOIN_PIPE_SELECT(pipe); + else + mbus_ctl |= MBUS_JOIN_PIPE_SELECT_NONE; + + intel_de_rmw(i915, MBUS_CTL, + MBUS_HASHING_MODE_MASK | MBUS_JOIN | + MBUS_JOIN_PIPE_SELECT_MASK, mbus_ctl); +} + +void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state) +{ + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + + if (!new_dbuf_state) + return; + + if (!old_dbuf_state->joined_mbus && new_dbuf_state->joined_mbus) { + enum pipe pipe = intel_mbus_joined_pipe(state, new_dbuf_state); + + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mbus_join_update(state, pipe); + intel_mbus_dbox_update(state); + intel_dbuf_mdclk_min_tracker_update(state); + } +} + +void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + + if (!new_dbuf_state) + return; + + if (old_dbuf_state->joined_mbus && !new_dbuf_state->joined_mbus) { + enum pipe pipe = intel_mbus_joined_pipe(state, old_dbuf_state); + + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mdclk_min_tracker_update(state); + intel_mbus_dbox_update(state); + intel_dbuf_mbus_join_update(state, pipe); + + if (pipe != INVALID_PIPE) { + struct intel_crtc *crtc = intel_crtc_for_pipe(i915, pipe); + + intel_crtc_wait_for_next_vblank(crtc); + } + } else if (old_dbuf_state->joined_mbus == new_dbuf_state->joined_mbus && + old_dbuf_state->active_pipes != new_dbuf_state->active_pipes) { + WARN_ON(!new_dbuf_state->base.changed); + + intel_dbuf_mdclk_min_tracker_update(state); + intel_mbus_dbox_update(state); + } + +} + +void intel_dbuf_pre_plane_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + u8 old_slices, new_slices; + + if (!new_dbuf_state) + return; + + old_slices = old_dbuf_state->enabled_slices; + new_slices = old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices; + + if (old_slices == new_slices) + return; + + WARN_ON(!new_dbuf_state->base.changed); + + gen9_dbuf_slices_update(i915, new_slices); +} + +void intel_dbuf_post_plane_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state = + intel_atomic_get_new_dbuf_state(state); + const struct intel_dbuf_state *old_dbuf_state = + intel_atomic_get_old_dbuf_state(state); + u8 old_slices, new_slices; + + if (!new_dbuf_state) + return; + + old_slices = old_dbuf_state->enabled_slices | new_dbuf_state->enabled_slices; + new_slices = new_dbuf_state->enabled_slices; + + if (old_slices == new_slices) + return; + + WARN_ON(!new_dbuf_state->base.changed); + + gen9_dbuf_slices_update(i915, new_slices); +} + static int skl_watermark_ipc_status_show(struct seq_file *m, void *data) { struct drm_i915_private *i915 = m->private; diff --git a/drivers/gpu/drm/i915/display/skl_watermark.h b/drivers/gpu/drm/i915/display/skl_watermark.h index e3d1d74a7b17..91f92c0e706e 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark.h +++ b/drivers/gpu/drm/i915/display/skl_watermark.h @@ -25,6 +25,7 @@ void intel_sagv_pre_plane_update(struct intel_atomic_state *state); void intel_sagv_post_plane_update(struct intel_atomic_state *state); bool intel_can_enable_sagv(struct drm_i915_private *i915, const struct intel_bw_state *bw_state); +bool intel_has_sagv(struct drm_i915_private *i915); u32 skl_ddb_dbuf_slice_mask(struct drm_i915_private *i915, const struct skl_ddb_entry *entry); @@ -58,22 +59,31 @@ struct intel_dbuf_state { u8 slices[I915_MAX_PIPES]; u8 enabled_slices; u8 active_pipes; + u8 mdclk_cdclk_ratio; bool joined_mbus; }; struct intel_dbuf_state * intel_atomic_get_dbuf_state(struct intel_atomic_state *state); -#define to_intel_dbuf_state(x) container_of((x), struct intel_dbuf_state, base) +#define to_intel_dbuf_state(global_state) \ + container_of_const((global_state), struct intel_dbuf_state, base) + #define intel_atomic_get_old_dbuf_state(state) \ to_intel_dbuf_state(intel_atomic_get_old_global_obj_state(state, &to_i915(state->base.dev)->display.dbuf.obj)) #define intel_atomic_get_new_dbuf_state(state) \ to_intel_dbuf_state(intel_atomic_get_new_global_obj_state(state, &to_i915(state->base.dev)->display.dbuf.obj)) int intel_dbuf_init(struct drm_i915_private *i915); +int intel_dbuf_state_set_mdclk_cdclk_ratio(struct intel_atomic_state *state, + int ratio); + void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); -void intel_mbus_dbox_update(struct intel_atomic_state *state); +void intel_dbuf_mdclk_cdclk_ratio_update(struct drm_i915_private *i915, + int ratio, bool joined_mbus); +void intel_dbuf_mbus_pre_ddb_update(struct intel_atomic_state *state); +void intel_dbuf_mbus_post_ddb_update(struct intel_atomic_state *state); #endif /* __SKL_WATERMARK_H__ */ diff --git a/drivers/gpu/drm/i915/display/skl_watermark_regs.h b/drivers/gpu/drm/i915/display/skl_watermark_regs.h index 20b30c9a6613..269163fa3350 100644 --- a/drivers/gpu/drm/i915/display/skl_watermark_regs.h +++ b/drivers/gpu/drm/i915/display/skl_watermark_regs.h @@ -32,14 +32,16 @@ #define MBUS_BBOX_CTL_S1 _MMIO(0x45040) #define MBUS_BBOX_CTL_S2 _MMIO(0x45044) -#define MBUS_CTL _MMIO(0x4438C) -#define MBUS_JOIN REG_BIT(31) -#define MBUS_HASHING_MODE_MASK REG_BIT(30) -#define MBUS_HASHING_MODE_2x2 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 0) -#define MBUS_HASHING_MODE_1x4 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 1) -#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26) -#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe) -#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7) +#define MBUS_CTL _MMIO(0x4438C) +#define MBUS_JOIN REG_BIT(31) +#define MBUS_HASHING_MODE_MASK REG_BIT(30) +#define MBUS_HASHING_MODE_2x2 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 0) +#define MBUS_HASHING_MODE_1x4 REG_FIELD_PREP(MBUS_HASHING_MODE_MASK, 1) +#define MBUS_JOIN_PIPE_SELECT_MASK REG_GENMASK(28, 26) +#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe) +#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7) +#define MBUS_TRANSLATION_THROTTLE_MIN_MASK REG_GENMASK(15, 13) +#define MBUS_TRANSLATION_THROTTLE_MIN(val) REG_FIELD_PREP(MBUS_TRANSLATION_THROTTLE_MIN_MASK, val) /* Watermark register definitions for SKL */ #define _CUR_WM_A_0 0x70140 diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 9b33b8a74d64..ee9923c7b115 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -85,20 +85,18 @@ enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt) void vlv_dsi_wait_for_fifo_empty(struct intel_dsi *intel_dsi, enum port port) { - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(&intel_dsi->base); u32 mask; mask = LP_CTRL_FIFO_EMPTY | HS_CTRL_FIFO_EMPTY | LP_DATA_FIFO_EMPTY | HS_DATA_FIFO_EMPTY; - if (intel_de_wait_for_set(dev_priv, MIPI_GEN_FIFO_STAT(port), + if (intel_de_wait_for_set(display, MIPI_GEN_FIFO_STAT(display, port), mask, 100)) - drm_err(&dev_priv->drm, "DPI FIFOs are not empty\n"); + drm_err(display->drm, "DPI FIFOs are not empty\n"); } -static void write_data(struct drm_i915_private *dev_priv, +static void write_data(struct intel_display *display, i915_reg_t reg, const u8 *data, u32 len) { @@ -110,18 +108,18 @@ static void write_data(struct drm_i915_private *dev_priv, for (j = 0; j < min_t(u32, len - i, 4); j++) val |= *data++ << 8 * j; - intel_de_write(dev_priv, reg, val); + intel_de_write(display, reg, val); } } -static void read_data(struct drm_i915_private *dev_priv, +static void read_data(struct intel_display *display, i915_reg_t reg, u8 *data, u32 len) { u32 i, j; for (i = 0; i < len; i += 4) { - u32 val = intel_de_read(dev_priv, reg); + u32 val = intel_de_read(display, reg); for (j = 0; j < min_t(u32, len - i, 4); j++) *data++ = val >> 8 * j; @@ -132,8 +130,8 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { struct intel_dsi_host *intel_dsi_host = to_intel_dsi_host(host); - struct drm_device *dev = intel_dsi_host->intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_dsi *intel_dsi = intel_dsi_host->intel_dsi; + struct intel_display *display = to_intel_display(&intel_dsi->base); enum port port = intel_dsi_host->port; struct mipi_dsi_packet packet; ssize_t ret; @@ -148,51 +146,51 @@ static ssize_t intel_dsi_host_transfer(struct mipi_dsi_host *host, header = packet.header; if (msg->flags & MIPI_DSI_MSG_USE_LPM) { - data_reg = MIPI_LP_GEN_DATA(port); + data_reg = MIPI_LP_GEN_DATA(display, port); data_mask = LP_DATA_FIFO_FULL; - ctrl_reg = MIPI_LP_GEN_CTRL(port); + ctrl_reg = MIPI_LP_GEN_CTRL(display, port); ctrl_mask = LP_CTRL_FIFO_FULL; } else { - data_reg = MIPI_HS_GEN_DATA(port); + data_reg = MIPI_HS_GEN_DATA(display, port); data_mask = HS_DATA_FIFO_FULL; - ctrl_reg = MIPI_HS_GEN_CTRL(port); + ctrl_reg = MIPI_HS_GEN_CTRL(display, port); ctrl_mask = HS_CTRL_FIFO_FULL; } /* note: this is never true for reads */ if (packet.payload_length) { - if (intel_de_wait_for_clear(dev_priv, MIPI_GEN_FIFO_STAT(port), + if (intel_de_wait_for_clear(display, MIPI_GEN_FIFO_STAT(display, port), data_mask, 50)) - drm_err(&dev_priv->drm, + drm_err(display->drm, "Timeout waiting for HS/LP DATA FIFO !full\n"); - write_data(dev_priv, data_reg, packet.payload, + write_data(display, data_reg, packet.payload, packet.payload_length); } if (msg->rx_len) { - intel_de_write(dev_priv, MIPI_INTR_STAT(port), + intel_de_write(display, MIPI_INTR_STAT(display, port), GEN_READ_DATA_AVAIL); } - if (intel_de_wait_for_clear(dev_priv, MIPI_GEN_FIFO_STAT(port), + if (intel_de_wait_for_clear(display, MIPI_GEN_FIFO_STAT(display, port), ctrl_mask, 50)) { - drm_err(&dev_priv->drm, + drm_err(display->drm, "Timeout waiting for HS/LP CTRL FIFO !full\n"); } - intel_de_write(dev_priv, ctrl_reg, + intel_de_write(display, ctrl_reg, header[2] << 16 | header[1] << 8 | header[0]); /* ->rx_len is set only for reads */ if (msg->rx_len) { data_mask = GEN_READ_DATA_AVAIL; - if (intel_de_wait_for_set(dev_priv, MIPI_INTR_STAT(port), + if (intel_de_wait_for_set(display, MIPI_INTR_STAT(display, port), data_mask, 50)) - drm_err(&dev_priv->drm, + drm_err(display->drm, "Timeout waiting for read data.\n"); - read_data(dev_priv, data_reg, msg->rx_buf, msg->rx_len); + read_data(display, data_reg, msg->rx_buf, msg->rx_len); } /* XXX: fix for reads and writes */ @@ -225,9 +223,7 @@ static const struct mipi_dsi_host_ops intel_dsi_host_ops = { static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, enum port port) { - struct drm_encoder *encoder = &intel_dsi->base.base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(&intel_dsi->base); u32 mask; /* XXX: pipe, hs */ @@ -237,18 +233,18 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, cmd |= DPI_LP_MODE; /* clear bit */ - intel_de_write(dev_priv, MIPI_INTR_STAT(port), SPL_PKT_SENT_INTERRUPT); + intel_de_write(display, MIPI_INTR_STAT(display, port), SPL_PKT_SENT_INTERRUPT); /* XXX: old code skips write if control unchanged */ - if (cmd == intel_de_read(dev_priv, MIPI_DPI_CONTROL(port))) - drm_dbg_kms(&dev_priv->drm, + if (cmd == intel_de_read(display, MIPI_DPI_CONTROL(display, port))) + drm_dbg_kms(display->drm, "Same special packet %02x twice in a row.\n", cmd); - intel_de_write(dev_priv, MIPI_DPI_CONTROL(port), cmd); + intel_de_write(display, MIPI_DPI_CONTROL(display, port), cmd); mask = SPL_PKT_SENT_INTERRUPT; - if (intel_de_wait_for_set(dev_priv, MIPI_INTR_STAT(port), mask, 100)) - drm_err(&dev_priv->drm, + if (intel_de_wait_for_set(display, MIPI_INTR_STAT(display, port), mask, 100)) + drm_err(display->drm, "Video mode command 0x%08x send failed.\n", cmd); return 0; @@ -273,8 +269,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dsi *intel_dsi = container_of(encoder, struct intel_dsi, - base); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct intel_connector *intel_connector = intel_dsi->attached_connector; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; int ret; @@ -329,7 +324,7 @@ static int intel_dsi_compute_config(struct intel_encoder *encoder, static bool glk_dsi_enable_io(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; bool cold_boot = false; @@ -339,29 +334,30 @@ static bool glk_dsi_enable_io(struct intel_encoder *encoder) * Power ON MIPI IO first and then write into IO reset and LP wake bits */ for_each_dsi_port(port, intel_dsi->ports) - intel_de_rmw(dev_priv, MIPI_CTRL(port), 0, GLK_MIPIIO_ENABLE); + intel_de_rmw(display, MIPI_CTRL(display, port), 0, GLK_MIPIIO_ENABLE); /* Put the IO into reset */ - intel_de_rmw(dev_priv, MIPI_CTRL(PORT_A), GLK_MIPIIO_RESET_RELEASED, 0); + intel_de_rmw(display, MIPI_CTRL(display, PORT_A), GLK_MIPIIO_RESET_RELEASED, 0); /* Program LP Wake */ for_each_dsi_port(port, intel_dsi->ports) { - u32 tmp = intel_de_read(dev_priv, MIPI_DEVICE_READY(port)); - intel_de_rmw(dev_priv, MIPI_CTRL(port), + u32 tmp = intel_de_read(display, MIPI_DEVICE_READY(display, port)); + + intel_de_rmw(display, MIPI_CTRL(display, port), GLK_LP_WAKE, (tmp & DEVICE_READY) ? GLK_LP_WAKE : 0); } /* Wait for Pwr ACK */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_set(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_set(display, MIPI_CTRL(display, port), GLK_MIPIIO_PORT_POWERED, 20)) - drm_err(&dev_priv->drm, "MIPIO port is powergated\n"); + drm_err(display->drm, "MIPIO port is powergated\n"); } /* Check for cold boot scenario */ for_each_dsi_port(port, intel_dsi->ports) { cold_boot |= - !(intel_de_read(dev_priv, MIPI_DEVICE_READY(port)) & DEVICE_READY); + !(intel_de_read(display, MIPI_DEVICE_READY(display, port)) & DEVICE_READY); } return cold_boot; @@ -369,99 +365,100 @@ static bool glk_dsi_enable_io(struct intel_encoder *encoder) static void glk_dsi_device_ready(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; /* Wait for MIPI PHY status bit to set */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_set(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_set(display, MIPI_CTRL(display, port), GLK_PHY_STATUS_PORT_READY, 20)) - drm_err(&dev_priv->drm, "PHY is not ON\n"); + drm_err(display->drm, "PHY is not ON\n"); } /* Get IO out of reset */ - intel_de_rmw(dev_priv, MIPI_CTRL(PORT_A), 0, GLK_MIPIIO_RESET_RELEASED); + intel_de_rmw(display, MIPI_CTRL(display, PORT_A), 0, GLK_MIPIIO_RESET_RELEASED); /* Get IO out of Low power state*/ for_each_dsi_port(port, intel_dsi->ports) { - if (!(intel_de_read(dev_priv, MIPI_DEVICE_READY(port)) & DEVICE_READY)) { - intel_de_rmw(dev_priv, MIPI_DEVICE_READY(port), + if (!(intel_de_read(display, MIPI_DEVICE_READY(display, port)) & DEVICE_READY)) { + intel_de_rmw(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_MASK, DEVICE_READY); usleep_range(10, 15); } else { /* Enter ULPS */ - intel_de_rmw(dev_priv, MIPI_DEVICE_READY(port), + intel_de_rmw(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_MASK, ULPS_STATE_ENTER | DEVICE_READY); /* Wait for ULPS active */ - if (intel_de_wait_for_clear(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_clear(display, MIPI_CTRL(display, port), GLK_ULPS_NOT_ACTIVE, 20)) - drm_err(&dev_priv->drm, "ULPS not active\n"); + drm_err(display->drm, "ULPS not active\n"); /* Exit ULPS */ - intel_de_rmw(dev_priv, MIPI_DEVICE_READY(port), + intel_de_rmw(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_MASK, ULPS_STATE_EXIT | DEVICE_READY); /* Enter Normal Mode */ - intel_de_rmw(dev_priv, MIPI_DEVICE_READY(port), + intel_de_rmw(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_MASK, ULPS_STATE_NORMAL_OPERATION | DEVICE_READY); - intel_de_rmw(dev_priv, MIPI_CTRL(port), GLK_LP_WAKE, 0); + intel_de_rmw(display, MIPI_CTRL(display, port), GLK_LP_WAKE, 0); } } /* Wait for Stop state */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_set(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_set(display, MIPI_CTRL(display, port), GLK_DATA_LANE_STOP_STATE, 20)) - drm_err(&dev_priv->drm, + drm_err(display->drm, "Date lane not in STOP state\n"); } /* Wait for AFE LATCH */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_set(dev_priv, BXT_MIPI_PORT_CTRL(port), + if (intel_de_wait_for_set(display, BXT_MIPI_PORT_CTRL(port), AFE_LATCHOUT, 20)) - drm_err(&dev_priv->drm, + drm_err(display->drm, "D-PHY not entering LP-11 state\n"); } } static void bxt_dsi_device_ready(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; u32 val; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); /* Enable MIPI PHY transparent latch */ for_each_dsi_port(port, intel_dsi->ports) { - intel_de_rmw(dev_priv, BXT_MIPI_PORT_CTRL(port), 0, LP_OUTPUT_HOLD); + intel_de_rmw(display, BXT_MIPI_PORT_CTRL(port), 0, LP_OUTPUT_HOLD); usleep_range(2000, 2500); } /* Clear ULPS and set device ready */ for_each_dsi_port(port, intel_dsi->ports) { - val = intel_de_read(dev_priv, MIPI_DEVICE_READY(port)); + val = intel_de_read(display, MIPI_DEVICE_READY(display, port)); val &= ~ULPS_STATE_MASK; - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), val); + intel_de_write(display, MIPI_DEVICE_READY(display, port), val); usleep_range(2000, 2500); val |= DEVICE_READY; - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), val); + intel_de_write(display, MIPI_DEVICE_READY(display, port), val); } } static void vlv_dsi_device_ready(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); vlv_flisdsi_get(dev_priv); /* program rcomp for compliance, reduce from 50 ohms to 45 ohms @@ -474,7 +471,7 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder) for_each_dsi_port(port, intel_dsi->ports) { - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_ENTER); usleep_range(2500, 3000); @@ -482,14 +479,14 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder) * Common bit for both MIPI Port A & MIPI Port C * No similar bit in MIPI Port C reg */ - intel_de_rmw(dev_priv, MIPI_PORT_CTRL(PORT_A), 0, LP_OUTPUT_HOLD); + intel_de_rmw(display, VLV_MIPI_PORT_CTRL(PORT_A), 0, LP_OUTPUT_HOLD); usleep_range(1000, 1500); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_EXIT); usleep_range(2500, 3000); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), DEVICE_READY); usleep_range(2500, 3000); } @@ -509,50 +506,50 @@ static void intel_dsi_device_ready(struct intel_encoder *encoder) static void glk_dsi_enter_low_power_mode(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; /* Enter ULPS */ for_each_dsi_port(port, intel_dsi->ports) - intel_de_rmw(dev_priv, MIPI_DEVICE_READY(port), + intel_de_rmw(display, MIPI_DEVICE_READY(display, port), ULPS_STATE_MASK, ULPS_STATE_ENTER | DEVICE_READY); /* Wait for MIPI PHY status bit to unset */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_clear(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_clear(display, MIPI_CTRL(display, port), GLK_PHY_STATUS_PORT_READY, 20)) - drm_err(&dev_priv->drm, "PHY is not turning OFF\n"); + drm_err(display->drm, "PHY is not turning OFF\n"); } /* Wait for Pwr ACK bit to unset */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_clear(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_clear(display, MIPI_CTRL(display, port), GLK_MIPIIO_PORT_POWERED, 20)) - drm_err(&dev_priv->drm, + drm_err(display->drm, "MIPI IO Port is not powergated\n"); } } static void glk_dsi_disable_mipi_io(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; /* Put the IO into reset */ - intel_de_rmw(dev_priv, MIPI_CTRL(PORT_A), GLK_MIPIIO_RESET_RELEASED, 0); + intel_de_rmw(display, MIPI_CTRL(display, PORT_A), GLK_MIPIIO_RESET_RELEASED, 0); /* Wait for MIPI PHY status bit to unset */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_wait_for_clear(dev_priv, MIPI_CTRL(port), + if (intel_de_wait_for_clear(display, MIPI_CTRL(display, port), GLK_PHY_STATUS_PORT_READY, 20)) - drm_err(&dev_priv->drm, "PHY is not turning OFF\n"); + drm_err(display->drm, "PHY is not turning OFF\n"); } /* Clear MIPI mode */ for_each_dsi_port(port, intel_dsi->ports) - intel_de_rmw(dev_priv, MIPI_CTRL(port), GLK_MIPIIO_ENABLE, 0); + intel_de_rmw(display, MIPI_CTRL(display, port), GLK_MIPIIO_ENABLE, 0); } static void glk_dsi_clear_device_ready(struct intel_encoder *encoder) @@ -564,30 +561,31 @@ static void glk_dsi_clear_device_ready(struct intel_encoder *encoder) static i915_reg_t port_ctrl_reg(struct drm_i915_private *i915, enum port port) { return IS_GEMINILAKE(i915) || IS_BROXTON(i915) ? - BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); + BXT_MIPI_PORT_CTRL(port) : VLV_MIPI_PORT_CTRL(port); } static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); for_each_dsi_port(port, intel_dsi->ports) { /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */ i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? - BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A); + BXT_MIPI_PORT_CTRL(port) : VLV_MIPI_PORT_CTRL(PORT_A); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), DEVICE_READY | ULPS_STATE_ENTER); usleep_range(2000, 2500); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), DEVICE_READY | ULPS_STATE_EXIT); usleep_range(2000, 2500); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), + intel_de_write(display, MIPI_DEVICE_READY(display, port), DEVICE_READY | ULPS_STATE_ENTER); usleep_range(2000, 2500); @@ -596,15 +594,15 @@ static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder) * Port A only. MIPI Port C has no similar bit for checking. */ if ((IS_BROXTON(dev_priv) || port == PORT_A) && - intel_de_wait_for_clear(dev_priv, port_ctrl, + intel_de_wait_for_clear(display, port_ctrl, AFE_LATCHOUT, 30)) - drm_err(&dev_priv->drm, "DSI LP not going Low\n"); + drm_err(display->drm, "DSI LP not going Low\n"); /* Disable MIPI PHY transparent latch */ - intel_de_rmw(dev_priv, port_ctrl, LP_OUTPUT_HOLD, 0); + intel_de_rmw(display, port_ctrl, LP_OUTPUT_HOLD, 0); usleep_range(1000, 1500); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), 0x00); + intel_de_write(display, MIPI_DEVICE_READY(display, port), 0x00); usleep_range(2000, 2500); } } @@ -612,6 +610,7 @@ static void vlv_dsi_clear_device_ready(struct intel_encoder *encoder) static void intel_dsi_port_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); @@ -622,11 +621,11 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder, if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { for_each_dsi_port(port, intel_dsi->ports) - intel_de_rmw(dev_priv, MIPI_CTRL(port), + intel_de_rmw(display, MIPI_CTRL(display, port), BXT_PIXEL_OVERLAP_CNT_MASK, temp << BXT_PIXEL_OVERLAP_CNT_SHIFT); } else { - intel_de_rmw(dev_priv, VLV_CHICKEN_3, + intel_de_rmw(display, VLV_CHICKEN_3, PIXEL_OVERLAP_CNT_MASK, temp << PIXEL_OVERLAP_CNT_SHIFT); } @@ -636,7 +635,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder, i915_reg_t port_ctrl = port_ctrl_reg(dev_priv, port); u32 temp; - temp = intel_de_read(dev_priv, port_ctrl); + temp = intel_de_read(display, port_ctrl); temp &= ~LANE_CONFIGURATION_MASK; temp &= ~DUAL_LINK_MODE_MASK; @@ -656,15 +655,15 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder, temp |= DITHERING_ENABLE; /* assert ip_tg_enable signal */ - intel_de_write(dev_priv, port_ctrl, temp | DPI_ENABLE); - intel_de_posting_read(dev_priv, port_ctrl); + intel_de_write(display, port_ctrl, temp | DPI_ENABLE); + intel_de_posting_read(display, port_ctrl); } } static void intel_dsi_port_disable(struct intel_encoder *encoder) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; @@ -672,11 +671,12 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) i915_reg_t port_ctrl = port_ctrl_reg(dev_priv, port); /* de-assert ip_tg_enable signal */ - intel_de_rmw(dev_priv, port_ctrl, DPI_ENABLE, 0); - intel_de_posting_read(dev_priv, port_ctrl); + intel_de_rmw(display, port_ctrl, DPI_ENABLE, 0); + intel_de_posting_read(display, port_ctrl); } } -static void intel_dsi_prepare(struct intel_encoder *intel_encoder, + +static void intel_dsi_prepare(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config); static void intel_dsi_unprepare(struct intel_encoder *encoder); @@ -726,6 +726,7 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -733,7 +734,7 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, enum port port; bool glk_cold_boot = false; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); intel_dsi_wait_panel_power_cycle(intel_dsi); @@ -753,16 +754,16 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, if (IS_BROXTON(dev_priv)) { /* Add MIPI IO reset programming for modeset */ - intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, 0, MIPIO_RST_CTRL); + intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, 0, MIPIO_RST_CTRL); /* Power up DSI regulator */ - intel_de_write(dev_priv, BXT_P_DSI_REGULATOR_CFG, STAP_SELECT); - intel_de_write(dev_priv, BXT_P_DSI_REGULATOR_TX_CTRL, 0); + intel_de_write(display, BXT_P_DSI_REGULATOR_CFG, STAP_SELECT); + intel_de_write(display, BXT_P_DSI_REGULATOR_TX_CTRL, 0); } if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { /* Disable DPOunit clock gating, can stall pipe */ - intel_de_rmw(dev_priv, DSPCLK_GATE_D(dev_priv), + intel_de_rmw(display, DSPCLK_GATE_D(dev_priv), 0, DPOUNIT_CLOCK_GATE_DISABLE); } @@ -798,8 +799,8 @@ static void intel_dsi_pre_enable(struct intel_atomic_state *state, */ if (is_cmd_mode(intel_dsi)) { for_each_dsi_port(port, intel_dsi->ports) - intel_de_write(dev_priv, - MIPI_MAX_RETURN_PKT_SIZE(port), 8 * 4); + intel_de_write(display, + MIPI_MAX_RETURN_PKT_SIZE(display, port), 8 * 4); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_TEAR_ON); intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON); } else { @@ -871,11 +872,12 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { intel_crtc_vblank_off(old_crtc_state); @@ -906,12 +908,12 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, if (IS_BROXTON(dev_priv)) { /* Power down DSI regulator to save power */ - intel_de_write(dev_priv, BXT_P_DSI_REGULATOR_CFG, STAP_SELECT); - intel_de_write(dev_priv, BXT_P_DSI_REGULATOR_TX_CTRL, + intel_de_write(display, BXT_P_DSI_REGULATOR_CFG, STAP_SELECT); + intel_de_write(display, BXT_P_DSI_REGULATOR_TX_CTRL, HS_IO_CTRL_SELECT); /* Add MIPI IO reset programming for modeset */ - intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, MIPIO_RST_CTRL, 0); + intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, MIPIO_RST_CTRL, 0); } if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { @@ -919,7 +921,7 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, } else { vlv_dsi_pll_disable(encoder); - intel_de_rmw(dev_priv, DSPCLK_GATE_D(dev_priv), + intel_de_rmw(display, DSPCLK_GATE_D(dev_priv), DPOUNIT_CLOCK_GATE_DISABLE, 0); } @@ -935,13 +937,14 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); intel_wakeref_t wakeref; enum port port; bool active = false; - drm_dbg_kms(&dev_priv->drm, "\n"); + drm_dbg_kms(display->drm, "\n"); wakeref = intel_display_power_get_if_enabled(dev_priv, encoder->power_domain); @@ -960,7 +963,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, /* XXX: this only works for one DSI output */ for_each_dsi_port(port, intel_dsi->ports) { i915_reg_t port_ctrl = port_ctrl_reg(dev_priv, port); - bool enabled = intel_de_read(dev_priv, port_ctrl) & DPI_ENABLE; + bool enabled = intel_de_read(display, port_ctrl) & DPI_ENABLE; /* * Due to some hardware limitations on VLV/CHV, the DPI enable @@ -969,27 +972,27 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, */ if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && port == PORT_C) - enabled = intel_de_read(dev_priv, TRANSCONF(PIPE_B)) & TRANSCONF_ENABLE; + enabled = intel_de_read(display, TRANSCONF(PIPE_B)) & TRANSCONF_ENABLE; /* Try command mode if video mode not enabled */ if (!enabled) { - u32 tmp = intel_de_read(dev_priv, - MIPI_DSI_FUNC_PRG(port)); + u32 tmp = intel_de_read(display, + MIPI_DSI_FUNC_PRG(display, port)); enabled = tmp & CMD_MODE_DATA_WIDTH_MASK; } if (!enabled) continue; - if (!(intel_de_read(dev_priv, MIPI_DEVICE_READY(port)) & DEVICE_READY)) + if (!(intel_de_read(display, MIPI_DEVICE_READY(display, port)) & DEVICE_READY)) continue; if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { - u32 tmp = intel_de_read(dev_priv, MIPI_CTRL(port)); + u32 tmp = intel_de_read(display, MIPI_CTRL(display, port)); tmp &= BXT_PIPE_SELECT_MASK; tmp >>= BXT_PIPE_SELECT_SHIFT; - if (drm_WARN_ON(&dev_priv->drm, tmp > PIPE_C)) + if (drm_WARN_ON(display->drm, tmp > PIPE_C)) continue; *pipe = tmp; @@ -1010,8 +1013,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(encoder); struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct drm_display_mode *adjusted_mode_sw; @@ -1033,11 +1035,11 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, * encoder->get_hw_state() returns true. */ for_each_dsi_port(port, intel_dsi->ports) { - if (intel_de_read(dev_priv, BXT_MIPI_PORT_CTRL(port)) & DPI_ENABLE) + if (intel_de_read(display, BXT_MIPI_PORT_CTRL(port)) & DPI_ENABLE) break; } - fmt = intel_de_read(dev_priv, MIPI_DSI_FUNC_PRG(port)) & VID_MODE_FORMAT_MASK; + fmt = intel_de_read(display, MIPI_DSI_FUNC_PRG(display, port)) & VID_MODE_FORMAT_MASK; bpp = mipi_dsi_pixel_format_to_bpp( pixel_format_from_register_bits(fmt)); @@ -1049,24 +1051,24 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, /* In terms of pixels */ adjusted_mode->crtc_hdisplay = - intel_de_read(dev_priv, + intel_de_read(display, BXT_MIPI_TRANS_HACTIVE(port)); adjusted_mode->crtc_vdisplay = - intel_de_read(dev_priv, + intel_de_read(display, BXT_MIPI_TRANS_VACTIVE(port)); adjusted_mode->crtc_vtotal = - intel_de_read(dev_priv, + intel_de_read(display, BXT_MIPI_TRANS_VTOTAL(port)); hactive = adjusted_mode->crtc_hdisplay; - hfp = intel_de_read(dev_priv, MIPI_HFP_COUNT(port)); + hfp = intel_de_read(display, MIPI_HFP_COUNT(display, port)); /* * Meaningful for video mode non-burst sync pulse mode only, * can be zero for non-burst sync events and burst modes */ - hsync = intel_de_read(dev_priv, MIPI_HSYNC_PADDING_COUNT(port)); - hbp = intel_de_read(dev_priv, MIPI_HBP_COUNT(port)); + hsync = intel_de_read(display, MIPI_HSYNC_PADDING_COUNT(display, port)); + hbp = intel_de_read(display, MIPI_HBP_COUNT(display, port)); /* harizontal values are in terms of high speed byte clock */ hfp = pixels_from_txbyteclkhs(hfp, bpp, lane_count, @@ -1083,8 +1085,8 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, } /* vertical values are in terms of lines */ - vfp = intel_de_read(dev_priv, MIPI_VFP_COUNT(port)); - vsync = intel_de_read(dev_priv, MIPI_VSYNC_PADDING_COUNT(port)); + vfp = intel_de_read(display, MIPI_VFP_COUNT(display, port)); + vsync = intel_de_read(display, MIPI_VSYNC_PADDING_COUNT(display, port)); adjusted_mode->crtc_htotal = hactive + hfp + hsync + hbp; adjusted_mode->crtc_hsync_start = hfp + adjusted_mode->crtc_hdisplay; @@ -1210,12 +1212,12 @@ static u16 txclkesc(u32 divider, unsigned int us) } } -static void set_dsi_timings(struct drm_encoder *encoder, +static void set_dsi_timings(struct intel_encoder *encoder, const struct drm_display_mode *adjusted_mode) { - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(encoder)); + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); unsigned int lane_count = intel_dsi->lane_count; @@ -1256,29 +1258,29 @@ static void set_dsi_timings(struct drm_encoder *encoder, * vactive, as they are calculated per channel basis, * whereas these values should be based on resolution. */ - intel_de_write(dev_priv, BXT_MIPI_TRANS_HACTIVE(port), + intel_de_write(display, BXT_MIPI_TRANS_HACTIVE(port), adjusted_mode->crtc_hdisplay); - intel_de_write(dev_priv, BXT_MIPI_TRANS_VACTIVE(port), + intel_de_write(display, BXT_MIPI_TRANS_VACTIVE(port), adjusted_mode->crtc_vdisplay); - intel_de_write(dev_priv, BXT_MIPI_TRANS_VTOTAL(port), + intel_de_write(display, BXT_MIPI_TRANS_VTOTAL(port), adjusted_mode->crtc_vtotal); } - intel_de_write(dev_priv, MIPI_HACTIVE_AREA_COUNT(port), + intel_de_write(display, MIPI_HACTIVE_AREA_COUNT(display, port), hactive); - intel_de_write(dev_priv, MIPI_HFP_COUNT(port), hfp); + intel_de_write(display, MIPI_HFP_COUNT(display, port), hfp); /* meaningful for video mode non-burst sync pulse mode only, * can be zero for non-burst sync events and burst modes */ - intel_de_write(dev_priv, MIPI_HSYNC_PADDING_COUNT(port), + intel_de_write(display, MIPI_HSYNC_PADDING_COUNT(display, port), hsync); - intel_de_write(dev_priv, MIPI_HBP_COUNT(port), hbp); + intel_de_write(display, MIPI_HBP_COUNT(display, port), hbp); /* vertical values are in terms of lines */ - intel_de_write(dev_priv, MIPI_VFP_COUNT(port), vfp); - intel_de_write(dev_priv, MIPI_VSYNC_PADDING_COUNT(port), + intel_de_write(display, MIPI_VFP_COUNT(display, port), vfp); + intel_de_write(display, MIPI_VSYNC_PADDING_COUNT(display, port), vsync); - intel_de_write(dev_priv, MIPI_VBP_COUNT(port), vbp); + intel_de_write(display, MIPI_VBP_COUNT(display, port), vbp); } } @@ -1299,21 +1301,20 @@ static u32 pixel_format_to_reg(enum mipi_dsi_pixel_format fmt) } } -static void intel_dsi_prepare(struct intel_encoder *intel_encoder, +static void intel_dsi_prepare(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config) { - struct drm_encoder *encoder = &intel_encoder->base; - struct drm_device *dev = encoder->dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); - struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(encoder)); + struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; enum port port; unsigned int bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format); u32 val, tmp; u16 mode_hdisplay; - drm_dbg_kms(&dev_priv->drm, "pipe %c\n", pipe_name(crtc->pipe)); + drm_dbg_kms(display->drm, "pipe %c\n", pipe_name(crtc->pipe)); mode_hdisplay = adjusted_mode->crtc_hdisplay; @@ -1329,31 +1330,31 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, * escape clock divider, 20MHz, shared for A and C. * device ready must be off when doing this! txclkesc? */ - tmp = intel_de_read(dev_priv, MIPI_CTRL(PORT_A)); + tmp = intel_de_read(display, MIPI_CTRL(display, PORT_A)); tmp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - intel_de_write(dev_priv, MIPI_CTRL(PORT_A), + intel_de_write(display, MIPI_CTRL(display, PORT_A), tmp | ESCAPE_CLOCK_DIVIDER_1); /* read request priority is per pipe */ - tmp = intel_de_read(dev_priv, MIPI_CTRL(port)); + tmp = intel_de_read(display, MIPI_CTRL(display, port)); tmp &= ~READ_REQUEST_PRIORITY_MASK; - intel_de_write(dev_priv, MIPI_CTRL(port), + intel_de_write(display, MIPI_CTRL(display, port), tmp | READ_REQUEST_PRIORITY_HIGH); } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { enum pipe pipe = crtc->pipe; - intel_de_rmw(dev_priv, MIPI_CTRL(port), + intel_de_rmw(display, MIPI_CTRL(display, port), BXT_PIPE_SELECT_MASK, BXT_PIPE_SELECT(pipe)); } /* XXX: why here, why like this? handling in irq handler?! */ - intel_de_write(dev_priv, MIPI_INTR_STAT(port), 0xffffffff); - intel_de_write(dev_priv, MIPI_INTR_EN(port), 0xffffffff); + intel_de_write(display, MIPI_INTR_STAT(display, port), 0xffffffff); + intel_de_write(display, MIPI_INTR_EN(display, port), 0xffffffff); - intel_de_write(dev_priv, MIPI_DPHY_PARAM(port), + intel_de_write(display, MIPI_DPHY_PARAM(display, port), intel_dsi->dphy_reg); - intel_de_write(dev_priv, MIPI_DPI_RESOLUTION(port), + intel_de_write(display, MIPI_DPI_RESOLUTION(display, port), adjusted_mode->crtc_vdisplay << VERTICAL_ADDRESS_SHIFT | mode_hdisplay << HORIZONTAL_ADDRESS_SHIFT); } @@ -1381,7 +1382,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, } for_each_dsi_port(port, intel_dsi->ports) { - intel_de_write(dev_priv, MIPI_DSI_FUNC_PRG(port), val); + intel_de_write(display, MIPI_DSI_FUNC_PRG(display, port), val); /* timeouts for recovery. one frame IIUC. if counter expires, * EOT and stop state. */ @@ -1402,23 +1403,23 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, if (is_vid_mode(intel_dsi) && intel_dsi->video_mode == BURST_MODE) { - intel_de_write(dev_priv, MIPI_HS_TX_TIMEOUT(port), + intel_de_write(display, MIPI_HS_TX_TIMEOUT(display, port), txbyteclkhs(adjusted_mode->crtc_htotal, bpp, intel_dsi->lane_count, intel_dsi->burst_mode_ratio) + 1); } else { - intel_de_write(dev_priv, MIPI_HS_TX_TIMEOUT(port), + intel_de_write(display, MIPI_HS_TX_TIMEOUT(display, port), txbyteclkhs(adjusted_mode->crtc_vtotal * adjusted_mode->crtc_htotal, bpp, intel_dsi->lane_count, intel_dsi->burst_mode_ratio) + 1); } - intel_de_write(dev_priv, MIPI_LP_RX_TIMEOUT(port), + intel_de_write(display, MIPI_LP_RX_TIMEOUT(display, port), intel_dsi->lp_rx_timeout); - intel_de_write(dev_priv, MIPI_TURN_AROUND_TIMEOUT(port), + intel_de_write(display, MIPI_TURN_AROUND_TIMEOUT(display, port), intel_dsi->turn_arnd_val); - intel_de_write(dev_priv, MIPI_DEVICE_RESET_TIMER(port), + intel_de_write(display, MIPI_DEVICE_RESET_TIMER(display, port), intel_dsi->rst_timer_val); /* dphy stuff */ /* in terms of low power clock */ - intel_de_write(dev_priv, MIPI_INIT_COUNT(port), + intel_de_write(display, MIPI_INIT_COUNT(display, port), txclkesc(intel_dsi->escape_clk_div, 100)); if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) && @@ -1429,16 +1430,16 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, * getting used. So write the other port * if not in dual link mode. */ - intel_de_write(dev_priv, - MIPI_INIT_COUNT(port == PORT_A ? PORT_C : PORT_A), + intel_de_write(display, + MIPI_INIT_COUNT(display, port == PORT_A ? PORT_C : PORT_A), intel_dsi->init_count); } /* recovery disables */ - intel_de_write(dev_priv, MIPI_EOT_DISABLE(port), tmp); + intel_de_write(display, MIPI_EOT_DISABLE(display, port), tmp); /* in terms of low power clock */ - intel_de_write(dev_priv, MIPI_INIT_COUNT(port), + intel_de_write(display, MIPI_INIT_COUNT(display, port), intel_dsi->init_count); /* in terms of txbyteclkhs. actual high to low switch + @@ -1446,7 +1447,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, * * XXX: write MIPI_STOP_STATE_STALL? */ - intel_de_write(dev_priv, MIPI_HIGH_LOW_SWITCH_COUNT(port), + intel_de_write(display, MIPI_HIGH_LOW_SWITCH_COUNT(display, port), intel_dsi->hs_to_lp_count); /* XXX: low power clock equivalence in terms of byte clock. @@ -1455,14 +1456,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, * txclkesc time / txbyteclk time * (105 + MIPI_STOP_STATE_STALL * ) / 105.??? */ - intel_de_write(dev_priv, MIPI_LP_BYTECLK(port), + intel_de_write(display, MIPI_LP_BYTECLK(display, port), intel_dsi->lp_byte_clk); if (IS_GEMINILAKE(dev_priv)) { - intel_de_write(dev_priv, MIPI_TLPX_TIME_COUNT(port), + intel_de_write(display, MIPI_TLPX_TIME_COUNT(display, port), intel_dsi->lp_byte_clk); /* Shadow of DPHY reg */ - intel_de_write(dev_priv, MIPI_CLK_LANE_TIMING(port), + intel_de_write(display, MIPI_CLK_LANE_TIMING(display, port), intel_dsi->dphy_reg); } @@ -1471,10 +1472,10 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, * this register in terms of byte clocks. based on dsi transfer * rate and the number of lanes configured the time taken to * transmit 16 long packets in a dsi stream varies. */ - intel_de_write(dev_priv, MIPI_DBI_BW_CTRL(port), + intel_de_write(display, MIPI_DBI_BW_CTRL(display, port), intel_dsi->bw_timer); - intel_de_write(dev_priv, MIPI_CLK_LANE_SWITCH_TIME_CNT(port), + intel_de_write(display, MIPI_CLK_LANE_SWITCH_TIME_CNT(display, port), intel_dsi->clk_lp_to_hs_count << LP_HS_SSW_CNT_SHIFT | intel_dsi->clk_hs_to_lp_count << HS_LP_PWR_SW_CNT_SHIFT); if (is_vid_mode(intel_dsi)) { @@ -1502,13 +1503,14 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, break; } - intel_de_write(dev_priv, MIPI_VIDEO_MODE_FORMAT(port), fmt); + intel_de_write(display, MIPI_VIDEO_MODE_FORMAT(display, port), fmt); } } } static void intel_dsi_unprepare(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); enum port port; @@ -1518,17 +1520,17 @@ static void intel_dsi_unprepare(struct intel_encoder *encoder) for_each_dsi_port(port, intel_dsi->ports) { /* Panel commands can be sent when clock is in LP11 */ - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), 0x0); + intel_de_write(display, MIPI_DEVICE_READY(display, port), 0x0); if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) bxt_dsi_reset_clocks(encoder, port); else vlv_dsi_reset_clocks(encoder, port); - intel_de_write(dev_priv, MIPI_EOT_DISABLE(port), CLOCKSTOP); + intel_de_write(display, MIPI_EOT_DISABLE(display, port), CLOCKSTOP); - intel_de_rmw(dev_priv, MIPI_DSI_FUNC_PRG(port), VID_MODE_FORMAT_MASK, 0); + intel_de_rmw(display, MIPI_DSI_FUNC_PRG(display, port), VID_MODE_FORMAT_MASK, 0); - intel_de_write(dev_priv, MIPI_DEVICE_READY(port), 0x1); + intel_de_write(display, MIPI_DEVICE_READY(display, port), 0x1); } } @@ -1592,8 +1594,7 @@ static void vlv_dsi_add_properties(struct intel_connector *connector) static void vlv_dphy_param_init(struct intel_dsi *intel_dsi) { - struct drm_device *dev = intel_dsi->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *dev_priv = to_i915(intel_dsi->base.base.dev); struct intel_connector *connector = intel_dsi->attached_connector; struct mipi_config *mipi_config = connector->panel.vbt.dsi.config; u32 tlpx_ns, extra_byte_count, tlpx_ui; @@ -1879,10 +1880,8 @@ static const struct dmi_system_id vlv_dsi_dmi_quirk_table[] = { void vlv_dsi_init(struct drm_i915_private *dev_priv) { struct intel_dsi *intel_dsi; - struct intel_encoder *intel_encoder; - struct drm_encoder *encoder; - struct intel_connector *intel_connector; - struct drm_connector *connector; + struct intel_encoder *encoder; + struct intel_connector *connector; struct drm_display_mode *current_mode; const struct dmi_system_id *dmi_id; enum port port; @@ -1903,64 +1902,61 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) if (!intel_dsi) return; - intel_connector = intel_connector_alloc(); - if (!intel_connector) { + connector = intel_connector_alloc(); + if (!connector) { kfree(intel_dsi); return; } - intel_encoder = &intel_dsi->base; - encoder = &intel_encoder->base; - intel_dsi->attached_connector = intel_connector; + encoder = &intel_dsi->base; + intel_dsi->attached_connector = connector; - connector = &intel_connector->base; + drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_dsi_funcs, + DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port)); - drm_encoder_init(&dev_priv->drm, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI, - "DSI %c", port_name(port)); - - intel_encoder->compute_config = intel_dsi_compute_config; - intel_encoder->pre_enable = intel_dsi_pre_enable; + encoder->compute_config = intel_dsi_compute_config; + encoder->pre_enable = intel_dsi_pre_enable; if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - intel_encoder->enable = bxt_dsi_enable; - intel_encoder->disable = intel_dsi_disable; - intel_encoder->post_disable = intel_dsi_post_disable; - intel_encoder->get_hw_state = intel_dsi_get_hw_state; - intel_encoder->get_config = intel_dsi_get_config; - intel_encoder->update_pipe = intel_backlight_update; - intel_encoder->shutdown = intel_dsi_shutdown; + encoder->enable = bxt_dsi_enable; + encoder->disable = intel_dsi_disable; + encoder->post_disable = intel_dsi_post_disable; + encoder->get_hw_state = intel_dsi_get_hw_state; + encoder->get_config = intel_dsi_get_config; + encoder->update_pipe = intel_backlight_update; + encoder->shutdown = intel_dsi_shutdown; - intel_connector->get_hw_state = intel_connector_get_hw_state; + connector->get_hw_state = intel_connector_get_hw_state; - intel_encoder->port = port; - intel_encoder->type = INTEL_OUTPUT_DSI; - intel_encoder->power_domain = POWER_DOMAIN_PORT_DSI; - intel_encoder->cloneable = 0; + encoder->port = port; + encoder->type = INTEL_OUTPUT_DSI; + encoder->power_domain = POWER_DOMAIN_PORT_DSI; + encoder->cloneable = 0; /* * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI * port C. BXT isn't limited like this. */ if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - intel_encoder->pipe_mask = ~0; + encoder->pipe_mask = ~0; else if (port == PORT_A) - intel_encoder->pipe_mask = BIT(PIPE_A); + encoder->pipe_mask = BIT(PIPE_A); else - intel_encoder->pipe_mask = BIT(PIPE_B); + encoder->pipe_mask = BIT(PIPE_B); intel_dsi->panel_power_off_time = ktime_get_boottime(); - intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL); + intel_bios_init_panel_late(dev_priv, &connector->panel, NULL, NULL); - if (intel_connector->panel.vbt.dsi.config->dual_link) + if (connector->panel.vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); else intel_dsi->ports = BIT(port); - if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) - intel_connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; + if (drm_WARN_ON(&dev_priv->drm, connector->panel.vbt.dsi.bl_ports & ~intel_dsi->ports)) + connector->panel.vbt.dsi.bl_ports &= intel_dsi->ports; - if (drm_WARN_ON(&dev_priv->drm, intel_connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) - intel_connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; + if (drm_WARN_ON(&dev_priv->drm, connector->panel.vbt.dsi.cabc_ports & ~intel_dsi->ports)) + connector->panel.vbt.dsi.cabc_ports &= intel_dsi->ports; /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { @@ -1980,7 +1976,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) } /* Use clock read-back from current hw-state for fastboot */ - current_mode = intel_encoder_current_mode(intel_encoder); + current_mode = intel_encoder_current_mode(encoder); if (current_mode) { drm_dbg_kms(&dev_priv->drm, "Calculated pclk %d GOP %d\n", intel_dsi->pclk, current_mode->clock); @@ -1996,22 +1992,22 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) vlv_dphy_param_init(intel_dsi); intel_dsi_vbt_gpio_init(intel_dsi, - intel_dsi_get_hw_state(intel_encoder, &pipe)); + intel_dsi_get_hw_state(encoder, &pipe)); - drm_connector_init(&dev_priv->drm, connector, &intel_dsi_connector_funcs, + drm_connector_init(&dev_priv->drm, &connector->base, &intel_dsi_connector_funcs, DRM_MODE_CONNECTOR_DSI); - drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs); + drm_connector_helper_add(&connector->base, &intel_dsi_connector_helper_funcs); - connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/ + connector->base.display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/ - intel_connector_attach_encoder(intel_connector, intel_encoder); + intel_connector_attach_encoder(connector, encoder); mutex_lock(&dev_priv->drm.mode_config.mutex); - intel_panel_add_vbt_lfp_fixed_mode(intel_connector); + intel_panel_add_vbt_lfp_fixed_mode(connector); mutex_unlock(&dev_priv->drm.mode_config.mutex); - if (!intel_panel_preferred_fixed_mode(intel_connector)) { + if (!intel_panel_preferred_fixed_mode(connector)) { drm_dbg_kms(&dev_priv->drm, "no fixed mode\n"); goto err_cleanup_connector; } @@ -2024,18 +2020,18 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) quirk_func(intel_dsi); } - intel_panel_init(intel_connector, NULL); + intel_panel_init(connector, NULL); - intel_backlight_setup(intel_connector, INVALID_PIPE); + intel_backlight_setup(connector, INVALID_PIPE); - vlv_dsi_add_properties(intel_connector); + vlv_dsi_add_properties(connector); return; err_cleanup_connector: - drm_connector_cleanup(&intel_connector->base); + drm_connector_cleanup(&connector->base); err: - drm_encoder_cleanup(&intel_encoder->base); + drm_encoder_cleanup(&encoder->base); kfree(intel_dsi); - kfree(intel_connector); + kfree(connector); } diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index ae0a0b11bae3..70c5a13a3c75 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -365,13 +365,13 @@ u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, void vlv_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) { - u32 temp; - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); + u32 temp; - temp = intel_de_read(dev_priv, MIPI_CTRL(port)); + temp = intel_de_read(display, MIPI_CTRL(display, port)); temp &= ~ESCAPE_CLOCK_DIVIDER_MASK; - intel_de_write(dev_priv, MIPI_CTRL(port), + intel_de_write(display, MIPI_CTRL(display, port), temp | intel_dsi->escape_clk_div << ESCAPE_CLOCK_DIVIDER_SHIFT); } @@ -570,24 +570,24 @@ void bxt_dsi_pll_enable(struct intel_encoder *encoder, void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) { + struct intel_display *display = to_intel_display(encoder); + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 tmp; - struct drm_device *dev = encoder->base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); /* Clear old configurations */ if (IS_BROXTON(dev_priv)) { - tmp = intel_de_read(dev_priv, BXT_MIPI_CLOCK_CTL); + tmp = intel_de_read(display, BXT_MIPI_CLOCK_CTL); tmp &= ~(BXT_MIPI_TX_ESCLK_FIXDIV_MASK(port)); tmp &= ~(BXT_MIPI_RX_ESCLK_UPPER_FIXDIV_MASK(port)); tmp &= ~(BXT_MIPI_8X_BY3_DIVIDER_MASK(port)); tmp &= ~(BXT_MIPI_RX_ESCLK_LOWER_FIXDIV_MASK(port)); - intel_de_write(dev_priv, BXT_MIPI_CLOCK_CTL, tmp); + intel_de_write(display, BXT_MIPI_CLOCK_CTL, tmp); } else { - intel_de_rmw(dev_priv, MIPIO_TXESC_CLK_DIV1, GLK_TX_ESC_CLK_DIV1_MASK, 0); + intel_de_rmw(display, MIPIO_TXESC_CLK_DIV1, GLK_TX_ESC_CLK_DIV1_MASK, 0); - intel_de_rmw(dev_priv, MIPIO_TXESC_CLK_DIV2, GLK_TX_ESC_CLK_DIV2_MASK, 0); + intel_de_rmw(display, MIPIO_TXESC_CLK_DIV2, GLK_TX_ESC_CLK_DIV2_MASK, 0); } - intel_de_write(dev_priv, MIPI_EOT_DISABLE(port), CLOCKSTOP); + intel_de_write(display, MIPI_EOT_DISABLE(display, port), CLOCKSTOP); } static void assert_dsi_pll(struct drm_i915_private *i915, bool state) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h index abbe427e462e..c1126d170ec6 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h +++ b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h @@ -11,26 +11,23 @@ #define VLV_MIPI_BASE VLV_DISPLAY_BASE #define BXT_MIPI_BASE 0x60000 -#define _MIPI_MMIO_BASE(__i915) ((__i915)->display.dsi.mmio_base) +#define _MIPI_MMIO_BASE(display) ((display)->dsi.mmio_base) #define _MIPI_PORT(port, a, c) (((port) == PORT_A) ? a : c) /* ports A and C only */ -#define _MMIO_MIPI(port, a, c) _MMIO(_MIPI_PORT(port, a, c)) +#define _MMIO_MIPI(base, port, a, c) _MMIO((base) + _MIPI_PORT(port, a, c)) /* BXT MIPI mode configure */ -#define _BXT_MIPIA_TRANS_HACTIVE 0x6B0F8 -#define _BXT_MIPIC_TRANS_HACTIVE 0x6B8F8 -#define BXT_MIPI_TRANS_HACTIVE(tc) _MMIO_MIPI(tc, \ - _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE) +#define _BXT_MIPIA_TRANS_HACTIVE 0xb0f8 +#define _BXT_MIPIC_TRANS_HACTIVE 0xb8f8 +#define BXT_MIPI_TRANS_HACTIVE(tc) _MMIO_MIPI(BXT_MIPI_BASE, tc, _BXT_MIPIA_TRANS_HACTIVE, _BXT_MIPIC_TRANS_HACTIVE) -#define _BXT_MIPIA_TRANS_VACTIVE 0x6B0FC -#define _BXT_MIPIC_TRANS_VACTIVE 0x6B8FC -#define BXT_MIPI_TRANS_VACTIVE(tc) _MMIO_MIPI(tc, \ - _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE) +#define _BXT_MIPIA_TRANS_VACTIVE 0xb0fc +#define _BXT_MIPIC_TRANS_VACTIVE 0xb8fc +#define BXT_MIPI_TRANS_VACTIVE(tc) _MMIO_MIPI(BXT_MIPI_BASE, tc, _BXT_MIPIA_TRANS_VACTIVE, _BXT_MIPIC_TRANS_VACTIVE) -#define _BXT_MIPIA_TRANS_VTOTAL 0x6B100 -#define _BXT_MIPIC_TRANS_VTOTAL 0x6B900 -#define BXT_MIPI_TRANS_VTOTAL(tc) _MMIO_MIPI(tc, \ - _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL) +#define _BXT_MIPIA_TRANS_VTOTAL 0xb100 +#define _BXT_MIPIC_TRANS_VTOTAL 0xb900 +#define BXT_MIPI_TRANS_VTOTAL(tc) _MMIO_MIPI(BXT_MIPI_BASE, tc, _BXT_MIPIA_TRANS_VTOTAL, _BXT_MIPIC_TRANS_VTOTAL) #define BXT_P_DSI_REGULATOR_CFG _MMIO(0x160020) #define STAP_SELECT (1 << 0) @@ -38,14 +35,14 @@ #define BXT_P_DSI_REGULATOR_TX_CTRL _MMIO(0x160054) #define HS_IO_CTRL_SELECT (1 << 0) -#define _MIPIA_PORT_CTRL (VLV_DISPLAY_BASE + 0x61190) -#define _MIPIC_PORT_CTRL (VLV_DISPLAY_BASE + 0x61700) -#define MIPI_PORT_CTRL(port) _MMIO_MIPI(port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) +#define _MIPIA_PORT_CTRL 0x61190 +#define _MIPIC_PORT_CTRL 0x61700 +#define VLV_MIPI_PORT_CTRL(port) _MMIO_MIPI(VLV_MIPI_BASE, port, _MIPIA_PORT_CTRL, _MIPIC_PORT_CTRL) /* BXT port control */ -#define _BXT_MIPIA_PORT_CTRL 0x6B0C0 -#define _BXT_MIPIC_PORT_CTRL 0x6B8C0 -#define BXT_MIPI_PORT_CTRL(tc) _MMIO_MIPI(tc, _BXT_MIPIA_PORT_CTRL, _BXT_MIPIC_PORT_CTRL) +#define _BXT_MIPIA_PORT_CTRL 0xb0c0 +#define _BXT_MIPIC_PORT_CTRL 0xb8c0 +#define BXT_MIPI_PORT_CTRL(tc) _MMIO_MIPI(BXT_MIPI_BASE, tc, _BXT_MIPIA_PORT_CTRL, _BXT_MIPIC_PORT_CTRL) #define DPI_ENABLE (1 << 31) /* A + C */ #define MIPIA_MIPI4DPHY_DELAY_COUNT_SHIFT 27 @@ -87,20 +84,17 @@ #define LANE_CONFIGURATION_DUAL_LINK_A (1 << 0) #define LANE_CONFIGURATION_DUAL_LINK_B (2 << 0) -#define _MIPIA_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61194) -#define _MIPIC_TEARING_CTRL (VLV_DISPLAY_BASE + 0x61704) -#define MIPI_TEARING_CTRL(port) _MMIO_MIPI(port, _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL) +#define _MIPIA_TEARING_CTRL 0x61194 +#define _MIPIC_TEARING_CTRL 0x61704 +#define VLV_MIPI_TEARING_CTRL(port) _MMIO_MIPI(VLV_MIPI_BASE, port, _MIPIA_TEARING_CTRL, _MIPIC_TEARING_CTRL) #define TEARING_EFFECT_DELAY_SHIFT 0 #define TEARING_EFFECT_DELAY_MASK (0xffff << 0) -/* XXX: all bits reserved */ -#define _MIPIA_AUTOPWG (VLV_DISPLAY_BASE + 0x611a0) - /* MIPI DSI Controller and D-PHY registers */ -#define _MIPIA_DEVICE_READY (_MIPI_MMIO_BASE(dev_priv) + 0xb000) -#define _MIPIC_DEVICE_READY (_MIPI_MMIO_BASE(dev_priv) + 0xb800) -#define MIPI_DEVICE_READY(port) _MMIO_MIPI(port, _MIPIA_DEVICE_READY, _MIPIC_DEVICE_READY) +#define _MIPIA_DEVICE_READY 0xb000 +#define _MIPIC_DEVICE_READY 0xb800 +#define MIPI_DEVICE_READY(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DEVICE_READY, _MIPIC_DEVICE_READY) #define BUS_POSSESSION (1 << 3) /* set to give bus to receiver */ #define ULPS_STATE_MASK (3 << 1) #define ULPS_STATE_ENTER (2 << 1) @@ -108,12 +102,12 @@ #define ULPS_STATE_NORMAL_OPERATION (0 << 1) #define DEVICE_READY (1 << 0) -#define _MIPIA_INTR_STAT (_MIPI_MMIO_BASE(dev_priv) + 0xb004) -#define _MIPIC_INTR_STAT (_MIPI_MMIO_BASE(dev_priv) + 0xb804) -#define MIPI_INTR_STAT(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT, _MIPIC_INTR_STAT) -#define _MIPIA_INTR_EN (_MIPI_MMIO_BASE(dev_priv) + 0xb008) -#define _MIPIC_INTR_EN (_MIPI_MMIO_BASE(dev_priv) + 0xb808) -#define MIPI_INTR_EN(port) _MMIO_MIPI(port, _MIPIA_INTR_EN, _MIPIC_INTR_EN) +#define _MIPIA_INTR_STAT 0xb004 +#define _MIPIC_INTR_STAT 0xb804 +#define MIPI_INTR_STAT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_INTR_STAT, _MIPIC_INTR_STAT) +#define _MIPIA_INTR_EN 0xb008 +#define _MIPIC_INTR_EN 0xb808 +#define MIPI_INTR_EN(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_INTR_EN, _MIPIC_INTR_EN) #define TEARING_EFFECT (1 << 31) #define SPL_PKT_SENT_INTERRUPT (1 << 30) #define GEN_READ_DATA_AVAIL (1 << 29) @@ -147,9 +141,9 @@ #define RXSOT_SYNC_ERROR (1 << 1) #define RXSOT_ERROR (1 << 0) -#define _MIPIA_DSI_FUNC_PRG (_MIPI_MMIO_BASE(dev_priv) + 0xb00c) -#define _MIPIC_DSI_FUNC_PRG (_MIPI_MMIO_BASE(dev_priv) + 0xb80c) -#define MIPI_DSI_FUNC_PRG(port) _MMIO_MIPI(port, _MIPIA_DSI_FUNC_PRG, _MIPIC_DSI_FUNC_PRG) +#define _MIPIA_DSI_FUNC_PRG 0xb00c +#define _MIPIC_DSI_FUNC_PRG 0xb80c +#define MIPI_DSI_FUNC_PRG(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DSI_FUNC_PRG, _MIPIC_DSI_FUNC_PRG) #define CMD_MODE_DATA_WIDTH_MASK (7 << 13) #define CMD_MODE_NOT_SUPPORTED (0 << 13) #define CMD_MODE_DATA_WIDTH_16_BIT (1 << 13) @@ -170,77 +164,77 @@ #define DATA_LANES_PRG_REG_SHIFT 0 #define DATA_LANES_PRG_REG_MASK (7 << 0) -#define _MIPIA_HS_TX_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb010) -#define _MIPIC_HS_TX_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb810) -#define MIPI_HS_TX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_HS_TX_TIMEOUT, _MIPIC_HS_TX_TIMEOUT) +#define _MIPIA_HS_TX_TIMEOUT 0xb010 +#define _MIPIC_HS_TX_TIMEOUT 0xb810 +#define MIPI_HS_TX_TIMEOUT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HS_TX_TIMEOUT, _MIPIC_HS_TX_TIMEOUT) #define HIGH_SPEED_TX_TIMEOUT_COUNTER_MASK 0xffffff -#define _MIPIA_LP_RX_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb014) -#define _MIPIC_LP_RX_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb814) -#define MIPI_LP_RX_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_LP_RX_TIMEOUT, _MIPIC_LP_RX_TIMEOUT) +#define _MIPIA_LP_RX_TIMEOUT 0xb014 +#define _MIPIC_LP_RX_TIMEOUT 0xb814 +#define MIPI_LP_RX_TIMEOUT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_LP_RX_TIMEOUT, _MIPIC_LP_RX_TIMEOUT) #define LOW_POWER_RX_TIMEOUT_COUNTER_MASK 0xffffff -#define _MIPIA_TURN_AROUND_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb018) -#define _MIPIC_TURN_AROUND_TIMEOUT (_MIPI_MMIO_BASE(dev_priv) + 0xb818) -#define MIPI_TURN_AROUND_TIMEOUT(port) _MMIO_MIPI(port, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT) +#define _MIPIA_TURN_AROUND_TIMEOUT 0xb018 +#define _MIPIC_TURN_AROUND_TIMEOUT 0xb818 +#define MIPI_TURN_AROUND_TIMEOUT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_TURN_AROUND_TIMEOUT, _MIPIC_TURN_AROUND_TIMEOUT) #define TURN_AROUND_TIMEOUT_MASK 0x3f -#define _MIPIA_DEVICE_RESET_TIMER (_MIPI_MMIO_BASE(dev_priv) + 0xb01c) -#define _MIPIC_DEVICE_RESET_TIMER (_MIPI_MMIO_BASE(dev_priv) + 0xb81c) -#define MIPI_DEVICE_RESET_TIMER(port) _MMIO_MIPI(port, _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER) +#define _MIPIA_DEVICE_RESET_TIMER 0xb01c +#define _MIPIC_DEVICE_RESET_TIMER 0xb81c +#define MIPI_DEVICE_RESET_TIMER(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DEVICE_RESET_TIMER, _MIPIC_DEVICE_RESET_TIMER) #define DEVICE_RESET_TIMER_MASK 0xffff -#define _MIPIA_DPI_RESOLUTION (_MIPI_MMIO_BASE(dev_priv) + 0xb020) -#define _MIPIC_DPI_RESOLUTION (_MIPI_MMIO_BASE(dev_priv) + 0xb820) -#define MIPI_DPI_RESOLUTION(port) _MMIO_MIPI(port, _MIPIA_DPI_RESOLUTION, _MIPIC_DPI_RESOLUTION) +#define _MIPIA_DPI_RESOLUTION 0xb020 +#define _MIPIC_DPI_RESOLUTION 0xb820 +#define MIPI_DPI_RESOLUTION(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DPI_RESOLUTION, _MIPIC_DPI_RESOLUTION) #define VERTICAL_ADDRESS_SHIFT 16 #define VERTICAL_ADDRESS_MASK (0xffff << 16) #define HORIZONTAL_ADDRESS_SHIFT 0 #define HORIZONTAL_ADDRESS_MASK 0xffff -#define _MIPIA_DBI_FIFO_THROTTLE (_MIPI_MMIO_BASE(dev_priv) + 0xb024) -#define _MIPIC_DBI_FIFO_THROTTLE (_MIPI_MMIO_BASE(dev_priv) + 0xb824) -#define MIPI_DBI_FIFO_THROTTLE(port) _MMIO_MIPI(port, _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE) +#define _MIPIA_DBI_FIFO_THROTTLE 0xb024 +#define _MIPIC_DBI_FIFO_THROTTLE 0xb824 +#define MIPI_DBI_FIFO_THROTTLE(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DBI_FIFO_THROTTLE, _MIPIC_DBI_FIFO_THROTTLE) #define DBI_FIFO_EMPTY_HALF (0 << 0) #define DBI_FIFO_EMPTY_QUARTER (1 << 0) #define DBI_FIFO_EMPTY_7_LOCATIONS (2 << 0) /* regs below are bits 15:0 */ -#define _MIPIA_HSYNC_PADDING_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb028) -#define _MIPIC_HSYNC_PADDING_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb828) -#define MIPI_HSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT) +#define _MIPIA_HSYNC_PADDING_COUNT 0xb028 +#define _MIPIC_HSYNC_PADDING_COUNT 0xb828 +#define MIPI_HSYNC_PADDING_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HSYNC_PADDING_COUNT, _MIPIC_HSYNC_PADDING_COUNT) -#define _MIPIA_HBP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb02c) -#define _MIPIC_HBP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb82c) -#define MIPI_HBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HBP_COUNT, _MIPIC_HBP_COUNT) +#define _MIPIA_HBP_COUNT 0xb02c +#define _MIPIC_HBP_COUNT 0xb82c +#define MIPI_HBP_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HBP_COUNT, _MIPIC_HBP_COUNT) -#define _MIPIA_HFP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb030) -#define _MIPIC_HFP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb830) -#define MIPI_HFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_HFP_COUNT, _MIPIC_HFP_COUNT) +#define _MIPIA_HFP_COUNT 0xb030 +#define _MIPIC_HFP_COUNT 0xb830 +#define MIPI_HFP_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HFP_COUNT, _MIPIC_HFP_COUNT) -#define _MIPIA_HACTIVE_AREA_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb034) -#define _MIPIC_HACTIVE_AREA_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb834) -#define MIPI_HACTIVE_AREA_COUNT(port) _MMIO_MIPI(port, _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT) +#define _MIPIA_HACTIVE_AREA_COUNT 0xb034 +#define _MIPIC_HACTIVE_AREA_COUNT 0xb834 +#define MIPI_HACTIVE_AREA_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HACTIVE_AREA_COUNT, _MIPIC_HACTIVE_AREA_COUNT) -#define _MIPIA_VSYNC_PADDING_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb038) -#define _MIPIC_VSYNC_PADDING_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb838) -#define MIPI_VSYNC_PADDING_COUNT(port) _MMIO_MIPI(port, _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT) +#define _MIPIA_VSYNC_PADDING_COUNT 0xb038 +#define _MIPIC_VSYNC_PADDING_COUNT 0xb838 +#define MIPI_VSYNC_PADDING_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_VSYNC_PADDING_COUNT, _MIPIC_VSYNC_PADDING_COUNT) -#define _MIPIA_VBP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb03c) -#define _MIPIC_VBP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb83c) -#define MIPI_VBP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VBP_COUNT, _MIPIC_VBP_COUNT) +#define _MIPIA_VBP_COUNT 0xb03c +#define _MIPIC_VBP_COUNT 0xb83c +#define MIPI_VBP_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_VBP_COUNT, _MIPIC_VBP_COUNT) -#define _MIPIA_VFP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb040) -#define _MIPIC_VFP_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb840) -#define MIPI_VFP_COUNT(port) _MMIO_MIPI(port, _MIPIA_VFP_COUNT, _MIPIC_VFP_COUNT) +#define _MIPIA_VFP_COUNT 0xb040 +#define _MIPIC_VFP_COUNT 0xb840 +#define MIPI_VFP_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_VFP_COUNT, _MIPIC_VFP_COUNT) -#define _MIPIA_HIGH_LOW_SWITCH_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb044) -#define _MIPIC_HIGH_LOW_SWITCH_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb844) -#define MIPI_HIGH_LOW_SWITCH_COUNT(port) _MMIO_MIPI(port, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT) +#define _MIPIA_HIGH_LOW_SWITCH_COUNT 0xb044 +#define _MIPIC_HIGH_LOW_SWITCH_COUNT 0xb844 +#define MIPI_HIGH_LOW_SWITCH_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HIGH_LOW_SWITCH_COUNT, _MIPIC_HIGH_LOW_SWITCH_COUNT) -#define _MIPIA_DPI_CONTROL (_MIPI_MMIO_BASE(dev_priv) + 0xb048) -#define _MIPIC_DPI_CONTROL (_MIPI_MMIO_BASE(dev_priv) + 0xb848) -#define MIPI_DPI_CONTROL(port) _MMIO_MIPI(port, _MIPIA_DPI_CONTROL, _MIPIC_DPI_CONTROL) +#define _MIPIA_DPI_CONTROL 0xb048 +#define _MIPIC_DPI_CONTROL 0xb848 +#define MIPI_DPI_CONTROL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DPI_CONTROL, _MIPIC_DPI_CONTROL) #define DPI_LP_MODE (1 << 6) #define BACKLIGHT_OFF (1 << 5) #define BACKLIGHT_ON (1 << 4) @@ -249,28 +243,27 @@ #define TURN_ON (1 << 1) #define SHUTDOWN (1 << 0) -#define _MIPIA_DPI_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb04c) -#define _MIPIC_DPI_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb84c) -#define MIPI_DPI_DATA(port) _MMIO_MIPI(port, _MIPIA_DPI_DATA, _MIPIC_DPI_DATA) +#define _MIPIA_DPI_DATA 0xb04c +#define _MIPIC_DPI_DATA 0xb84c +#define MIPI_DPI_DATA(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DPI_DATA, _MIPIC_DPI_DATA) #define COMMAND_BYTE_SHIFT 0 #define COMMAND_BYTE_MASK (0x3f << 0) -#define _MIPIA_INIT_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb050) -#define _MIPIC_INIT_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb850) -#define MIPI_INIT_COUNT(port) _MMIO_MIPI(port, _MIPIA_INIT_COUNT, _MIPIC_INIT_COUNT) +#define _MIPIA_INIT_COUNT 0xb050 +#define _MIPIC_INIT_COUNT 0xb850 +#define MIPI_INIT_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_INIT_COUNT, _MIPIC_INIT_COUNT) #define MASTER_INIT_TIMER_SHIFT 0 #define MASTER_INIT_TIMER_MASK (0xffff << 0) -#define _MIPIA_MAX_RETURN_PKT_SIZE (_MIPI_MMIO_BASE(dev_priv) + 0xb054) -#define _MIPIC_MAX_RETURN_PKT_SIZE (_MIPI_MMIO_BASE(dev_priv) + 0xb854) -#define MIPI_MAX_RETURN_PKT_SIZE(port) _MMIO_MIPI(port, \ - _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIC_MAX_RETURN_PKT_SIZE) +#define _MIPIA_MAX_RETURN_PKT_SIZE 0xb054 +#define _MIPIC_MAX_RETURN_PKT_SIZE 0xb854 +#define MIPI_MAX_RETURN_PKT_SIZE(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_MAX_RETURN_PKT_SIZE, _MIPIC_MAX_RETURN_PKT_SIZE) #define MAX_RETURN_PKT_SIZE_SHIFT 0 #define MAX_RETURN_PKT_SIZE_MASK (0x3ff << 0) -#define _MIPIA_VIDEO_MODE_FORMAT (_MIPI_MMIO_BASE(dev_priv) + 0xb058) -#define _MIPIC_VIDEO_MODE_FORMAT (_MIPI_MMIO_BASE(dev_priv) + 0xb858) -#define MIPI_VIDEO_MODE_FORMAT(port) _MMIO_MIPI(port, _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT) +#define _MIPIA_VIDEO_MODE_FORMAT 0xb058 +#define _MIPIC_VIDEO_MODE_FORMAT 0xb858 +#define MIPI_VIDEO_MODE_FORMAT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_VIDEO_MODE_FORMAT, _MIPIC_VIDEO_MODE_FORMAT) #define RANDOM_DPI_DISPLAY_RESOLUTION (1 << 4) #define DISABLE_VIDEO_BTA (1 << 3) #define IP_TG_CONFIG (1 << 2) @@ -278,9 +271,9 @@ #define VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS (2 << 0) #define VIDEO_MODE_BURST (3 << 0) -#define _MIPIA_EOT_DISABLE (_MIPI_MMIO_BASE(dev_priv) + 0xb05c) -#define _MIPIC_EOT_DISABLE (_MIPI_MMIO_BASE(dev_priv) + 0xb85c) -#define MIPI_EOT_DISABLE(port) _MMIO_MIPI(port, _MIPIA_EOT_DISABLE, _MIPIC_EOT_DISABLE) +#define _MIPIA_EOT_DISABLE 0xb05c +#define _MIPIC_EOT_DISABLE 0xb85c +#define MIPI_EOT_DISABLE(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_EOT_DISABLE, _MIPIC_EOT_DISABLE) #define BXT_DEFEATURE_DPI_FIFO_CTR (1 << 9) #define BXT_DPHY_DEFEATURE_EN (1 << 8) #define LP_RX_TIMEOUT_ERROR_RECOVERY_DISABLE (1 << 7) @@ -292,36 +285,36 @@ #define CLOCKSTOP (1 << 1) #define EOT_DISABLE (1 << 0) -#define _MIPIA_LP_BYTECLK (_MIPI_MMIO_BASE(dev_priv) + 0xb060) -#define _MIPIC_LP_BYTECLK (_MIPI_MMIO_BASE(dev_priv) + 0xb860) -#define MIPI_LP_BYTECLK(port) _MMIO_MIPI(port, _MIPIA_LP_BYTECLK, _MIPIC_LP_BYTECLK) +#define _MIPIA_LP_BYTECLK 0xb060 +#define _MIPIC_LP_BYTECLK 0xb860 +#define MIPI_LP_BYTECLK(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_LP_BYTECLK, _MIPIC_LP_BYTECLK) #define LP_BYTECLK_SHIFT 0 #define LP_BYTECLK_MASK (0xffff << 0) -#define _MIPIA_TLPX_TIME_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb0a4) -#define _MIPIC_TLPX_TIME_COUNT (_MIPI_MMIO_BASE(dev_priv) + 0xb8a4) -#define MIPI_TLPX_TIME_COUNT(port) _MMIO_MIPI(port, _MIPIA_TLPX_TIME_COUNT, _MIPIC_TLPX_TIME_COUNT) +#define _MIPIA_TLPX_TIME_COUNT 0xb0a4 +#define _MIPIC_TLPX_TIME_COUNT 0xb8a4 +#define MIPI_TLPX_TIME_COUNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_TLPX_TIME_COUNT, _MIPIC_TLPX_TIME_COUNT) -#define _MIPIA_CLK_LANE_TIMING (_MIPI_MMIO_BASE(dev_priv) + 0xb098) -#define _MIPIC_CLK_LANE_TIMING (_MIPI_MMIO_BASE(dev_priv) + 0xb898) -#define MIPI_CLK_LANE_TIMING(port) _MMIO_MIPI(port, _MIPIA_CLK_LANE_TIMING, _MIPIC_CLK_LANE_TIMING) +#define _MIPIA_CLK_LANE_TIMING 0xb098 +#define _MIPIC_CLK_LANE_TIMING 0xb898 +#define MIPI_CLK_LANE_TIMING(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_CLK_LANE_TIMING, _MIPIC_CLK_LANE_TIMING) /* bits 31:0 */ -#define _MIPIA_LP_GEN_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb064) -#define _MIPIC_LP_GEN_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb864) -#define MIPI_LP_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_DATA, _MIPIC_LP_GEN_DATA) +#define _MIPIA_LP_GEN_DATA 0xb064 +#define _MIPIC_LP_GEN_DATA 0xb864 +#define MIPI_LP_GEN_DATA(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_LP_GEN_DATA, _MIPIC_LP_GEN_DATA) /* bits 31:0 */ -#define _MIPIA_HS_GEN_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb068) -#define _MIPIC_HS_GEN_DATA (_MIPI_MMIO_BASE(dev_priv) + 0xb868) -#define MIPI_HS_GEN_DATA(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_DATA, _MIPIC_HS_GEN_DATA) +#define _MIPIA_HS_GEN_DATA 0xb068 +#define _MIPIC_HS_GEN_DATA 0xb868 +#define MIPI_HS_GEN_DATA(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HS_GEN_DATA, _MIPIC_HS_GEN_DATA) -#define _MIPIA_LP_GEN_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb06c) -#define _MIPIC_LP_GEN_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb86c) -#define MIPI_LP_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_LP_GEN_CTRL, _MIPIC_LP_GEN_CTRL) -#define _MIPIA_HS_GEN_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb070) -#define _MIPIC_HS_GEN_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb870) -#define MIPI_HS_GEN_CTRL(port) _MMIO_MIPI(port, _MIPIA_HS_GEN_CTRL, _MIPIC_HS_GEN_CTRL) +#define _MIPIA_LP_GEN_CTRL 0xb06c +#define _MIPIC_LP_GEN_CTRL 0xb86c +#define MIPI_LP_GEN_CTRL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_LP_GEN_CTRL, _MIPIC_LP_GEN_CTRL) +#define _MIPIA_HS_GEN_CTRL 0xb070 +#define _MIPIC_HS_GEN_CTRL 0xb870 +#define MIPI_HS_GEN_CTRL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HS_GEN_CTRL, _MIPIC_HS_GEN_CTRL) #define LONG_PACKET_WORD_COUNT_SHIFT 8 #define LONG_PACKET_WORD_COUNT_MASK (0xffff << 8) #define SHORT_PACKET_PARAM_SHIFT 8 @@ -332,9 +325,9 @@ #define DATA_TYPE_MASK (0x3f << 0) /* data type values, see include/video/mipi_display.h */ -#define _MIPIA_GEN_FIFO_STAT (_MIPI_MMIO_BASE(dev_priv) + 0xb074) -#define _MIPIC_GEN_FIFO_STAT (_MIPI_MMIO_BASE(dev_priv) + 0xb874) -#define MIPI_GEN_FIFO_STAT(port) _MMIO_MIPI(port, _MIPIA_GEN_FIFO_STAT, _MIPIC_GEN_FIFO_STAT) +#define _MIPIA_GEN_FIFO_STAT 0xb074 +#define _MIPIC_GEN_FIFO_STAT 0xb874 +#define MIPI_GEN_FIFO_STAT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_GEN_FIFO_STAT, _MIPIC_GEN_FIFO_STAT) #define DPI_FIFO_EMPTY (1 << 28) #define DBI_FIFO_EMPTY (1 << 27) #define LP_CTRL_FIFO_EMPTY (1 << 26) @@ -350,16 +343,16 @@ #define HS_DATA_FIFO_HALF_EMPTY (1 << 1) #define HS_DATA_FIFO_FULL (1 << 0) -#define _MIPIA_HS_LS_DBI_ENABLE (_MIPI_MMIO_BASE(dev_priv) + 0xb078) -#define _MIPIC_HS_LS_DBI_ENABLE (_MIPI_MMIO_BASE(dev_priv) + 0xb878) -#define MIPI_HS_LP_DBI_ENABLE(port) _MMIO_MIPI(port, _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE) +#define _MIPIA_HS_LS_DBI_ENABLE 0xb078 +#define _MIPIC_HS_LS_DBI_ENABLE 0xb878 +#define MIPI_HS_LP_DBI_ENABLE(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_HS_LS_DBI_ENABLE, _MIPIC_HS_LS_DBI_ENABLE) #define DBI_HS_LP_MODE_MASK (1 << 0) #define DBI_LP_MODE (1 << 0) #define DBI_HS_MODE (0 << 0) -#define _MIPIA_DPHY_PARAM (_MIPI_MMIO_BASE(dev_priv) + 0xb080) -#define _MIPIC_DPHY_PARAM (_MIPI_MMIO_BASE(dev_priv) + 0xb880) -#define MIPI_DPHY_PARAM(port) _MMIO_MIPI(port, _MIPIA_DPHY_PARAM, _MIPIC_DPHY_PARAM) +#define _MIPIA_DPHY_PARAM 0xb080 +#define _MIPIC_DPHY_PARAM 0xb880 +#define MIPI_DPHY_PARAM(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DPHY_PARAM, _MIPIC_DPHY_PARAM) #define EXIT_ZERO_COUNT_SHIFT 24 #define EXIT_ZERO_COUNT_MASK (0x3f << 24) #define TRAIL_COUNT_SHIFT 16 @@ -369,34 +362,34 @@ #define PREPARE_COUNT_SHIFT 0 #define PREPARE_COUNT_MASK (0x3f << 0) -#define _MIPIA_DBI_BW_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb084) -#define _MIPIC_DBI_BW_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb884) -#define MIPI_DBI_BW_CTRL(port) _MMIO_MIPI(port, _MIPIA_DBI_BW_CTRL, _MIPIC_DBI_BW_CTRL) +#define _MIPIA_DBI_BW_CTRL 0xb084 +#define _MIPIC_DBI_BW_CTRL 0xb884 +#define MIPI_DBI_BW_CTRL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DBI_BW_CTRL, _MIPIC_DBI_BW_CTRL) -#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT (_MIPI_MMIO_BASE(dev_priv) + 0xb088) -#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT (_MIPI_MMIO_BASE(dev_priv) + 0xb888) -#define MIPI_CLK_LANE_SWITCH_TIME_CNT(port) _MMIO_MIPI(port, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT) +#define _MIPIA_CLK_LANE_SWITCH_TIME_CNT 0xb088 +#define _MIPIC_CLK_LANE_SWITCH_TIME_CNT 0xb888 +#define MIPI_CLK_LANE_SWITCH_TIME_CNT(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_CLK_LANE_SWITCH_TIME_CNT, _MIPIC_CLK_LANE_SWITCH_TIME_CNT) #define LP_HS_SSW_CNT_SHIFT 16 #define LP_HS_SSW_CNT_MASK (0xffff << 16) #define HS_LP_PWR_SW_CNT_SHIFT 0 #define HS_LP_PWR_SW_CNT_MASK (0xffff << 0) -#define _MIPIA_STOP_STATE_STALL (_MIPI_MMIO_BASE(dev_priv) + 0xb08c) -#define _MIPIC_STOP_STATE_STALL (_MIPI_MMIO_BASE(dev_priv) + 0xb88c) -#define MIPI_STOP_STATE_STALL(port) _MMIO_MIPI(port, _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL) +#define _MIPIA_STOP_STATE_STALL 0xb08c +#define _MIPIC_STOP_STATE_STALL 0xb88c +#define MIPI_STOP_STATE_STALL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_STOP_STATE_STALL, _MIPIC_STOP_STATE_STALL) #define STOP_STATE_STALL_COUNTER_SHIFT 0 #define STOP_STATE_STALL_COUNTER_MASK (0xff << 0) -#define _MIPIA_INTR_STAT_REG_1 (_MIPI_MMIO_BASE(dev_priv) + 0xb090) -#define _MIPIC_INTR_STAT_REG_1 (_MIPI_MMIO_BASE(dev_priv) + 0xb890) -#define MIPI_INTR_STAT_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1) -#define _MIPIA_INTR_EN_REG_1 (_MIPI_MMIO_BASE(dev_priv) + 0xb094) -#define _MIPIC_INTR_EN_REG_1 (_MIPI_MMIO_BASE(dev_priv) + 0xb894) -#define MIPI_INTR_EN_REG_1(port) _MMIO_MIPI(port, _MIPIA_INTR_EN_REG_1, _MIPIC_INTR_EN_REG_1) +#define _MIPIA_INTR_STAT_REG_1 0xb090 +#define _MIPIC_INTR_STAT_REG_1 0xb890 +#define MIPI_INTR_STAT_REG_1(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_INTR_STAT_REG_1, _MIPIC_INTR_STAT_REG_1) +#define _MIPIA_INTR_EN_REG_1 0xb094 +#define _MIPIC_INTR_EN_REG_1 0xb894 +#define MIPI_INTR_EN_REG_1(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_INTR_EN_REG_1, _MIPIC_INTR_EN_REG_1) #define RX_CONTENTION_DETECTED (1 << 0) /* XXX: only pipe A ?!? */ -#define MIPIA_DBI_TYPEC_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb100) +#define MIPIA_DBI_TYPEC_CTRL(display) (_MIPI_MMIO_BASE(display) + 0xb100) #define DBI_TYPEC_ENABLE (1 << 31) #define DBI_TYPEC_WIP (1 << 30) #define DBI_TYPEC_OPTION_SHIFT 28 @@ -409,9 +402,9 @@ /* MIPI adapter registers */ -#define _MIPIA_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb104) -#define _MIPIC_CTRL (_MIPI_MMIO_BASE(dev_priv) + 0xb904) -#define MIPI_CTRL(port) _MMIO_MIPI(port, _MIPIA_CTRL, _MIPIC_CTRL) +#define _MIPIA_CTRL 0xb104 +#define _MIPIC_CTRL 0xb904 +#define MIPI_CTRL(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_CTRL, _MIPIC_CTRL) #define ESCAPE_CLOCK_DIVIDER_SHIFT 5 /* A only */ #define ESCAPE_CLOCK_DIVIDER_MASK (3 << 5) #define ESCAPE_CLOCK_DIVIDER_1 (0 << 5) @@ -442,41 +435,41 @@ #define GLK_MIPIIO_PORT_POWERED (1 << 1) /* RO */ #define GLK_MIPIIO_ENABLE (1 << 0) -#define _MIPIA_DATA_ADDRESS (_MIPI_MMIO_BASE(dev_priv) + 0xb108) -#define _MIPIC_DATA_ADDRESS (_MIPI_MMIO_BASE(dev_priv) + 0xb908) -#define MIPI_DATA_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_DATA_ADDRESS, _MIPIC_DATA_ADDRESS) +#define _MIPIA_DATA_ADDRESS 0xb108 +#define _MIPIC_DATA_ADDRESS 0xb908 +#define MIPI_DATA_ADDRESS(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DATA_ADDRESS, _MIPIC_DATA_ADDRESS) #define DATA_MEM_ADDRESS_SHIFT 5 #define DATA_MEM_ADDRESS_MASK (0x7ffffff << 5) #define DATA_VALID (1 << 0) -#define _MIPIA_DATA_LENGTH (_MIPI_MMIO_BASE(dev_priv) + 0xb10c) -#define _MIPIC_DATA_LENGTH (_MIPI_MMIO_BASE(dev_priv) + 0xb90c) -#define MIPI_DATA_LENGTH(port) _MMIO_MIPI(port, _MIPIA_DATA_LENGTH, _MIPIC_DATA_LENGTH) +#define _MIPIA_DATA_LENGTH 0xb10c +#define _MIPIC_DATA_LENGTH 0xb90c +#define MIPI_DATA_LENGTH(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_DATA_LENGTH, _MIPIC_DATA_LENGTH) #define DATA_LENGTH_SHIFT 0 #define DATA_LENGTH_MASK (0xfffff << 0) -#define _MIPIA_COMMAND_ADDRESS (_MIPI_MMIO_BASE(dev_priv) + 0xb110) -#define _MIPIC_COMMAND_ADDRESS (_MIPI_MMIO_BASE(dev_priv) + 0xb910) -#define MIPI_COMMAND_ADDRESS(port) _MMIO_MIPI(port, _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS) +#define _MIPIA_COMMAND_ADDRESS 0xb110 +#define _MIPIC_COMMAND_ADDRESS 0xb910 +#define MIPI_COMMAND_ADDRESS(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_COMMAND_ADDRESS, _MIPIC_COMMAND_ADDRESS) #define COMMAND_MEM_ADDRESS_SHIFT 5 #define COMMAND_MEM_ADDRESS_MASK (0x7ffffff << 5) #define AUTO_PWG_ENABLE (1 << 2) #define MEMORY_WRITE_DATA_FROM_PIPE_RENDERING (1 << 1) #define COMMAND_VALID (1 << 0) -#define _MIPIA_COMMAND_LENGTH (_MIPI_MMIO_BASE(dev_priv) + 0xb114) -#define _MIPIC_COMMAND_LENGTH (_MIPI_MMIO_BASE(dev_priv) + 0xb914) -#define MIPI_COMMAND_LENGTH(port) _MMIO_MIPI(port, _MIPIA_COMMAND_LENGTH, _MIPIC_COMMAND_LENGTH) +#define _MIPIA_COMMAND_LENGTH 0xb114 +#define _MIPIC_COMMAND_LENGTH 0xb914 +#define MIPI_COMMAND_LENGTH(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_COMMAND_LENGTH, _MIPIC_COMMAND_LENGTH) #define COMMAND_LENGTH_SHIFT(n) (8 * (n)) /* n: 0...3 */ #define COMMAND_LENGTH_MASK(n) (0xff << (8 * (n))) -#define _MIPIA_READ_DATA_RETURN0 (_MIPI_MMIO_BASE(dev_priv) + 0xb118) -#define _MIPIC_READ_DATA_RETURN0 (_MIPI_MMIO_BASE(dev_priv) + 0xb918) -#define MIPI_READ_DATA_RETURN(port, n) _MMIO(_MIPI(port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) + 4 * (n)) /* n: 0...7 */ +#define _MIPIA_READ_DATA_RETURN0 0xb118 +#define _MIPIC_READ_DATA_RETURN0 0xb918 +#define MIPI_READ_DATA_RETURN(display, port, n) _MMIO_MIPI(_MIPI_MMIO_BASE(display) + 4 * (n), port, _MIPIA_READ_DATA_RETURN0, _MIPIC_READ_DATA_RETURN0) /* n: 0...7 */ -#define _MIPIA_READ_DATA_VALID (_MIPI_MMIO_BASE(dev_priv) + 0xb138) -#define _MIPIC_READ_DATA_VALID (_MIPI_MMIO_BASE(dev_priv) + 0xb938) -#define MIPI_READ_DATA_VALID(port) _MMIO_MIPI(port, _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID) +#define _MIPIA_READ_DATA_VALID 0xb138 +#define _MIPIC_READ_DATA_VALID 0xb938 +#define MIPI_READ_DATA_VALID(display, port) _MMIO_MIPI(_MIPI_MMIO_BASE(display), port, _MIPIA_READ_DATA_VALID, _MIPIC_READ_DATA_VALID) #define READ_DATA_VALID(n) (1 << (n)) #endif /* __VLV_DSI_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index dcbfe32fd30c..81f65cab1330 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -879,6 +879,7 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, struct i915_gem_proto_context *pc, struct drm_i915_gem_context_param *args) { + struct drm_i915_private *i915 = fpriv->i915; int ret = 0; switch (args->param) { @@ -904,6 +905,13 @@ static int set_proto_ctx_param(struct drm_i915_file_private *fpriv, pc->user_flags &= ~BIT(UCONTEXT_BANNABLE); break; + case I915_CONTEXT_PARAM_LOW_LATENCY: + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + pc->user_flags |= BIT(UCONTEXT_LOW_LATENCY); + else + ret = -EINVAL; + break; + case I915_CONTEXT_PARAM_RECOVERABLE: if (args->size) ret = -EINVAL; @@ -992,6 +1000,9 @@ static int intel_context_set_gem(struct intel_context *ce, if (sseu.slice_mask && !WARN_ON(ce->engine->class != RENDER_CLASS)) ret = intel_context_reconfigure_sseu(ce, sseu); + if (test_bit(UCONTEXT_LOW_LATENCY, &ctx->user_flags)) + __set_bit(CONTEXT_LOW_LATENCY, &ce->flags); + return ret; } @@ -1630,6 +1641,9 @@ i915_gem_create_context(struct drm_i915_private *i915, if (vm) ctx->vm = vm; + /* Assign early so intel_context_set_gem can access these flags */ + ctx->user_flags = pc->user_flags; + mutex_init(&ctx->engines_mutex); if (pc->num_user_engines >= 0) { i915_gem_context_set_user_engines(ctx); @@ -1652,8 +1666,6 @@ i915_gem_create_context(struct drm_i915_private *i915, * is no remap info, it will be a NOP. */ ctx->remap_slice = ALL_L3_SLICES(i915); - ctx->user_flags = pc->user_flags; - for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h index 03bc7f9d191b..b6d97da63d1f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h @@ -338,6 +338,7 @@ struct i915_gem_context { #define UCONTEXT_BANNABLE 2 #define UCONTEXT_RECOVERABLE 3 #define UCONTEXT_PERSISTENCE 4 +#define UCONTEXT_LOW_LATENCY 5 /** * @flags: small set of booleans diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index d3a771afb083..42619fc05de4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -255,7 +255,6 @@ struct i915_execbuffer { struct intel_context *context; /* logical state for the request */ struct i915_gem_context *gem_context; /** caller's context */ intel_wakeref_t wakeref; - intel_wakeref_t wakeref_gt0; /** our requests to build */ struct i915_request *requests[MAX_ENGINE_INSTANCE + 1]; @@ -2457,7 +2456,7 @@ static int eb_submit(struct i915_execbuffer *eb) * The engine index is returned. */ static unsigned int -gen8_dispatch_bsd_engine(struct drm_i915_private *dev_priv, +gen8_dispatch_bsd_engine(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; @@ -2465,7 +2464,7 @@ gen8_dispatch_bsd_engine(struct drm_i915_private *dev_priv, /* Check whether the file_priv has already selected one ring. */ if ((int)file_priv->bsd_engine < 0) file_priv->bsd_engine = - get_random_u32_below(dev_priv->engine_uabi_class_count[I915_ENGINE_CLASS_VIDEO]); + get_random_u32_below(i915->engine_uabi_class_count[I915_ENGINE_CLASS_VIDEO]); return file_priv->bsd_engine; } @@ -2686,7 +2685,6 @@ static int eb_select_engine(struct i915_execbuffer *eb) { struct intel_context *ce, *child; - struct intel_gt *gt; unsigned int idx; int err; @@ -2710,17 +2708,10 @@ eb_select_engine(struct i915_execbuffer *eb) } } eb->num_batches = ce->parallel.number_children + 1; - gt = ce->engine->gt; for_each_child(ce, child) intel_context_get(child); eb->wakeref = intel_gt_pm_get(ce->engine->gt); - /* - * Keep GT0 active on MTL so that i915_vma_parked() doesn't - * free VMAs while execbuf ioctl is validating VMAs. - */ - if (gt->info.id) - eb->wakeref_gt0 = intel_gt_pm_get(to_gt(gt->i915)); if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { err = intel_context_alloc_state(ce); @@ -2759,9 +2750,6 @@ eb_select_engine(struct i915_execbuffer *eb) return err; err: - if (gt->info.id) - intel_gt_pm_put(to_gt(gt->i915), eb->wakeref_gt0); - intel_gt_pm_put(ce->engine->gt, eb->wakeref); for_each_child(ce, child) intel_context_put(child); @@ -2775,12 +2763,6 @@ eb_put_engine(struct i915_execbuffer *eb) struct intel_context *child; i915_vm_put(eb->context->vm); - /* - * This works in conjunction with eb_select_engine() to prevent - * i915_vma_parked() from interfering while execbuf validates vmas. - */ - if (eb->gt->info.id) - intel_gt_pm_put(to_gt(eb->gt->i915), eb->wakeref_gt0); intel_gt_pm_put(eb->context->engine->gt, eb->wakeref); for_each_child(eb->context, child) intel_context_put(child); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 0c5cdab278b6..1495b6074492 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -386,7 +386,7 @@ struct drm_i915_gem_object { * and kernel mode driver for caching policy control after GEN12. * In the meantime platform specific tables are created to translate * i915_cache_level into pat index, for more details check the macros - * defined i915/i915_pci.c, e.g. PVC_CACHELEVEL. + * defined i915/i915_pci.c, e.g. TGL_CACHELEVEL. * For backward compatibility, this field contains values exactly match * the entries of enum i915_cache_level for pre-GEN12 platforms (See * LEGACY_CACHELEVEL), so that the PTE encode functions for these diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 38b72d86560f..c5e1c718a6d2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -654,7 +654,7 @@ i915_gem_object_create_shmem(struct drm_i915_private *i915, /* Allocate a new GEM object and fill it with the supplied data */ struct drm_i915_gem_object * -i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv, +i915_gem_object_create_shmem_from_data(struct drm_i915_private *i915, const void *data, resource_size_t size) { struct drm_i915_gem_object *obj; @@ -663,8 +663,8 @@ i915_gem_object_create_shmem_from_data(struct drm_i915_private *dev_priv, resource_size_t offset; int err; - GEM_WARN_ON(IS_DGFX(dev_priv)); - obj = i915_gem_object_create_shmem(dev_priv, round_up(size, PAGE_SIZE)); + GEM_WARN_ON(IS_DGFX(i915)); + obj = i915_gem_object_create_shmem(i915, round_up(size, PAGE_SIZE)); if (IS_ERR(obj)) return obj; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h index 258381d1c054..dfe0db8bb1b9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h @@ -14,14 +14,14 @@ struct drm_i915_gem_object; #define i915_stolen_fb drm_mm_node -int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv, +int i915_gem_stolen_insert_node(struct drm_i915_private *i915, struct drm_mm_node *node, u64 size, unsigned alignment); -int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, +int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *i915, struct drm_mm_node *node, u64 size, unsigned alignment, u64 start, u64 end); -void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, +void i915_gem_stolen_remove_node(struct drm_i915_private *i915, struct drm_mm_node *node); struct intel_memory_region * i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type, @@ -31,7 +31,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, u16 instance); struct drm_i915_gem_object * -i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, +i915_gem_object_create_stolen(struct drm_i915_private *i915, resource_size_t size); bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index a049ca0b7980..d9eb84c1d2f1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -343,12 +343,12 @@ int i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_set_tiling *args = data; struct drm_i915_gem_object *obj; int err; - if (!to_gt(dev_priv)->ggtt->num_fences) + if (!to_gt(i915)->ggtt->num_fences) return -EOPNOTSUPP; obj = i915_gem_object_lookup(file, args->handle); @@ -374,9 +374,9 @@ i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data, args->stride = 0; } else { if (args->tiling_mode == I915_TILING_X) - args->swizzle_mode = to_gt(dev_priv)->ggtt->bit_6_swizzle_x; + args->swizzle_mode = to_gt(i915)->ggtt->bit_6_swizzle_x; else - args->swizzle_mode = to_gt(dev_priv)->ggtt->bit_6_swizzle_y; + args->swizzle_mode = to_gt(i915)->ggtt->bit_6_swizzle_y; /* Hide bit 17 swizzling from the user. This prevents old Mesa * from aborting the application on sw fallbacks to bit 17, @@ -427,11 +427,11 @@ i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_gem_get_tiling *args = data; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_object *obj; int err = -ENOENT; - if (!to_gt(dev_priv)->ggtt->num_fences) + if (!to_gt(i915)->ggtt->num_fences) return -EOPNOTSUPP; rcu_read_lock(); @@ -447,10 +447,10 @@ i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data, switch (args->tiling_mode) { case I915_TILING_X: - args->swizzle_mode = to_gt(dev_priv)->ggtt->bit_6_swizzle_x; + args->swizzle_mode = to_gt(i915)->ggtt->bit_6_swizzle_x; break; case I915_TILING_Y: - args->swizzle_mode = to_gt(dev_priv)->ggtt->bit_6_swizzle_y; + args->swizzle_mode = to_gt(i915)->ggtt->bit_6_swizzle_y; break; default: case I915_TILING_NONE: @@ -459,7 +459,7 @@ i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data, } /* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */ - if (dev_priv->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) + if (i915->gem_quirks & GEM_QUIRK_PIN_SWIZZLED_PAGES) args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN; else args->phys_swizzle_mode = args->swizzle_mode; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index 61abfb505766..09b68713ab32 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -463,13 +463,13 @@ i915_gem_userptr_ioctl(struct drm_device *dev, struct drm_file *file) { static struct lock_class_key __maybe_unused lock_class; - struct drm_i915_private *dev_priv = to_i915(dev); + struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_userptr *args = data; struct drm_i915_gem_object __maybe_unused *obj; int __maybe_unused ret; u32 __maybe_unused handle; - if (!HAS_LLC(dev_priv) && !HAS_SNOOP(dev_priv)) { + if (!HAS_LLC(i915) && !HAS_SNOOP(i915)) { /* We cannot support coherent userptr objects on hw without * LLC and broken snooping. */ @@ -501,7 +501,7 @@ i915_gem_userptr_ioctl(struct drm_device *dev, * On almost all of the older hw, we cannot tell the GPU that * a page is readonly. */ - if (!to_gt(dev_priv)->vm->has_read_only) + if (!to_gt(i915)->vm->has_read_only) return -ENODEV; } diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 3ff3d8889c6c..84d41e6ccf05 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -713,7 +713,7 @@ static int igt_ppgtt_huge_fill(void *arg) { struct drm_i915_private *i915 = arg; unsigned int supported = RUNTIME_INFO(i915)->page_sizes; - bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50); + bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55); struct i915_address_space *vm; struct i915_gem_context *ctx; unsigned long max_pages; @@ -857,7 +857,7 @@ static int igt_ppgtt_huge_fill(void *arg) static int igt_ppgtt_64K(void *arg) { struct drm_i915_private *i915 = arg; - bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50); + bool has_pte64 = GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55); struct drm_i915_gem_object *obj; struct i915_address_space *vm; struct i915_gem_context *ctx; @@ -1969,19 +1969,19 @@ int i915_gem_huge_page_mock_selftests(void) SUBTEST(igt_mock_memory_region_huge_pages), SUBTEST(igt_mock_ppgtt_misaligned_dma), }; - struct drm_i915_private *dev_priv; + struct drm_i915_private *i915; struct i915_ppgtt *ppgtt; int err; - dev_priv = mock_gem_device(); - if (!dev_priv) + i915 = mock_gem_device(); + if (!i915) return -ENOMEM; /* Pretend to be a device which supports the 48b PPGTT */ - RUNTIME_INFO(dev_priv)->ppgtt_type = INTEL_PPGTT_FULL; - RUNTIME_INFO(dev_priv)->ppgtt_size = 48; + RUNTIME_INFO(i915)->ppgtt_type = INTEL_PPGTT_FULL; + RUNTIME_INFO(i915)->ppgtt_size = 48; - ppgtt = i915_ppgtt_create(to_gt(dev_priv), 0); + ppgtt = i915_ppgtt_create(to_gt(i915), 0); if (IS_ERR(ppgtt)) { err = PTR_ERR(ppgtt); goto out_unlock; @@ -2005,7 +2005,7 @@ int i915_gem_huge_page_mock_selftests(void) out_put: i915_vm_put(&ppgtt->vm); out_unlock: - mock_destroy_device(dev_priv); + mock_destroy_device(i915); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index 10a7847f1b04..bac15196b4d2 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -117,7 +117,7 @@ static bool fastblit_supports_x_tiling(const struct drm_i915_private *i915) if (gen < 12) return true; - if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) return false; return HAS_DISPLAY(i915); @@ -166,7 +166,7 @@ static int prepare_blit(const struct tiled_blits *t, src_pitch = t->width; /* in dwords */ if (src->tiling == CLIENT_TILING_Y) { src_tiles = XY_FAST_COPY_BLT_D0_SRC_TILE_MODE(YMAJOR); - if (GRAPHICS_VER_FULL(to_i915(batch->base.dev)) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(to_i915(batch->base.dev)) >= IP_VER(12, 55)) src_4t = XY_FAST_COPY_BLT_D1_SRC_TILE4; } else if (src->tiling == CLIENT_TILING_X) { src_tiles = XY_FAST_COPY_BLT_D0_SRC_TILE_MODE(TILE_X); @@ -177,7 +177,7 @@ static int prepare_blit(const struct tiled_blits *t, dst_pitch = t->width; /* in dwords */ if (dst->tiling == CLIENT_TILING_Y) { dst_tiles = XY_FAST_COPY_BLT_D0_DST_TILE_MODE(YMAJOR); - if (GRAPHICS_VER_FULL(to_i915(batch->base.dev)) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(to_i915(batch->base.dev)) >= IP_VER(12, 55)) dst_4t = XY_FAST_COPY_BLT_D1_DST_TILE4; } else if (dst->tiling == CLIENT_TILING_X) { dst_tiles = XY_FAST_COPY_BLT_D0_DST_TILE_MODE(TILE_X); @@ -365,7 +365,7 @@ static u64 tiled_offset(const struct intel_gt *gt, v += x; swizzle = gt->ggtt->bit_6_swizzle_x; - } else if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50)) { + } else if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55)) { /* Y-major tiling layout is Tile4 for Xe_HP and beyond */ v = linear_x_y_to_ftiled_pos(x_pos, y_pos, stride, 32); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index d684a70f2c04..65a931ea80e9 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -7,6 +7,7 @@ #include "i915_drv.h" #include "i915_selftest.h" #include "gem/i915_gem_context.h" +#include "gt/intel_gt.h" #include "mock_context.h" #include "mock_dmabuf.h" @@ -155,6 +156,7 @@ static int verify_access(struct drm_i915_private *i915, struct file *file; u32 *vaddr; int err = 0, i; + unsigned int mode; file = mock_file(i915); if (IS_ERR(file)) @@ -194,7 +196,8 @@ static int verify_access(struct drm_i915_private *i915, if (err) goto out_file; - vaddr = i915_gem_object_pin_map_unlocked(native_obj, I915_MAP_WB); + mode = intel_gt_coherent_map_type(to_gt(i915), native_obj, true); + vaddr = i915_gem_object_pin_map_unlocked(native_obj, mode); if (IS_ERR(vaddr)) { err = PTR_ERR(vaddr); goto out_file; diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index e1bf13e3d307..e9f65f27b53f 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -189,9 +189,6 @@ static bool gen12_needs_ccs_aux_inv(struct intel_engine_cs *engine) { i915_reg_t reg = gen12_get_aux_inv_reg(engine); - if (IS_PONTEVECCHIO(engine->i915)) - return false; - /* * So far platforms supported by i915 having flat ccs do not require * AUX invalidation. Check also whether the engine requires it. @@ -743,21 +740,25 @@ static u32 *gen12_emit_preempt_busywait(struct i915_request *rq, u32 *cs) } /* Wa_14014475959:dg2 */ -#define CCS_SEMAPHORE_PPHWSP_OFFSET 0x540 -static u32 ccs_semaphore_offset(struct i915_request *rq) +/* Wa_16019325821 */ +/* Wa_14019159160 */ +#define HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET 0x540 +static u32 hold_switchout_semaphore_offset(struct i915_request *rq) { return i915_ggtt_offset(rq->context->state) + - (LRC_PPHWSP_PN * PAGE_SIZE) + CCS_SEMAPHORE_PPHWSP_OFFSET; + (LRC_PPHWSP_PN * PAGE_SIZE) + HOLD_SWITCHOUT_SEMAPHORE_PPHWSP_OFFSET; } /* Wa_14014475959:dg2 */ -static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) +/* Wa_16019325821 */ +/* Wa_14019159160 */ +static u32 *hold_switchout_emit_wa_busywait(struct i915_request *rq, u32 *cs) { int i; *cs++ = MI_ATOMIC_INLINE | MI_ATOMIC_GLOBAL_GTT | MI_ATOMIC_CS_STALL | MI_ATOMIC_MOVE; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; *cs++ = 1; @@ -773,7 +774,7 @@ static u32 *ccs_emit_wa_busywait(struct i915_request *rq, u32 *cs) MI_SEMAPHORE_POLL | MI_SEMAPHORE_SAD_EQ_SDD; *cs++ = 0; - *cs++ = ccs_semaphore_offset(rq); + *cs++ = hold_switchout_semaphore_offset(rq); *cs++ = 0; return cs; @@ -790,8 +791,10 @@ gen12_emit_fini_breadcrumb_tail(struct i915_request *rq, u32 *cs) cs = gen12_emit_preempt_busywait(rq, cs); /* Wa_14014475959:dg2 */ - if (intel_engine_uses_wa_hold_ccs_switchout(rq->engine)) - cs = ccs_emit_wa_busywait(rq, cs); + /* Wa_16019325821 */ + /* Wa_14019159160 */ + if (intel_engine_uses_wa_hold_switchout(rq->engine)) + cs = hold_switchout_emit_wa_busywait(rq, cs); rq->tail = intel_ring_offset(rq, cs); assert_ring_tail_valid(rq->ring, rq->tail); @@ -827,7 +830,7 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs) cs = gen12_emit_pipe_control(cs, 0, PIPE_CONTROL_DEPTH_CACHE_FLUSH, 0); - if (GRAPHICS_VER(i915) == 12 && GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) + if (GRAPHICS_VER(i915) == 12 && GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) /* Wa_1409600907 */ flags |= PIPE_CONTROL_DEPTH_STALL; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index fa46d2308b0e..398d60a66410 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -500,11 +500,11 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, } static void -xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm, - struct i915_vma_resource *vma_res, - struct sgt_dma *iter, - unsigned int pat_index, - u32 flags) +xehp_ppgtt_insert_huge(struct i915_address_space *vm, + struct i915_vma_resource *vma_res, + struct sgt_dma *iter, + unsigned int pat_index, + u32 flags) { const gen8_pte_t pte_encode = vm->pte_encode(0, pat_index, flags); unsigned int rem = sg_dma_len(iter->sg); @@ -741,8 +741,8 @@ static void gen8_ppgtt_insert(struct i915_address_space *vm, struct sgt_dma iter = sgt_dma(vma_res); if (vma_res->bi.page_sizes.sg > I915_GTT_PAGE_SIZE) { - if (GRAPHICS_VER_FULL(vm->i915) >= IP_VER(12, 50)) - xehpsdv_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags); + if (GRAPHICS_VER_FULL(vm->i915) >= IP_VER(12, 55)) + xehp_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags); else gen8_ppgtt_insert_huge(vm, vma_res, &iter, pat_index, flags); } else { @@ -781,11 +781,11 @@ static void gen8_ppgtt_insert_entry(struct i915_address_space *vm, drm_clflush_virt_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr)); } -static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm, - dma_addr_t addr, - u64 offset, - unsigned int pat_index, - u32 flags) +static void xehp_ppgtt_insert_entry_lm(struct i915_address_space *vm, + dma_addr_t addr, + u64 offset, + unsigned int pat_index, + u32 flags) { u64 idx = offset >> GEN8_PTE_SHIFT; struct i915_page_directory * const pdp = @@ -810,15 +810,15 @@ static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm, vaddr[gen8_pd_index(idx, 0) / 16] = vm->pte_encode(addr, pat_index, flags); } -static void xehpsdv_ppgtt_insert_entry(struct i915_address_space *vm, - dma_addr_t addr, - u64 offset, - unsigned int pat_index, - u32 flags) +static void xehp_ppgtt_insert_entry(struct i915_address_space *vm, + dma_addr_t addr, + u64 offset, + unsigned int pat_index, + u32 flags) { if (flags & PTE_LM) - return __xehpsdv_ppgtt_insert_entry_lm(vm, addr, offset, - pat_index, flags); + return xehp_ppgtt_insert_entry_lm(vm, addr, offset, + pat_index, flags); return gen8_ppgtt_insert_entry(vm, addr, offset, pat_index, flags); } @@ -961,6 +961,9 @@ static int gen8_init_rsvd(struct i915_address_space *vm) struct i915_vma *vma; int ret; + if (!intel_gt_needs_wa_16018031267(vm->gt)) + return 0; + /* The memory will be used only by GPU. */ obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, I915_BO_ALLOC_VOLATILE | @@ -1042,7 +1045,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt, ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND; ppgtt->vm.insert_entries = gen8_ppgtt_insert; if (HAS_64K_PAGES(gt->i915)) - ppgtt->vm.insert_page = xehpsdv_ppgtt_insert_entry; + ppgtt->vm.insert_page = xehp_ppgtt_insert_entry; else ppgtt->vm.insert_page = gen8_ppgtt_insert_entry; ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc; diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 7eccbd70d89f..ed95a7b57cbb 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -130,6 +130,7 @@ struct intel_context { #define CONTEXT_PERMA_PIN 11 #define CONTEXT_IS_PARKING 12 #define CONTEXT_EXITING 13 +#define CONTEXT_LOW_LATENCY 14 struct { u64 timeout_us; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 1ade568ffbfa..5c8e9ee3b008 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -497,9 +497,8 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, engine->logical_mask = BIT(logical_instance); __sprint_engine_name(engine); - if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) && - __ffs(CCS_MASK(engine->gt)) == engine->instance) || - engine->class == RENDER_CLASS) + if ((engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) && + __ffs(CCS_MASK(engine->gt) | RCS_MASK(engine->gt)) == engine->instance) engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE; /* features common between engines sharing EUs */ @@ -589,7 +588,7 @@ u64 intel_clamp_preempt_timeout_ms(struct intel_engine_cs *engine, u64 value) * NB: The GuC API only supports 32bit values. However, the limit is further * reduced due to internal calculations which would otherwise overflow. */ - if (intel_guc_submission_is_wanted(&engine->gt->uc.guc)) + if (intel_guc_submission_is_wanted(gt_to_guc(engine->gt))) value = min_t(u64, value, guc_policy_max_preempt_timeout_ms()); value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); @@ -610,7 +609,7 @@ u64 intel_clamp_timeslice_duration_ms(struct intel_engine_cs *engine, u64 value) * NB: The GuC API only supports 32bit values. However, the limit is further * reduced due to internal calculations which would otherwise overflow. */ - if (intel_guc_submission_is_wanted(&engine->gt->uc.guc)) + if (intel_guc_submission_is_wanted(gt_to_guc(engine->gt))) value = min_t(u64, value, guc_policy_max_exec_quantum_ms()); value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT)); @@ -679,7 +678,7 @@ void intel_engines_release(struct intel_gt *gt) */ GEM_BUG_ON(intel_gt_pm_is_awake(gt)); if (!INTEL_INFO(gt->i915)->gpu_reset_clobbers_display) - __intel_gt_reset(gt, ALL_ENGINES); + intel_gt_reset_all_engines(gt); /* Decouple the backend; but keep the layout for late GPU resets */ for_each_engine(engine, gt, id) { @@ -765,14 +764,14 @@ static void engine_mask_apply_media_fuses(struct intel_gt *gt) * and bits have disable semantices. */ media_fuse = intel_uncore_read(gt->uncore, GEN11_GT_VEBOX_VDBOX_DISABLE); - if (MEDIA_VER_FULL(i915) < IP_VER(12, 50)) + if (MEDIA_VER_FULL(i915) < IP_VER(12, 55)) media_fuse = ~media_fuse; vdbox_mask = media_fuse & GEN11_GT_VDBOX_DISABLE_MASK; vebox_mask = (media_fuse & GEN11_GT_VEBOX_DISABLE_MASK) >> GEN11_GT_VEBOX_DISABLE_SHIFT; - if (MEDIA_VER_FULL(i915) >= IP_VER(12, 50)) { + if (MEDIA_VER_FULL(i915) >= IP_VER(12, 55)) { fuse1 = intel_uncore_read(gt->uncore, HSW_PAVP_FUSE1); gt->info.sfc_mask = REG_FIELD_GET(XEHP_SFC_ENABLE_MASK, fuse1); } else { @@ -839,38 +838,6 @@ static void engine_mask_apply_compute_fuses(struct intel_gt *gt) } } -static void engine_mask_apply_copy_fuses(struct intel_gt *gt) -{ - struct drm_i915_private *i915 = gt->i915; - struct intel_gt_info *info = >->info; - unsigned long meml3_mask; - unsigned long quad; - - if (!(GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60) && - GRAPHICS_VER_FULL(i915) < IP_VER(12, 70))) - return; - - meml3_mask = intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3); - meml3_mask = REG_FIELD_GET(GEN12_MEML3_EN_MASK, meml3_mask); - - /* - * Link Copy engines may be fused off according to meml3_mask. Each - * bit is a quad that houses 2 Link Copy and two Sub Copy engines. - */ - for_each_clear_bit(quad, &meml3_mask, GEN12_MAX_MSLICES) { - unsigned int instance = quad * 2 + 1; - intel_engine_mask_t mask = GENMASK(_BCS(instance + 1), - _BCS(instance)); - - if (mask & info->engine_mask) { - gt_dbg(gt, "bcs%u fused off\n", instance); - gt_dbg(gt, "bcs%u fused off\n", instance + 1); - - info->engine_mask &= ~mask; - } - } -} - /* * Determine which engines are fused off in our particular hardware. * Note that we have a catch-22 situation where we need to be able to access @@ -889,7 +856,6 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt) engine_mask_apply_media_fuses(gt); engine_mask_apply_compute_fuses(gt); - engine_mask_apply_copy_fuses(gt); /* * The only use of the GSC CS is to load and communicate with the GSC @@ -908,6 +874,23 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt) info->engine_mask &= ~BIT(GSC0); } + /* + * Do not create the command streamer for CCS slices beyond the first. + * All the workload submitted to the first engine will be shared among + * all the slices. + * + * Once the user will be allowed to customize the CCS mode, then this + * check needs to be removed. + */ + if (IS_DG2(gt->i915)) { + u8 first_ccs = __ffs(CCS_MASK(gt)); + + /* Mask off all the CCS engine */ + info->engine_mask &= ~GENMASK(CCS3, CCS0); + /* Put back in the first CCS engine */ + info->engine_mask |= BIT(_CCS(first_ccs)); + } + return info->engine_mask; } @@ -1193,7 +1176,6 @@ static int intel_engine_init_tlb_invalidation(struct intel_engine_cs *engine) if (GRAPHICS_VER_FULL(i915) == IP_VER(12, 74) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 71) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 70) || - GRAPHICS_VER_FULL(i915) == IP_VER(12, 50) || GRAPHICS_VER_FULL(i915) == IP_VER(12, 55)) { regs = xehp_regs; num = ARRAY_SIZE(xehp_regs); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 960e6be2042f..ba55c059063d 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -586,7 +586,7 @@ struct intel_engine_cs { #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITY BIT(10) #define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) -#define I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT BIT(12) +#define I915_ENGINE_USES_WA_HOLD_SWITCHOUT BIT(12) unsigned int flags; /* @@ -696,10 +696,12 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) } /* Wa_14014475959:dg2 */ +/* Wa_16019325821 */ +/* Wa_14019159160 */ static inline bool -intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) +intel_engine_uses_wa_hold_switchout(struct intel_engine_cs *engine) { - return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + return engine->flags & I915_ENGINE_USES_WA_HOLD_SWITCHOUT; } #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index b061a0a0d6b0..21829439e686 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -493,7 +493,7 @@ __execlists_schedule_in(struct i915_request *rq) /* Use a fixed tag for OA and friends */ GEM_BUG_ON(ce->tag <= BITS_PER_LONG); ce->lrc.ccid = ce->tag; - } else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) { + } else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) { /* We don't need a strict matching tag, just different values */ unsigned int tag = ffs(READ_ONCE(engine->context_tag)); @@ -613,7 +613,7 @@ static void __execlists_schedule_out(struct i915_request * const rq, intel_engine_add_retire(engine, ce->timeline); ccid = ce->lrc.ccid; - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) { ccid >>= XEHP_SW_CTX_ID_SHIFT - 32; ccid &= XEHP_MAX_CONTEXT_HW_ID; } else { @@ -1907,7 +1907,7 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive) ENGINE_TRACE(engine, "csb[%d]: status=0x%08x:0x%08x\n", head, upper_32_bits(csb), lower_32_bits(csb)); - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) promote = xehp_csb_parse(csb); else if (GRAPHICS_VER(engine->i915) >= 12) promote = gen12_csb_parse(csb); @@ -2898,7 +2898,7 @@ static void enable_error_interrupt(struct intel_engine_cs *engine) drm_err(&engine->i915->drm, "engine '%s' resumed still in error: %08x\n", engine->name, status); - __intel_gt_reset(engine->gt, engine->mask); + intel_gt_reset_engine(engine); } /* @@ -3482,7 +3482,7 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine) } } - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) { if (intel_engine_has_preemption(engine)) engine->emit_bb_start = xehp_emit_bb_start; else @@ -3585,7 +3585,7 @@ int intel_execlists_submission_setup(struct intel_engine_cs *engine) engine->context_tag = GENMASK(BITS_PER_LONG - 2, 0); if (GRAPHICS_VER(engine->i915) >= 11 && - GRAPHICS_VER_FULL(engine->i915) < IP_VER(12, 50)) { + GRAPHICS_VER_FULL(engine->i915) < IP_VER(12, 55)) { execlists->ccid |= engine->instance << (GEN11_ENGINE_INSTANCE_SHIFT - 32); execlists->ccid |= engine->class << (GEN11_ENGINE_CLASS_SHIFT - 32); } diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index ec1cbe229f0e..0d0a0dc9f610 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -231,11 +231,8 @@ static void guc_ggtt_ct_invalidate(struct intel_gt *gt) struct intel_uncore *uncore = gt->uncore; intel_wakeref_t wakeref; - with_intel_runtime_pm_if_active(uncore->rpm, wakeref) { - struct intel_guc *guc = >->uc.guc; - - intel_guc_invalidate_tlb_guc(guc); - } + with_intel_runtime_pm_if_active(uncore->rpm, wakeref) + intel_guc_invalidate_tlb_guc(gt_to_guc(gt)); } static void guc_ggtt_invalidate(struct i915_ggtt *ggtt) @@ -246,7 +243,7 @@ static void guc_ggtt_invalidate(struct i915_ggtt *ggtt) gen8_ggtt_invalidate(ggtt); list_for_each_entry(gt, &ggtt->gt_list, ggtt_link) { - if (intel_guc_tlb_invalidation_is_available(>->uc.guc)) + if (intel_guc_tlb_invalidation_is_available(gt_to_guc(gt))) guc_ggtt_ct_invalidate(gt); else if (GRAPHICS_VER(i915) >= 12) intel_uncore_write_fw(gt->uncore, diff --git a/drivers/gpu/drm/i915/gt/intel_gsc.c b/drivers/gpu/drm/i915/gt/intel_gsc.c index 6d440de8ba01..1e925c75fb08 100644 --- a/drivers/gpu/drm/i915/gt/intel_gsc.c +++ b/drivers/gpu/drm/i915/gt/intel_gsc.c @@ -103,19 +103,6 @@ static const struct gsc_def gsc_def_dg1[] = { } }; -static const struct gsc_def gsc_def_xehpsdv[] = { - { - /* HECI1 not enabled on the device. */ - }, - { - .name = "mei-gscfi", - .bar = DG1_GSC_HECI2_BASE, - .bar_size = GSC_BAR_LENGTH, - .use_polling = true, - .slow_firmware = true, - } -}; - static const struct gsc_def gsc_def_dg2[] = { { .name = "mei-gsc", @@ -188,8 +175,6 @@ static void gsc_init_one(struct drm_i915_private *i915, struct intel_gsc *gsc, if (IS_DG1(i915)) { def = &gsc_def_dg1[intf_id]; - } else if (IS_XEHPSDV(i915)) { - def = &gsc_def_xehpsdv[intf_id]; } else if (IS_DG2(i915)) { def = &gsc_def_dg2[intf_id]; } else { diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index a425db5ed3a2..626b166e67ef 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -278,7 +278,7 @@ intel_gt_clear_error_registers(struct intel_gt *gt, intel_uncore_posting_read(uncore, XELPMP_RING_FAULT_REG); - } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { + } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { intel_gt_mcr_multicast_rmw(gt, XEHP_RING_FAULT_REG, RING_FAULT_VALID, 0); intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG); @@ -403,7 +403,7 @@ void intel_gt_check_and_clear_faults(struct intel_gt *gt) struct drm_i915_private *i915 = gt->i915; /* From GEN8 onwards we only have one 'All Engine Fault Register' */ - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) xehp_check_faults(gt); else if (GRAPHICS_VER(i915) >= 8) gen8_check_faults(gt); @@ -832,7 +832,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt) /* Scrub all HW state upon release */ with_intel_runtime_pm(gt->uncore->rpm, wakeref) - __intel_gt_reset(gt, ALL_ENGINES); + intel_gt_reset_all_engines(gt); } void intel_gt_driver_release(struct intel_gt *gt) @@ -1024,6 +1024,12 @@ enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt, return I915_MAP_WC; } +bool intel_gt_needs_wa_16018031267(struct intel_gt *gt) +{ + /* Wa_16018031267, Wa_16018063123 */ + return IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 55), IP_VER(12, 71)); +} + bool intel_gt_needs_wa_22016122933(struct intel_gt *gt) { return MEDIA_VER_FULL(gt->i915) == IP_VER(13, 0) && gt->type == GT_MEDIA; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 608f5c872928..b5e114d284ad 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -82,17 +82,18 @@ struct drm_printer; ##__VA_ARGS__); \ } while (0) -#define NEEDS_FASTCOLOR_BLT_WABB(engine) ( \ - IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 55), IP_VER(12, 71)) && \ - engine->class == COPY_ENGINE_CLASS && engine->instance == 0) - static inline bool gt_is_root(struct intel_gt *gt) { return !gt->info.id; } +bool intel_gt_needs_wa_16018031267(struct intel_gt *gt); bool intel_gt_needs_wa_22016122933(struct intel_gt *gt); +#define NEEDS_FASTCOLOR_BLT_WABB(engine) ( \ + intel_gt_needs_wa_16018031267(engine->gt) && \ + engine->class == COPY_ENGINE_CLASS && engine->instance == 0) + static inline struct intel_gt *uc_to_gt(struct intel_uc *uc) { return container_of(uc, struct intel_gt, uc); @@ -123,6 +124,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) return guc_to_gt(guc)->i915; } +static inline struct intel_guc *gt_to_guc(struct intel_gt *gt) +{ + return >->uc.guc; +} + void intel_gt_common_init_early(struct intel_gt *gt); int intel_root_gt_init_early(struct drm_i915_private *i915); int intel_gt_assign_ggtt(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c new file mode 100644 index 000000000000..044219c5960a --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2024 Intel Corporation + */ + +#include "i915_drv.h" +#include "intel_gt.h" +#include "intel_gt_ccs_mode.h" +#include "intel_gt_regs.h" + +void intel_gt_apply_ccs_mode(struct intel_gt *gt) +{ + int cslice; + u32 mode = 0; + int first_ccs = __ffs(CCS_MASK(gt)); + + if (!IS_DG2(gt->i915)) + return; + + /* Build the value for the fixed CCS load balancing */ + for (cslice = 0; cslice < I915_MAX_CCS; cslice++) { + if (CCS_MASK(gt) & BIT(cslice)) + /* + * If available, assign the cslice + * to the first available engine... + */ + mode |= XEHP_CCS_MODE_CSLICE(cslice, first_ccs); + + else + /* + * ... otherwise, mark the cslice as + * unavailable if no CCS dispatches here + */ + mode |= XEHP_CCS_MODE_CSLICE(cslice, + XEHP_CCS_MODE_CSLICE_MASK); + } + + intel_uncore_write(gt->uncore, XEHP_CCS_MODE, mode); +} diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h new file mode 100644 index 000000000000..9e5549caeb26 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2024 Intel Corporation + */ + +#ifndef __INTEL_GT_CCS_MODE_H__ +#define __INTEL_GT_CCS_MODE_H__ + +struct intel_gt; + +void intel_gt_apply_ccs_mode(struct intel_gt *gt); + +#endif /* __INTEL_GT_CCS_MODE_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index 77fb57223465..ad4c51f18d3a 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -68,9 +68,9 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance, struct intel_gt *media_gt = gt->i915->media_gt; if (instance == OTHER_GUC_INSTANCE) - return guc_irq_handler(>->uc.guc, iir); + return guc_irq_handler(gt_to_guc(gt), iir); if (instance == OTHER_MEDIA_GUC_INSTANCE && media_gt) - return guc_irq_handler(&media_gt->uc.guc, iir); + return guc_irq_handler(gt_to_guc(media_gt), iir); if (instance == OTHER_GTPM_INSTANCE) return gen11_rps_irq_handler(>->rps, iir); @@ -442,7 +442,7 @@ void gen8_gt_irq_handler(struct intel_gt *gt, u32 master_ctl) iir = raw_reg_read(regs, GEN8_GT_IIR(2)); if (likely(iir)) { gen6_rps_irq_handler(>->rps, iir); - guc_irq_handler(>->uc.guc, iir >> 16); + guc_irq_handler(gt_to_guc(gt), iir >> 16); raw_reg_write(regs, GEN8_GT_IIR(2), iir); } } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c index e253750a51c5..b8912bd6c08e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c @@ -57,51 +57,18 @@ static const struct intel_mmio_range icl_l3bank_steering_table[] = { * are of a "GAM" subclass that has special rules. Thus we use a separate * GAM table farther down for those. */ -static const struct intel_mmio_range xehpsdv_mslice_steering_table[] = { +static const struct intel_mmio_range dg2_mslice_steering_table[] = { { 0x00DD00, 0x00DDFF }, { 0x00E900, 0x00FFFF }, /* 0xEA00 - OxEFFF is unused */ {}, }; -static const struct intel_mmio_range xehpsdv_gam_steering_table[] = { - { 0x004000, 0x004AFF }, - { 0x00C800, 0x00CFFF }, - {}, -}; - -static const struct intel_mmio_range xehpsdv_lncf_steering_table[] = { - { 0x00B000, 0x00B0FF }, - { 0x00D800, 0x00D8FF }, - {}, -}; - static const struct intel_mmio_range dg2_lncf_steering_table[] = { { 0x00B000, 0x00B0FF }, { 0x00D880, 0x00D8FF }, {}, }; -/* - * We have several types of MCR registers on PVC where steering to (0,0) - * will always provide us with a non-terminated value. We'll stick them - * all in the same table for simplicity. - */ -static const struct intel_mmio_range pvc_instance0_steering_table[] = { - { 0x004000, 0x004AFF }, /* HALF-BSLICE */ - { 0x008800, 0x00887F }, /* CC */ - { 0x008A80, 0x008AFF }, /* TILEPSMI */ - { 0x00B000, 0x00B0FF }, /* HALF-BSLICE */ - { 0x00B100, 0x00B3FF }, /* L3BANK */ - { 0x00C800, 0x00CFFF }, /* HALF-BSLICE */ - { 0x00D800, 0x00D8FF }, /* HALF-BSLICE */ - { 0x00DD00, 0x00DDFF }, /* BSLICE */ - { 0x00E900, 0x00E9FF }, /* HALF-BSLICE */ - { 0x00EC00, 0x00EEFF }, /* HALF-BSLICE */ - { 0x00F000, 0x00FFFF }, /* HALF-BSLICE */ - { 0x024180, 0x0241FF }, /* HALF-BSLICE */ - {}, -}; - static const struct intel_mmio_range xelpg_instance0_steering_table[] = { { 0x000B00, 0x000BFF }, /* SQIDI */ { 0x001000, 0x001FFF }, /* SQIDI */ @@ -185,22 +152,16 @@ void intel_gt_mcr_init(struct intel_gt *gt) gt->steering_table[INSTANCE0] = xelpg_instance0_steering_table; gt->steering_table[L3BANK] = xelpg_l3bank_steering_table; gt->steering_table[DSS] = xelpg_dss_steering_table; - } else if (IS_PONTEVECCHIO(i915)) { - gt->steering_table[INSTANCE0] = pvc_instance0_steering_table; } else if (IS_DG2(i915)) { - gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table; + gt->steering_table[MSLICE] = dg2_mslice_steering_table; gt->steering_table[LNCF] = dg2_lncf_steering_table; /* * No need to hook up the GAM table since it has a dedicated * steering control register on DG2 and can use implicit * steering. */ - } else if (IS_XEHPSDV(i915)) { - gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table; - gt->steering_table[LNCF] = xehpsdv_lncf_steering_table; - gt->steering_table[GAM] = xehpsdv_gam_steering_table; } else if (GRAPHICS_VER(i915) >= 11 && - GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) { + GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) { gt->steering_table[L3BANK] = icl_l3bank_steering_table; gt->info.l3bank_mask = ~intel_uncore_read(gt->uncore, GEN10_MIRROR_FUSE3) & @@ -821,8 +782,6 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt, for (int i = 0; i < NUM_STEERING_TYPES; i++) if (gt->steering_table[i]) report_steering_type(p, gt, i, dump_table); - } else if (IS_PONTEVECCHIO(gt->i915)) { - report_steering_type(p, gt, INSTANCE0, dump_table); } else if (HAS_MSLICE_STEERING(gt->i915)) { report_steering_type(p, gt, MSLICE, dump_table); report_steering_type(p, gt, LNCF, dump_table); @@ -842,10 +801,7 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt, void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss, unsigned int *group, unsigned int *instance) { - if (IS_PONTEVECCHIO(gt->i915)) { - *group = dss / GEN_DSS_PER_CSLICE; - *instance = dss % GEN_DSS_PER_CSLICE; - } else if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55)) { *group = dss / GEN_DSS_PER_GSLICE; *instance = dss % GEN_DSS_PER_GSLICE; } else { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h index 01ac565a56a4..a67a4c35a4fa 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h @@ -54,7 +54,7 @@ int intel_gt_mcr_wait_for_reg(struct intel_gt *gt, * the topology, so we lookup the DSS ID directly in "slice 0." */ #define _HAS_SS(ss_, gt_, group_, instance_) ( \ - GRAPHICS_VER_FULL(gt_->i915) >= IP_VER(12, 50) ? \ + GRAPHICS_VER_FULL(gt_->i915) >= IP_VER(12, 55) ? \ intel_sseu_has_subslice(&(gt_)->info.sseu, 0, ss_) : \ intel_sseu_has_subslice(&(gt_)->info.sseu, group_, instance_)) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index 220ac4f92edf..c08fdb65cc69 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -159,7 +159,7 @@ static bool reset_engines(struct intel_gt *gt) if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display) return false; - return __intel_gt_reset(gt, ALL_ENGINES) == 0; + return intel_gt_reset_all_engines(gt) == 0; } static void gt_sanitize(struct intel_gt *gt, bool force) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 7114c116e928..4fcba42cfe34 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -392,10 +392,6 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) drm_puts(p, "no P-state info available\n"); } - drm_printf(p, "Current CD clock frequency: %d kHz\n", i915->display.cdclk.hw.cdclk); - drm_printf(p, "Max CD clock frequency: %d kHz\n", i915->display.cdclk.max_cdclk_freq); - drm_printf(p, "Max pixel clock frequency: %d kHz\n", i915->max_dotclk_freq); - intel_runtime_pm_put(uncore->rpm, wakeref); } @@ -538,7 +534,7 @@ static bool rps_eval(void *data) { struct intel_gt *gt = data; - if (intel_guc_slpc_is_used(>->uc.guc)) + if (intel_guc_slpc_is_used(gt_to_guc(gt))) return false; else return HAS_RPS(gt->i915); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 50962cfd1353..e42b3a5d4e63 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -718,44 +718,11 @@ #define UNSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9434) #define VFUNIT_CLKGATE_DIS REG_BIT(20) -#define TSGUNIT_CLKGATE_DIS REG_BIT(17) /* XEHPSDV */ #define CG3DDISCFEG_CLKGATE_DIS REG_BIT(17) /* DG2 */ #define GAMEDIA_CLKGATE_DIS REG_BIT(11) #define HSUNIT_CLKGATE_DIS REG_BIT(8) #define VSUNIT_CLKGATE_DIS REG_BIT(3) -#define UNSLCGCTL9440 _MMIO(0x9440) -#define GAMTLBOACS_CLKGATE_DIS REG_BIT(28) -#define GAMTLBVDBOX5_CLKGATE_DIS REG_BIT(27) -#define GAMTLBVDBOX6_CLKGATE_DIS REG_BIT(26) -#define GAMTLBVDBOX3_CLKGATE_DIS REG_BIT(24) -#define GAMTLBVDBOX4_CLKGATE_DIS REG_BIT(23) -#define GAMTLBVDBOX7_CLKGATE_DIS REG_BIT(22) -#define GAMTLBVDBOX2_CLKGATE_DIS REG_BIT(21) -#define GAMTLBVDBOX0_CLKGATE_DIS REG_BIT(17) -#define GAMTLBKCR_CLKGATE_DIS REG_BIT(16) -#define GAMTLBGUC_CLKGATE_DIS REG_BIT(15) -#define GAMTLBBLT_CLKGATE_DIS REG_BIT(14) -#define GAMTLBVDBOX1_CLKGATE_DIS REG_BIT(6) - -#define UNSLCGCTL9444 _MMIO(0x9444) -#define GAMTLBGFXA0_CLKGATE_DIS REG_BIT(30) -#define GAMTLBGFXA1_CLKGATE_DIS REG_BIT(29) -#define GAMTLBCOMPA0_CLKGATE_DIS REG_BIT(28) -#define GAMTLBCOMPA1_CLKGATE_DIS REG_BIT(27) -#define GAMTLBCOMPB0_CLKGATE_DIS REG_BIT(26) -#define GAMTLBCOMPB1_CLKGATE_DIS REG_BIT(25) -#define GAMTLBCOMPC0_CLKGATE_DIS REG_BIT(24) -#define GAMTLBCOMPC1_CLKGATE_DIS REG_BIT(23) -#define GAMTLBCOMPD0_CLKGATE_DIS REG_BIT(22) -#define GAMTLBCOMPD1_CLKGATE_DIS REG_BIT(21) -#define GAMTLBMERT_CLKGATE_DIS REG_BIT(20) -#define GAMTLBVEBOX3_CLKGATE_DIS REG_BIT(19) -#define GAMTLBVEBOX2_CLKGATE_DIS REG_BIT(18) -#define GAMTLBVEBOX1_CLKGATE_DIS REG_BIT(17) -#define GAMTLBVEBOX0_CLKGATE_DIS REG_BIT(16) -#define LTCDD_CLKGATE_DIS REG_BIT(10) - #define GEN11_SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4) #define XEHP_SLICE_UNIT_LEVEL_CLKGATE MCR_REG(0x94d4) #define SARBUNIT_CLKGATE_DIS (1 << 5) @@ -765,9 +732,6 @@ #define L3_CLKGATE_DIS REG_BIT(16) #define L3_CR2X_CLKGATE_DIS REG_BIT(17) -#define SCCGCTL94DC MCR_REG(0x94dc) -#define CG3DDISURB REG_BIT(14) - #define UNSLICE_UNIT_LEVEL_CLKGATE2 _MMIO(0x94e4) #define VSUNIT_CLKGATE_DIS_TGL REG_BIT(19) #define PSDUNIT_CLKGATE_DIS REG_BIT(5) @@ -989,10 +953,6 @@ #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C #define GEN7_L3AGDIS (1 << 19) -#define XEHPC_LNCFMISCCFGREG0 MCR_REG(0xb01c) -#define XEHPC_HOSTCACHEEN REG_BIT(1) -#define XEHPC_OVRLSCCC REG_BIT(0) - #define GEN7_L3CNTLREG2 _MMIO(0xb020) /* MOCS (Memory Object Control State) registers */ @@ -1046,20 +1006,9 @@ #define XEHP_L3SQCREG5 MCR_REG(0xb158) #define L3_PWM_TIMER_INIT_VAL_MASK REG_GENMASK(9, 0) -#define MLTICTXCTL MCR_REG(0xb170) -#define TDONRENDER REG_BIT(2) - #define XEHP_L3SCQREG7 MCR_REG(0xb188) #define BLEND_FILL_CACHING_OPT_DIS REG_BIT(3) -#define XEHPC_L3SCRUB MCR_REG(0xb18c) -#define SCRUB_CL_DWNGRADE_SHARED REG_BIT(12) -#define SCRUB_RATE_PER_BANK_MASK REG_GENMASK(2, 0) -#define SCRUB_RATE_4B_PER_CLK REG_FIELD_PREP(SCRUB_RATE_PER_BANK_MASK, 0x6) - -#define L3SQCREG1_CCS0 MCR_REG(0xb200) -#define FLUSHALLNONCOH REG_BIT(5) - #define GEN11_GLBLINVL _MMIO(0xb404) #define GEN11_BANK_HASH_ADDR_EXCL_MASK (0x7f << 5) #define GEN11_BANK_HASH_ADDR_EXCL_BIT0 (1 << 5) @@ -1109,7 +1058,6 @@ #define XEHP_COMPCTX_TLB_INV_CR MCR_REG(0xcf04) #define XELPMP_GSC_TLB_INV_CR _MMIO(0xcf04) /* media GT only */ -#define XEHP_MERT_MOD_CTRL MCR_REG(0xcf28) #define RENDER_MOD_CTRL MCR_REG(0xcf2c) #define COMP_MOD_CTRL MCR_REG(0xcf30) #define XELPMP_GSC_MOD_CTRL _MMIO(0xcf30) /* media GT only */ @@ -1185,7 +1133,6 @@ #define EU_PERF_CNTL4 PERF_REG(0xe45c) #define GEN9_ROW_CHICKEN4 MCR_REG(0xe48c) -#define GEN12_DISABLE_GRF_CLEAR REG_BIT(13) #define XEHP_DIS_BBL_SYSPIPE REG_BIT(11) #define GEN12_DISABLE_TDL_PUSH REG_BIT(9) #define GEN11_DIS_PICK_2ND_EU REG_BIT(7) @@ -1202,7 +1149,6 @@ #define FLOW_CONTROL_ENABLE REG_BIT(15) #define UGM_BACKUP_MODE REG_BIT(13) #define MDQ_ARBITRATION_MODE REG_BIT(12) -#define SYSTOLIC_DOP_CLOCK_GATING_DIS REG_BIT(10) #define PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE REG_BIT(8) #define STALL_DOP_GATING_DISABLE REG_BIT(5) #define THROTTLE_12_5 REG_GENMASK(4, 2) @@ -1215,6 +1161,7 @@ #define GEN12_DISABLE_EARLY_READ REG_BIT(14) #define GEN12_ENABLE_LARGE_GRF_MODE REG_BIT(12) #define GEN12_PUSH_CONST_DEREF_HOLD_DIS REG_BIT(8) +#define XELPG_DISABLE_TDL_SVHS_GATING REG_BIT(1) #define GEN12_DISABLE_DOP_GATING REG_BIT(0) #define RT_CTRL MCR_REG(0xe530) @@ -1477,8 +1424,14 @@ #define ECOBITS_PPGTT_CACHE4B (0 << 8) #define GEN12_RCU_MODE _MMIO(0x14800) +#define XEHP_RCU_MODE_FIXED_SLICE_CCS_MODE REG_BIT(1) #define GEN12_RCU_MODE_CCS_ENABLE REG_BIT(0) +#define XEHP_CCS_MODE _MMIO(0x14804) +#define XEHP_CCS_MODE_CSLICE_MASK REG_GENMASK(2, 0) /* CCS0-3 + rsvd */ +#define XEHP_CCS_MODE_CSLICE_WIDTH ilog2(XEHP_CCS_MODE_CSLICE_MASK + 1) +#define XEHP_CCS_MODE_CSLICE(cslice, ccs) (ccs << (cslice * XEHP_CCS_MODE_CSLICE_WIDTH)) + #define CHV_FUSE_GT _MMIO(VLV_GUNIT_BASE + 0x2168) #define CHV_FGT_DISABLE_SS0 (1 << 10) #define CHV_FGT_DISABLE_SS1 (1 << 11) @@ -1679,11 +1632,6 @@ #define GEN12_SFC_DONE(n) _MMIO(0x1cc000 + (n) * 0x1000) -#define GT0_PACKAGE_ENERGY_STATUS _MMIO(0x250004) -#define GT0_PACKAGE_RAPL_LIMIT _MMIO(0x250008) -#define GT0_PACKAGE_POWER_SKU_UNIT _MMIO(0x250068) -#define GT0_PLATFORM_ENERGY_STATUS _MMIO(0x25006c) - /* * Standalone Media's non-engine GT registers are located at their regular GT * offsets plus 0x380000. This extra offset is stored inside the intel_uncore diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c index c0b202223940..d7784650e4d9 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -442,7 +442,7 @@ static ssize_t slpc_ignore_eff_freq_show(struct kobject *kobj, char *buff) { struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; return sysfs_emit(buff, "%u\n", slpc->ignore_eff_freq); } @@ -452,7 +452,7 @@ static ssize_t slpc_ignore_eff_freq_store(struct kobject *kobj, const char *buff, size_t count) { struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; int err; u32 val; @@ -573,7 +573,6 @@ static ssize_t media_freq_factor_show(struct kobject *kobj, char *buff) { struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); - struct intel_guc_slpc *slpc = >->uc.guc.slpc; intel_wakeref_t wakeref; u32 mode; @@ -581,20 +580,12 @@ static ssize_t media_freq_factor_show(struct kobject *kobj, * Retrieve media_ratio_mode from GEN6_RPNSWREQ bit 13 set by * GuC. GEN6_RPNSWREQ:13 value 0 represents 1:2 and 1 represents 1:1 */ - if (IS_XEHPSDV(gt->i915) && - slpc->media_ratio_mode == SLPC_MEDIA_RATIO_MODE_DYNAMIC_CONTROL) { - /* - * For XEHPSDV dynamic mode GEN6_RPNSWREQ:13 does not contain - * the media_ratio_mode, just return the cached media ratio - */ - mode = slpc->media_ratio_mode; - } else { - with_intel_runtime_pm(gt->uncore->rpm, wakeref) - mode = intel_uncore_read(gt->uncore, GEN6_RPNSWREQ); - mode = REG_FIELD_GET(GEN12_MEDIA_FREQ_RATIO, mode) ? - SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_ONE : - SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO; - } + with_intel_runtime_pm(gt->uncore->rpm, wakeref) + mode = intel_uncore_read(gt->uncore, GEN6_RPNSWREQ); + + mode = REG_FIELD_GET(GEN12_MEDIA_FREQ_RATIO, mode) ? + SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_ONE : + SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO; return sysfs_emit(buff, "%u\n", media_ratio_mode_to_factor(mode)); } @@ -604,7 +595,7 @@ static ssize_t media_freq_factor_store(struct kobject *kobj, const char *buff, size_t count) { struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name); - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; u32 factor, mode; int err; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 7811a8c9da06..30b128b1fde7 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -680,7 +680,7 @@ void setup_private_pat(struct intel_gt *gt) if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) xelpg_setup_private_ppat(gt); - else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) xehp_setup_private_ppat(gt); else if (GRAPHICS_VER(i915) >= 12) tgl_setup_private_ppat(uncore); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 7c367ba8d9dc..b387146ede98 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -546,47 +546,6 @@ static const u8 gen12_rcs_offsets[] = { END }; -static const u8 xehp_rcs_offsets[] = { - NOP(1), - LRI(13, POSTED), - REG16(0x244), - REG(0x034), - REG(0x030), - REG(0x038), - REG(0x03c), - REG(0x168), - REG(0x140), - REG(0x110), - REG(0x1c0), - REG(0x1c4), - REG(0x1c8), - REG(0x180), - REG16(0x2b4), - - NOP(5), - LRI(9, POSTED), - REG16(0x3a8), - REG16(0x28c), - REG16(0x288), - REG16(0x284), - REG16(0x280), - REG16(0x27c), - REG16(0x278), - REG16(0x274), - REG16(0x270), - - LRI(3, POSTED), - REG(0x1b0), - REG16(0x5a8), - REG16(0x5ac), - - NOP(6), - LRI(1, 0), - REG(0x0c8), - - END -}; - static const u8 dg2_rcs_offsets[] = { NOP(1), LRI(15, POSTED), @@ -695,8 +654,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine) return mtl_rcs_offsets; else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) return dg2_rcs_offsets; - else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) - return xehp_rcs_offsets; else if (GRAPHICS_VER(engine->i915) >= 12) return gen12_rcs_offsets; else if (GRAPHICS_VER(engine->i915) >= 11) @@ -719,7 +676,7 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine) static int lrc_ring_mi_mode(const struct intel_engine_cs *engine) { - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) return 0x70; else if (GRAPHICS_VER(engine->i915) >= 12) return 0x60; @@ -733,7 +690,7 @@ static int lrc_ring_mi_mode(const struct intel_engine_cs *engine) static int lrc_ring_bb_offset(const struct intel_engine_cs *engine) { - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) return 0x80; else if (GRAPHICS_VER(engine->i915) >= 12) return 0x70; @@ -748,7 +705,7 @@ static int lrc_ring_bb_offset(const struct intel_engine_cs *engine) static int lrc_ring_gpr0(const struct intel_engine_cs *engine) { - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) return 0x84; else if (GRAPHICS_VER(engine->i915) >= 12) return 0x74; @@ -795,7 +752,7 @@ static int lrc_ring_indirect_offset(const struct intel_engine_cs *engine) static int lrc_ring_cmd_buf_cctl(const struct intel_engine_cs *engine) { - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) /* * Note that the CSFE context has a dummy slot for CMD_BUF_CCTL * simply to match the RCS context image layout. diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index 576e5ef0289b..6f7af4077135 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -35,9 +35,9 @@ static bool engine_supports_migration(struct intel_engine_cs *engine) return true; } -static void xehpsdv_toggle_pdes(struct i915_address_space *vm, - struct i915_page_table *pt, - void *data) +static void xehp_toggle_pdes(struct i915_address_space *vm, + struct i915_page_table *pt, + void *data) { struct insert_pte_data *d = data; @@ -52,9 +52,9 @@ static void xehpsdv_toggle_pdes(struct i915_address_space *vm, d->offset += SZ_2M; } -static void xehpsdv_insert_pte(struct i915_address_space *vm, - struct i915_page_table *pt, - void *data) +static void xehp_insert_pte(struct i915_address_space *vm, + struct i915_page_table *pt, + void *data) { struct insert_pte_data *d = data; @@ -120,7 +120,7 @@ static struct i915_address_space *migrate_vm(struct intel_gt *gt) * 512 entry layout using 4K GTT pages. The other two windows just map * lmem pages and must use the new compact 32 entry layout using 64K GTT * pages, which ensures we can address any lmem object that the user - * throws at us. We then also use the xehpsdv_toggle_pdes as a way of + * throws at us. We then also use the xehp_toggle_pdes as a way of * just toggling the PDE bit(GEN12_PDE_64K) for us, to enable the * compact layout for each of these page-tables, that fall within the * [CHUNK_SIZE, 3 * CHUNK_SIZE) range. @@ -209,12 +209,12 @@ static struct i915_address_space *migrate_vm(struct intel_gt *gt) /* Now allow the GPU to rewrite the PTE via its own ppGTT */ if (HAS_64K_PAGES(gt->i915)) { vm->vm.foreach(&vm->vm, base, d.offset - base, - xehpsdv_insert_pte, &d); + xehp_insert_pte, &d); d.offset = base + CHUNK_SZ; vm->vm.foreach(&vm->vm, d.offset, 2 * CHUNK_SZ, - xehpsdv_toggle_pdes, &d); + xehp_toggle_pdes, &d); } else { vm->vm.foreach(&vm->vm, base, d.offset - base, insert_pte, &d); @@ -925,7 +925,7 @@ static int emit_clear(struct i915_request *rq, u32 offset, int size, GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX); - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) ring_sz = XY_FAST_COLOR_BLT_DW; else if (ver >= 8) ring_sz = 8; @@ -936,7 +936,7 @@ static int emit_clear(struct i915_request *rq, u32 offset, int size, if (IS_ERR(cs)) return PTR_ERR(cs); - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { *cs++ = XY_FAST_COLOR_BLT_CMD | XY_FAST_COLOR_BLT_DEPTH_32 | (XY_FAST_COLOR_BLT_DW - 2); *cs++ = FIELD_PREP(XY_FAST_COLOR_BLT_MOCS_MASK, mocs) | diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c index 25c1023eb5f9..d791d63d49b4 100644 --- a/drivers/gpu/drm/i915/gt/intel_mocs.c +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c @@ -53,7 +53,6 @@ struct drm_i915_mocs_table { /* Helper defines */ #define GEN9_NUM_MOCS_ENTRIES 64 /* 63-64 are reserved, but configured. */ -#define PVC_NUM_MOCS_ENTRIES 3 #define MTL_NUM_MOCS_ENTRIES 16 /* (e)LLC caching options */ @@ -367,31 +366,6 @@ static const struct drm_i915_mocs_entry gen12_mocs_table[] = { L3_3_WB), }; -static const struct drm_i915_mocs_entry xehpsdv_mocs_table[] = { - /* wa_1608975824 */ - MOCS_ENTRY(0, 0, L3_3_WB | L3_LKUP(1)), - - /* UC - Coherent; GO:L3 */ - MOCS_ENTRY(1, 0, L3_1_UC | L3_LKUP(1)), - /* UC - Coherent; GO:Memory */ - MOCS_ENTRY(2, 0, L3_1_UC | L3_GLBGO(1) | L3_LKUP(1)), - /* UC - Non-Coherent; GO:Memory */ - MOCS_ENTRY(3, 0, L3_1_UC | L3_GLBGO(1)), - /* UC - Non-Coherent; GO:L3 */ - MOCS_ENTRY(4, 0, L3_1_UC), - - /* WB */ - MOCS_ENTRY(5, 0, L3_3_WB | L3_LKUP(1)), - - /* HW Reserved - SW program but never use. */ - MOCS_ENTRY(48, 0, L3_3_WB | L3_LKUP(1)), - MOCS_ENTRY(49, 0, L3_1_UC | L3_LKUP(1)), - MOCS_ENTRY(60, 0, L3_1_UC), - MOCS_ENTRY(61, 0, L3_1_UC), - MOCS_ENTRY(62, 0, L3_1_UC), - MOCS_ENTRY(63, 0, L3_1_UC), -}; - static const struct drm_i915_mocs_entry dg2_mocs_table[] = { /* UC - Coherent; GO:L3 */ MOCS_ENTRY(0, 0, L3_1_UC | L3_LKUP(1)), @@ -404,17 +378,6 @@ static const struct drm_i915_mocs_entry dg2_mocs_table[] = { MOCS_ENTRY(3, 0, L3_3_WB | L3_LKUP(1)), }; -static const struct drm_i915_mocs_entry pvc_mocs_table[] = { - /* Error */ - MOCS_ENTRY(0, 0, L3_3_WB), - - /* UC */ - MOCS_ENTRY(1, 0, L3_1_UC), - - /* WB */ - MOCS_ENTRY(2, 0, L3_3_WB), -}; - static const struct drm_i915_mocs_entry mtl_mocs_table[] = { /* Error - Reserved for Non-Use */ MOCS_ENTRY(0, @@ -501,25 +464,12 @@ static unsigned int get_mocs_settings(struct drm_i915_private *i915, table->n_entries = MTL_NUM_MOCS_ENTRIES; table->uc_index = 9; table->unused_entries_index = 1; - } else if (IS_PONTEVECCHIO(i915)) { - table->size = ARRAY_SIZE(pvc_mocs_table); - table->table = pvc_mocs_table; - table->n_entries = PVC_NUM_MOCS_ENTRIES; - table->uc_index = 1; - table->wb_index = 2; - table->unused_entries_index = 2; } else if (IS_DG2(i915)) { table->size = ARRAY_SIZE(dg2_mocs_table); table->table = dg2_mocs_table; table->uc_index = 1; table->n_entries = GEN9_NUM_MOCS_ENTRIES; table->unused_entries_index = 3; - } else if (IS_XEHPSDV(i915)) { - table->size = ARRAY_SIZE(xehpsdv_mocs_table); - table->table = xehpsdv_mocs_table; - table->uc_index = 2; - table->n_entries = GEN9_NUM_MOCS_ENTRIES; - table->unused_entries_index = 5; } else if (IS_DG1(i915)) { table->size = ARRAY_SIZE(dg1_mocs_table); table->table = dg1_mocs_table; @@ -670,7 +620,7 @@ static void init_l3cc_table(struct intel_gt *gt, intel_gt_mcr_lock(gt, &flags); for_each_l3cc(l3cc, table, i) - if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 55)) intel_gt_mcr_multicast_write_fw(gt, XEHP_LNCFCMOCS(i), l3cc); else intel_uncore_write_fw(gt->uncore, GEN9_LNCFCMOCS(i), l3cc); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 8f4b3c8af09c..c864d101faf9 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -109,7 +109,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6) * thus allowing GuC to control RC6 entry/exit fully instead. * We will not set the HW ENABLE and EI bits */ - if (!intel_guc_rc_enable(>->uc.guc)) + if (!intel_guc_rc_enable(gt_to_guc(gt))) rc6->ctl_enable = GEN6_RC_CTL_RC6_ENABLE; else rc6->ctl_enable = @@ -569,7 +569,7 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6) struct intel_gt *gt = rc6_to_gt(rc6); /* Take control of RC6 back from GuC */ - intel_guc_rc_disable(>->uc.guc); + intel_guc_rc_disable(gt_to_guc(gt)); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); if (GRAPHICS_VER(i915) >= 9) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index c8e9aa41fdea..6161f7a3ff70 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -764,7 +764,7 @@ wa_14015076503_end(struct intel_gt *gt, intel_engine_mask_t engine_mask) HECI_H_GS1_ER_PREP, 0); } -int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask) +static int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask) { const int retries = engine_mask == ALL_ENGINES ? RESET_MAX_RETRIES : 1; reset_func reset; @@ -879,8 +879,17 @@ static intel_engine_mask_t reset_prepare(struct intel_gt *gt) intel_engine_mask_t awake = 0; enum intel_engine_id id; - /* For GuC mode, ensure submission is disabled before stopping ring */ - intel_uc_reset_prepare(>->uc); + /** + * For GuC mode with submission enabled, ensure submission + * is disabled before stopping ring. + * + * For GuC mode with submission disabled, ensure that GuC is not + * sanitized, do that after engine reset. reset_prepare() + * is followed by engine reset which in this mode requires GuC to + * process any CSB FIFO entries generated by the resets. + */ + if (intel_uc_uses_guc_submission(>->uc)) + intel_uc_reset_prepare(>->uc); for_each_engine(engine, gt, id) { if (intel_engine_pm_get_if_awake(engine)) @@ -978,7 +987,7 @@ static void __intel_gt_set_wedged(struct intel_gt *gt) /* Even if the GPU reset fails, it should still stop the engines */ if (!INTEL_INFO(gt->i915)->gpu_reset_clobbers_display) - __intel_gt_reset(gt, ALL_ENGINES); + intel_gt_reset_all_engines(gt); for_each_engine(engine, gt, id) engine->submit_request = nop_submit_request; @@ -1089,7 +1098,7 @@ static bool __intel_gt_unset_wedged(struct intel_gt *gt) /* We must reset pending GPU events before restoring our submission */ ok = !HAS_EXECLISTS(gt->i915); /* XXX better agnosticism desired */ if (!INTEL_INFO(gt->i915)->gpu_reset_clobbers_display) - ok = __intel_gt_reset(gt, ALL_ENGINES) == 0; + ok = intel_gt_reset_all_engines(gt) == 0; if (!ok) { /* * Warn CI about the unrecoverable wedged condition. @@ -1133,10 +1142,10 @@ static int do_reset(struct intel_gt *gt, intel_engine_mask_t stalled_mask) { int err, i; - err = __intel_gt_reset(gt, ALL_ENGINES); + err = intel_gt_reset_all_engines(gt); for (i = 0; err && i < RESET_MAX_RETRIES; i++) { msleep(10 * (i + 1)); - err = __intel_gt_reset(gt, ALL_ENGINES); + err = intel_gt_reset_all_engines(gt); } if (err) return err; @@ -1227,6 +1236,9 @@ void intel_gt_reset(struct intel_gt *gt, intel_overlay_reset(gt->i915); + /* sanitize uC after engine reset */ + if (!intel_uc_uses_guc_submission(>->uc)) + intel_uc_reset_prepare(>->uc); /* * Next we need to restore the context, but we don't use those * yet either... @@ -1270,7 +1282,30 @@ void intel_gt_reset(struct intel_gt *gt, goto finish; } -static int intel_gt_reset_engine(struct intel_engine_cs *engine) +/** + * intel_gt_reset_all_engines() - Reset all engines in the given gt. + * @gt: the GT to reset all engines for. + * + * This function resets all engines within the given gt. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int intel_gt_reset_all_engines(struct intel_gt *gt) +{ + return __intel_gt_reset(gt, ALL_ENGINES); +} + +/** + * intel_gt_reset_engine() - Reset a specific engine within a gt. + * @engine: engine to be reset. + * + * This function resets the specified engine within a gt. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int intel_gt_reset_engine(struct intel_engine_cs *engine) { return __intel_gt_reset(engine->gt, engine->mask); } diff --git a/drivers/gpu/drm/i915/gt/intel_reset.h b/drivers/gpu/drm/i915/gt/intel_reset.h index f615b30b81c5..c00de353075c 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.h +++ b/drivers/gpu/drm/i915/gt/intel_reset.h @@ -54,7 +54,8 @@ int intel_gt_terminally_wedged(struct intel_gt *gt); void intel_gt_set_wedged_on_init(struct intel_gt *gt); void intel_gt_set_wedged_on_fini(struct intel_gt *gt); -int __intel_gt_reset(struct intel_gt *gt, intel_engine_mask_t engine_mask); +int intel_gt_reset_engine(struct intel_engine_cs *engine); +int intel_gt_reset_all_engines(struct intel_gt *gt); int intel_reset_guc(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 4feef874e6d6..c9cb2a391942 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -52,7 +52,7 @@ static struct intel_guc_slpc *rps_to_slpc(struct intel_rps *rps) { struct intel_gt *gt = rps_to_gt(rps); - return >->uc.guc.slpc; + return >_to_guc(gt)->slpc; } static bool rps_uses_slpc(struct intel_rps *rps) @@ -1013,6 +1013,10 @@ void intel_rps_boost(struct i915_request *rq) if (i915_request_signaled(rq) || i915_request_has_waitboost(rq)) return; + /* Waitboost is not needed for contexts marked with a Freq hint */ + if (test_bit(CONTEXT_LOW_LATENCY, &rq->context->flags)) + return; + /* Serializes with i915_request_retire() */ if (!test_and_set_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags)) { struct intel_rps *rps = &READ_ONCE(rq->engine)->gt->rps; @@ -1086,11 +1090,7 @@ static u32 intel_rps_read_state_cap(struct intel_rps *rps) struct drm_i915_private *i915 = rps_to_i915(rps); struct intel_uncore *uncore = rps_to_uncore(rps); - if (IS_PONTEVECCHIO(i915)) - return intel_uncore_read(uncore, PVC_RP_STATE_CAP); - else if (IS_XEHPSDV(i915)) - return intel_uncore_read(uncore, XEHPSDV_RP_STATE_CAP); - else if (IS_GEN9_LP(i915)) + if (IS_GEN9_LP(i915)) return intel_uncore_read(uncore, BXT_RP_STATE_CAP); else return intel_uncore_read(uncore, GEN6_RP_STATE_CAP); diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index 6a3246240e81..c8fadf58d836 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -214,13 +214,8 @@ static void xehp_sseu_info_init(struct intel_gt *gt) int num_compute_regs, num_geometry_regs; int eu; - if (IS_PONTEVECCHIO(gt->i915)) { - num_geometry_regs = 0; - num_compute_regs = 2; - } else { - num_geometry_regs = 1; - num_compute_regs = 1; - } + num_geometry_regs = 1; + num_compute_regs = 1; /* * The concept of slice has been removed in Xe_HP. To be compatible @@ -642,7 +637,7 @@ void intel_sseu_info_init(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) xehp_sseu_info_init(gt); else if (GRAPHICS_VER(i915) >= 12) gen12_sseu_info_init(gt); @@ -851,7 +846,7 @@ void intel_sseu_print_topology(struct drm_i915_private *i915, { if (sseu->max_slices == 0) drm_printf(p, "Unavailable\n"); - else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) sseu_print_xehp_topology(sseu, p); else sseu_print_hsw_topology(sseu, p); diff --git a/drivers/gpu/drm/i915/gt/intel_tlb.c b/drivers/gpu/drm/i915/gt/intel_tlb.c index 4bb13d1890e3..756e9ebbc725 100644 --- a/drivers/gpu/drm/i915/gt/intel_tlb.c +++ b/drivers/gpu/drm/i915/gt/intel_tlb.c @@ -132,7 +132,7 @@ void intel_gt_invalidate_tlb_full(struct intel_gt *gt, u32 seqno) return; with_intel_gt_pm_if_awake(gt, wakeref) { - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); mutex_lock(>->tlb.invalidate_lock); if (tlb_seqno_passed(gt, seqno)) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 25413809b9dc..68b6aa11bcf7 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -10,6 +10,7 @@ #include "intel_engine_regs.h" #include "intel_gpu_commands.h" #include "intel_gt.h" +#include "intel_gt_ccs_mode.h" #include "intel_gt_mcr.h" #include "intel_gt_print.h" #include "intel_gt_regs.h" @@ -51,7 +52,8 @@ * registers belonging to BCS, VCS or VECS should be implemented in * xcs_engine_wa_init(). Workarounds for registers not belonging to a specific * engine's MMIO range but that are part of of the common RCS/CCS reset domain - * should be implemented in general_render_compute_wa_init(). + * should be implemented in general_render_compute_wa_init(). The settings + * about the CCS load balancing should be added in ccs_engine_wa_mode(). * * - GT workarounds: the list of these WAs is applied whenever these registers * revert to their default values: on GPU reset, suspend/resume [1]_, etc. @@ -257,12 +259,6 @@ wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 set) wa_write_clr_set(wal, reg, ~0, set); } -static void -wa_mcr_write(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 set) -{ - wa_mcr_write_clr_set(wal, reg, ~0, set); -} - static void wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set) { @@ -918,12 +914,8 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine, if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74))) xelpg_ctx_workarounds_init(engine, wal); - else if (IS_PONTEVECCHIO(i915)) - ; /* noop; none at this time */ else if (IS_DG2(i915)) dg2_ctx_workarounds_init(engine, wal); - else if (IS_XEHPSDV(i915)) - ; /* noop; none at this time */ else if (IS_DG1(i915)) dg1_ctx_workarounds_init(engine, wal); else if (GRAPHICS_VER(i915) == 12) @@ -1350,9 +1342,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal) gt->steering_table[MSLICE] = NULL; } - if (IS_XEHPSDV(gt->i915) && slice_mask & BIT(0)) - gt->steering_table[GAM] = NULL; - slice = __ffs(slice_mask); subslice = intel_sseu_find_first_xehp_dss(sseu, GEN_DSS_PER_GSLICE, slice) % GEN_DSS_PER_GSLICE; @@ -1379,20 +1368,6 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal) __set_mcr_steering(wal, GAM_MCR_SELECTOR, 1, 0); } -static void -pvc_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal) -{ - unsigned int dss; - - /* - * Setup implicit steering for COMPUTE and DSS ranges to the first - * non-fused-off DSS. All other types of MCR registers will be - * explicitly steered. - */ - dss = intel_sseu_find_first_xehp_dss(>->info.sseu, 0, 0); - __add_mcr_wa(gt, wal, dss / GEN_DSS_PER_CSLICE, dss % GEN_DSS_PER_CSLICE); -} - static void icl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { @@ -1519,76 +1494,6 @@ dg1_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE2, VSUNIT_CLKGATE_DIS_TGL); } -static void -xehpsdv_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) -{ - struct drm_i915_private *i915 = gt->i915; - - xehp_init_mcr(gt, wal); - - /* Wa_1409757795:xehpsdv */ - wa_mcr_write_or(wal, SCCGCTL94DC, CG3DDISURB); - - /* Wa_18011725039:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A1, STEP_B0)) { - wa_mcr_masked_dis(wal, MLTICTXCTL, TDONRENDER); - wa_mcr_write_or(wal, L3SQCREG1_CCS0, FLUSHALLNONCOH); - } - - /* Wa_16011155590:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A0, STEP_B0)) - wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE, - TSGUNIT_CLKGATE_DIS); - - /* Wa_14011780169:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_B0, STEP_FOREVER)) { - wa_write_or(wal, UNSLCGCTL9440, GAMTLBOACS_CLKGATE_DIS | - GAMTLBVDBOX7_CLKGATE_DIS | - GAMTLBVDBOX6_CLKGATE_DIS | - GAMTLBVDBOX5_CLKGATE_DIS | - GAMTLBVDBOX4_CLKGATE_DIS | - GAMTLBVDBOX3_CLKGATE_DIS | - GAMTLBVDBOX2_CLKGATE_DIS | - GAMTLBVDBOX1_CLKGATE_DIS | - GAMTLBVDBOX0_CLKGATE_DIS | - GAMTLBKCR_CLKGATE_DIS | - GAMTLBGUC_CLKGATE_DIS | - GAMTLBBLT_CLKGATE_DIS); - wa_write_or(wal, UNSLCGCTL9444, GAMTLBGFXA0_CLKGATE_DIS | - GAMTLBGFXA1_CLKGATE_DIS | - GAMTLBCOMPA0_CLKGATE_DIS | - GAMTLBCOMPA1_CLKGATE_DIS | - GAMTLBCOMPB0_CLKGATE_DIS | - GAMTLBCOMPB1_CLKGATE_DIS | - GAMTLBCOMPC0_CLKGATE_DIS | - GAMTLBCOMPC1_CLKGATE_DIS | - GAMTLBCOMPD0_CLKGATE_DIS | - GAMTLBCOMPD1_CLKGATE_DIS | - GAMTLBMERT_CLKGATE_DIS | - GAMTLBVEBOX3_CLKGATE_DIS | - GAMTLBVEBOX2_CLKGATE_DIS | - GAMTLBVEBOX1_CLKGATE_DIS | - GAMTLBVEBOX0_CLKGATE_DIS); - } - - /* Wa_16012725990:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A1, STEP_FOREVER)) - wa_write_or(wal, UNSLICE_UNIT_LEVEL_CLKGATE, VFUNIT_CLKGATE_DIS); - - /* Wa_14011060649:xehpsdv */ - wa_14011060649(gt, wal); - - /* Wa_14012362059:xehpsdv */ - wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB); - - /* Wa_14014368820:xehpsdv */ - wa_mcr_write_or(wal, XEHP_GAMCNTRL_CTRL, - INVALIDATION_BROADCAST_MODE_DIS | GLOBAL_INVALIDATION_MODE); - - /* Wa_14010670810:xehpsdv */ - wa_mcr_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE); -} - static void dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { @@ -1631,24 +1536,6 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) wa_mcr_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE); } -static void -pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) -{ - pvc_init_mcr(gt, wal); - - /* Wa_14015795083 */ - wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE); - - /* Wa_18018781329 */ - wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, XEHP_VDBX_MOD_CTRL, FORCE_MISS_FTLB); - wa_mcr_write_or(wal, XEHP_VEBX_MOD_CTRL, FORCE_MISS_FTLB); - - /* Wa_16016694945 */ - wa_mcr_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC); -} - static void xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal) { @@ -1725,12 +1612,6 @@ static void gt_tuning_settings(struct intel_gt *gt, struct i915_wa_list *wal) wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS); } - if (IS_PONTEVECCHIO(gt->i915)) { - wa_mcr_write(wal, XEHPC_L3SCRUB, - SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK); - wa_mcr_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_HOSTCACHEEN); - } - if (IS_DG2(gt->i915)) { wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS); wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS); @@ -1755,12 +1636,8 @@ gt_init_workarounds(struct intel_gt *gt, struct i915_wa_list *wal) if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) xelpg_gt_workarounds_init(gt, wal); - else if (IS_PONTEVECCHIO(i915)) - pvc_gt_workarounds_init(gt, wal); else if (IS_DG2(i915)) dg2_gt_workarounds_init(gt, wal); - else if (IS_XEHPSDV(i915)) - xehpsdv_gt_workarounds_init(gt, wal); else if (IS_DG1(i915)) dg1_gt_workarounds_init(gt, wal); else if (GRAPHICS_VER(i915) == 12) @@ -2178,30 +2055,6 @@ static void dg2_whitelist_build(struct intel_engine_cs *engine) } } -static void blacklist_trtt(struct intel_engine_cs *engine) -{ - struct i915_wa_list *w = &engine->whitelist; - - /* - * Prevent read/write access to [0x4400, 0x4600) which covers - * the TRTT range across all engines. Note that normally userspace - * cannot access the other engines' trtt control, but for simplicity - * we cover the entire range on each engine. - */ - whitelist_reg_ext(w, _MMIO(0x4400), - RING_FORCE_TO_NONPRIV_DENY | - RING_FORCE_TO_NONPRIV_RANGE_64); - whitelist_reg_ext(w, _MMIO(0x4500), - RING_FORCE_TO_NONPRIV_DENY | - RING_FORCE_TO_NONPRIV_RANGE_64); -} - -static void pvc_whitelist_build(struct intel_engine_cs *engine) -{ - /* Wa_16014440446:pvc */ - blacklist_trtt(engine); -} - static void xelpg_whitelist_build(struct intel_engine_cs *engine) { struct i915_wa_list *w = &engine->whitelist; @@ -2228,12 +2081,8 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine) ; /* none yet */ else if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74))) xelpg_whitelist_build(engine); - else if (IS_PONTEVECCHIO(i915)) - pvc_whitelist_build(engine); else if (IS_DG2(i915)) dg2_whitelist_build(engine); - else if (IS_XEHPSDV(i915)) - ; /* none needed */ else if (GRAPHICS_VER(i915) == 12) tgl_whitelist_build(engine); else if (GRAPHICS_VER(i915) == 11) @@ -2814,10 +2663,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) static void ccs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) { - if (IS_PVC_CT_STEP(engine->i915, STEP_A0, STEP_C0)) { - /* Wa_14014999345:pvc */ - wa_mcr_masked_en(wal, GEN10_CACHE_MODE_SS, DISABLE_ECC); - } + /* boilerplate for any CCS engine workaround */ } /* @@ -2850,10 +2696,32 @@ add_render_compute_tuning_settings(struct intel_gt *gt, wa_mcr_masked_field_set(wal, GEN9_ROW_CHICKEN4, THREAD_EX_ARB_MODE, THREAD_EX_ARB_MODE_RR_AFTER_DEP); - if (GRAPHICS_VER(i915) == 12 && GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) + if (GRAPHICS_VER(i915) == 12 && GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) wa_write_clr(wal, GEN8_GARBCNTL, GEN12_BUS_HASH_CTL_BIT_EXC); } +static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_list *wal) +{ + struct intel_gt *gt = engine->gt; + + if (!IS_DG2(gt->i915)) + return; + + /* + * Wa_14019159160: This workaround, along with others, leads to + * significant challenges in utilizing load balancing among the + * CCS slices. Consequently, an architectural decision has been + * made to completely disable automatic CCS load balancing. + */ + wa_masked_en(wal, GEN12_RCU_MODE, XEHP_RCU_MODE_FIXED_SLICE_CCS_MODE); + + /* + * After having disabled automatic load balancing we need to + * assign all slices to a single CCS. We will call it CCS mode 1 + */ + intel_gt_apply_ccs_mode(gt); +} + /* * The workarounds in this function apply to shared registers in * the general render reset domain that aren't tied to a @@ -2892,10 +2760,14 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) || IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER) || - IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74))) + IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74))) { /* Wa_14017856879 */ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH); + /* Wa_14020495402 */ + wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2, XELPG_DISABLE_TDL_SVHS_GATING); + } + if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_A0, STEP_B0) || IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_A0, STEP_B0)) /* @@ -2923,21 +2795,15 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_A0, STEP_B0) || IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_A0, STEP_B0) || - IS_PONTEVECCHIO(i915) || IS_DG2(i915)) { /* Wa_22014226127 */ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE); } - if (IS_PONTEVECCHIO(i915) || IS_DG2(i915)) { + if (IS_DG2(i915)) { /* Wa_14015227452:dg2,pvc */ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, XEHP_DIS_BBL_SYSPIPE); - /* Wa_16015675438:dg2,pvc */ - wa_masked_en(wal, FF_SLICE_CS_CHICKEN2, GEN12_PERF_FIX_BALANCING_CFE_DISABLE); - } - - if (IS_DG2(i915)) { /* * Wa_16011620976:dg2_g11 * Wa_22015475538:dg2 @@ -2973,22 +2839,6 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li 0 /* write-only, so skip validation */, true); } - - if (IS_XEHPSDV(i915)) { - /* Wa_1409954639 */ - wa_mcr_masked_en(wal, - GEN8_ROW_CHICKEN, - SYSTOLIC_DOP_CLOCK_GATING_DIS); - - /* Wa_1607196519 */ - wa_mcr_masked_en(wal, - GEN9_ROW_CHICKEN4, - GEN12_DISABLE_GRF_CLEAR); - - /* Wa_14010449647:xehpsdv */ - wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN1, - GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE); - } } static void @@ -3004,8 +2854,10 @@ engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal * to a single RCS/CCS engine's workaround list since * they're reset as part of the general render domain reset. */ - if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) + if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) { general_render_compute_wa_init(engine, wal); + ccs_engine_wa_mode(engine, wal); + } if (engine->class == COMPUTE_CLASS) ccs_engine_wa_init(engine, wal); @@ -3069,7 +2921,7 @@ static bool mcr_range(struct drm_i915_private *i915, u32 offset) const struct i915_range *mcr_ranges; int i; - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) mcr_ranges = mcr_ranges_xehp; else if (GRAPHICS_VER(i915) >= 12) mcr_ranges = mcr_ranges_gen12; diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c index 0dd4d00ee894..9ce8ff1c04fe 100644 --- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c +++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c @@ -319,7 +319,7 @@ static int igt_hang_sanitycheck(void *arg) i915_request_add(rq); timeout = 0; - intel_wedge_on_timeout(&w, gt, HZ / 10 /* 100ms */) + intel_wedge_on_timeout(&w, gt, HZ / 5 /* 200ms */) timeout = i915_request_wait(rq, 0, MAX_SCHEDULE_TIMEOUT); if (intel_gt_is_wedged(gt)) diff --git a/drivers/gpu/drm/i915/gt/selftest_reset.c b/drivers/gpu/drm/i915/gt/selftest_reset.c index f40de408cd3a..2cfc23c58e90 100644 --- a/drivers/gpu/drm/i915/gt/selftest_reset.c +++ b/drivers/gpu/drm/i915/gt/selftest_reset.c @@ -281,7 +281,7 @@ static int igt_atomic_reset(void *arg) awake = reset_prepare(gt); p->critical_section_begin(); - err = __intel_gt_reset(gt, ALL_ENGINES); + err = intel_gt_reset_all_engines(gt); p->critical_section_end(); reset_finish(gt, awake); diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index 302d0540295d..4ecc4ae74a54 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -53,7 +53,7 @@ static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq) static int slpc_set_freq(struct intel_gt *gt, u32 freq) { int err; - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; err = slpc_set_max_freq(slpc, freq); if (err) { @@ -182,7 +182,7 @@ static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, static int slpc_power(struct intel_gt *gt, struct intel_engine_cs *engine) { - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; struct { u64 power; int freq; @@ -262,7 +262,7 @@ static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, static int run_test(struct intel_gt *gt, int test_type) { - struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_guc_slpc *slpc = >_to_guc(gt)->slpc; struct intel_rps *rps = >->rps; struct intel_engine_cs *engine; enum intel_engine_id id; diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h index 811add10c30d..c34674e797c6 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h @@ -207,6 +207,27 @@ struct slpc_shared_data { u8 reserved_mode_definition[4096]; } __packed; +struct slpc_context_frequency_request { + u32 frequency_request:16; + u32 reserved:12; + u32 is_compute:1; + u32 ignore_busyness:1; + u32 is_minimum:1; + u32 is_predefined:1; +} __packed; + +#define SLPC_CTX_FREQ_REQ_IS_COMPUTE REG_BIT(28) + +struct slpc_optimized_strategies { + u32 compute:1; + u32 async_flip:1; + u32 media:1; + u32 vsync_flip:1; + u32 reserved:28; +} __packed; + +#define SLPC_OPTIMIZED_STRATEGY_COMPUTE REG_BIT(0) + /** * DOC: SLPC H2G MESSAGE FORMAT * diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index dabeaf4f245f..00d6402333f8 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -36,6 +36,7 @@ enum intel_guc_load_status { INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_START, INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID = 0x73, INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID = 0x74, + INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR = 0x75, INTEL_GUC_LOAD_STATUS_INVALID_INIT_DATA_RANGE_END, INTEL_GUC_LOAD_STATUS_READY = 0xF0, diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h index 58012edd4eb0..bebf28e3c479 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h @@ -101,4 +101,11 @@ enum { GUC_CONTEXT_POLICIES_KLV_NUM_IDS = 5, }; +/* + * Workaround keys: + */ +enum { + GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE = 0x9001, +}; + #endif /* _ABI_GUC_KLVS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c index e2e42b3e0d5d..3b69bc6616bd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_fw.c @@ -298,7 +298,7 @@ static int gsc_fw_load_prepare(struct intel_gsc_uc *gsc) memcpy_toio(gsc->local_vaddr, src, gsc->fw.size); memset_io(gsc->local_vaddr + gsc->fw.size, 0, gsc->local->size - gsc->fw.size); - intel_guc_write_barrier(>->uc.guc); + intel_guc_write_barrier(gt_to_guc(gt)); i915_gem_object_unpin_map(gsc->fw.obj); @@ -351,7 +351,7 @@ static int gsc_fw_query_compatibility_version(struct intel_gsc_uc *gsc) void *vaddr; int err; - err = intel_guc_allocate_and_map_vma(>->uc.guc, GSC_VER_PKT_SZ * 2, + err = intel_guc_allocate_and_map_vma(gt_to_guc(gt), GSC_VER_PKT_SZ * 2, &vma, &vaddr); if (err) { gt_err(gt, "failed to allocate vma for GSC version query\n"); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c index 40817ebcca71..a7d5465655f9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_gsc_proxy.c @@ -358,7 +358,8 @@ static int proxy_channel_alloc(struct intel_gsc_uc *gsc) void *vaddr; int err; - err = intel_guc_allocate_and_map_vma(>->uc.guc, GSC_PROXY_CHANNEL_SIZE, + err = intel_guc_allocate_and_map_vma(gt_to_guc(gt), + GSC_PROXY_CHANNEL_SIZE, &vma, &vaddr); if (err) return err; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 2b450c43bbd7..5e60a34692af 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -286,7 +286,7 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) /* Wa_22012773006:gen11,gen12 < XeHP */ if (GRAPHICS_VER(gt->i915) >= 11 && - GRAPHICS_VER_FULL(gt->i915) < IP_VER(12, 50)) + GRAPHICS_VER_FULL(gt->i915) < IP_VER(12, 55)) flags |= GUC_WA_POLLCS; /* Wa_14014475959 */ @@ -294,6 +294,11 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) IS_DG2(gt->i915)) flags |= GUC_WA_HOLD_CCS_SWITCHOUT; + /* Wa_16019325821 */ + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) + flags |= GUC_WA_RCS_CCS_SWITCHOUT; + /* * Wa_14012197797 * Wa_22011391025 @@ -315,15 +320,12 @@ static u32 guc_ctl_wa_flags(struct intel_guc *guc) if (IS_DG2_G11(gt->i915)) flags |= GUC_WA_CONTEXT_ISOLATION; - /* Wa_16015675438 */ - if (!RCS_MASK(gt)) - flags |= GUC_WA_RCS_REGS_IN_CCS_REGS_LIST; - - /* Wa_14018913170 */ - if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) { - if (IS_DG2(gt->i915) || IS_METEORLAKE(gt->i915) || IS_PONTEVECCHIO(gt->i915)) - flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; - } + /* + * Wa_14018913170: Applicable to all platforms supported by i915 so + * don't bother testing for all X/Y/Z platforms explicitly. + */ + if (GUC_FIRMWARE_VER(guc) >= MAKE_GUC_VER(70, 7, 0)) + flags |= GUC_WA_ENABLE_TSC_CHECK_ON_RC6; return flags; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index be70c46604b4..57b903132776 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -204,6 +204,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_waklv_size: size of workaround KLVs */ + u32 ads_waklv_size; /** @ads_capture_size: size of register lists in the ADS used for error capture */ u32 ads_capture_size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index f7372f736a77..c606bb5e3b7b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -46,6 +46,10 @@ * +---------------------------------------+ * | padding | * +---------------------------------------+ <== 4K aligned + * | w/a KLVs | + * +---------------------------------------+ + * | padding | + * +---------------------------------------+ <== 4K aligned * | capture lists | * +---------------------------------------+ * | padding | @@ -88,6 +92,11 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) return PAGE_ALIGN(guc->ads_golden_ctxt_size); } +static u32 guc_ads_waklv_size(struct intel_guc *guc) +{ + return PAGE_ALIGN(guc->ads_waklv_size); +} + static u32 guc_ads_capture_size(struct intel_guc *guc) { return PAGE_ALIGN(guc->ads_capture_size); @@ -113,7 +122,7 @@ static u32 guc_ads_golden_ctxt_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } -static u32 guc_ads_capture_offset(struct intel_guc *guc) +static u32 guc_ads_waklv_offset(struct intel_guc *guc) { u32 offset; @@ -123,6 +132,16 @@ static u32 guc_ads_capture_offset(struct intel_guc *guc) return PAGE_ALIGN(offset); } +static u32 guc_ads_capture_offset(struct intel_guc *guc) +{ + u32 offset; + + offset = guc_ads_waklv_offset(guc) + + guc_ads_waklv_size(guc); + + return PAGE_ALIGN(offset); +} + static u32 guc_ads_private_data_offset(struct intel_guc *guc) { u32 offset; @@ -393,7 +412,7 @@ static int guc_mmio_regset_init(struct temp_regset *regset, /* add in local MOCS registers */ for (i = 0; i < LNCFCMOCS_REG_COUNT; i++) - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) ret |= GUC_MCR_REG_ADD(gt, regset, XEHP_LNCFCMOCS(i), false); else ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false); @@ -503,7 +522,7 @@ static void fill_engine_enable_masks(struct intel_gt *gt, #define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) #define XEHP_LR_HW_CONTEXT_SIZE (96 * sizeof(u32)) -#define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50) ? \ +#define LR_HW_CONTEXT_SZ(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55) ? \ XEHP_LR_HW_CONTEXT_SIZE : \ LR_HW_CONTEXT_SIZE) #define LRC_SKIP_SIZE(i915) (LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SZ(i915)) @@ -796,6 +815,65 @@ guc_capture_prep_lists(struct intel_guc *guc) return PAGE_ALIGN(total_size); } +/* Wa_14019159160 */ +static u32 guc_waklv_ra_mode(struct intel_guc *guc, u32 offset, u32 remain) +{ + u32 size; + u32 klv_entry[] = { + /* 16:16 key/length */ + FIELD_PREP(GUC_KLV_0_KEY, GUC_WORKAROUND_KLV_SERIALIZED_RA_MODE) | + FIELD_PREP(GUC_KLV_0_LEN, 0), + /* 0 dwords data */ + }; + + size = sizeof(klv_entry); + GEM_BUG_ON(remain < size); + + iosys_map_memcpy_to(&guc->ads_map, offset, klv_entry, size); + + return size; +} + +static void guc_waklv_init(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + u32 offset, addr_ggtt, remain, size; + + if (!intel_uc_uses_guc_submission(>->uc)) + return; + + if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 10, 0)) + return; + + GEM_BUG_ON(iosys_map_is_null(&guc->ads_map)); + offset = guc_ads_waklv_offset(guc); + remain = guc_ads_waklv_size(guc); + + /* Wa_14019159160 */ + if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) { + size = guc_waklv_ra_mode(guc, offset, remain); + offset += size; + remain -= size; + } + + size = guc_ads_waklv_size(guc) - remain; + if (!size) + return; + + offset = guc_ads_waklv_offset(guc); + addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + + ads_blob_write(guc, ads.wa_klv_addr_lo, addr_ggtt); + ads_blob_write(guc, ads.wa_klv_addr_hi, 0); + ads_blob_write(guc, ads.wa_klv_size, size); +} + +static int guc_prep_waklv(struct intel_guc *guc) +{ + /* Fudge something chunky for now: */ + return PAGE_SIZE; +} + static void __guc_ads_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); @@ -843,6 +921,9 @@ static void __guc_ads_init(struct intel_guc *guc) /* MMIO save/restore list */ guc_mmio_reg_state_init(guc); + /* Workaround KLV list */ + guc_waklv_init(guc); + /* Private Data */ ads_blob_write(guc, ads.private_data, base + guc_ads_private_data_offset(guc)); @@ -886,6 +967,12 @@ int intel_guc_ads_create(struct intel_guc *guc) return ret; guc->ads_capture_size = ret; + /* And don't forget the workaround KLVs: */ + ret = guc_prep_waklv(guc); + if (ret < 0) + return ret; + guc->ads_waklv_size = ret; + /* Now the total size can be determined: */ size = guc_ads_blob_size(guc); @@ -961,7 +1048,7 @@ u32 intel_guc_engine_usage_offset(struct intel_guc *guc) struct iosys_map intel_guc_engine_usage_record_map(struct intel_engine_cs *engine) { - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); u8 guc_class = engine_class_to_guc_class(engine->class); size_t offset = offsetof(struct __guc_ads_blob, engine_usage.engines[guc_class][ilog2(engine->logical_mask)]); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index a1cd40d80517..9547fff672bd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -51,6 +51,7 @@ { RING_ESR(0), 0, 0, "ESR" }, \ { RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW" }, \ { RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW" }, \ + { RING_EIR(0), 0, 0, "EIR" }, \ { RING_IPEIR(0), 0, 0, "IPEIR" }, \ { RING_IPEHR(0), 0, 0, "IPEHR" }, \ { RING_INSTPS(0), 0, 0, "INSTPS" }, \ @@ -80,9 +81,6 @@ { GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW" }, \ { GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW" } -#define COMMON_BASE_HAS_EU \ - { EIR, 0, 0, "EIR" } - #define COMMON_BASE_RENDER \ { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" } @@ -105,7 +103,6 @@ static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = { /* XE_LP Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lp_rc_class_regs[] = { - COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, COMMON_GEN12BASE_RENDER, }; @@ -148,7 +145,6 @@ static const struct __guc_mmio_reg_descr gen8_global_regs[] = { }; static const struct __guc_mmio_reg_descr gen8_rc_class_regs[] = { - COMMON_BASE_HAS_EU, COMMON_BASE_RENDER, }; @@ -1441,7 +1437,7 @@ int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, if (!cap || !ee->engine) return -ENODEV; - guc = &ee->engine->gt->uc.guc; + guc = gt_to_guc(ee->engine->gt); i915_error_printf(ebuf, "global --- GuC Error Capture on %s command stream:\n", ee->engine->name); @@ -1543,7 +1539,7 @@ bool intel_guc_capture_is_matching_engine(struct intel_gt *gt, if (!gt || !ce || !engine) return false; - guc = >->uc.guc; + guc = gt_to_guc(gt); if (!guc->capture) return false; @@ -1573,7 +1569,7 @@ void intel_guc_capture_get_matching_node(struct intel_gt *gt, if (!gt || !ee || !ce) return; - guc = >->uc.guc; + guc = gt_to_guc(gt); if (!guc->capture) return; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c index 52332bb14339..23f54c84cbab 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c @@ -26,7 +26,7 @@ static void guc_prepare_xfer(struct intel_gt *gt) GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | GUC_ENABLE_MIA_CLOCK_GATING; - if (GRAPHICS_VER_FULL(uncore->i915) < IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(uncore->i915) < IP_VER(12, 55)) shim_flags |= GUC_DISABLE_SRAM_INIT_TO_ZEROES | GUC_ENABLE_MIA_CACHING; @@ -115,6 +115,7 @@ static inline bool guc_load_done(struct intel_uncore *uncore, u32 *status, bool case INTEL_GUC_LOAD_STATUS_INIT_DATA_INVALID: case INTEL_GUC_LOAD_STATUS_MPU_DATA_INVALID: case INTEL_GUC_LOAD_STATUS_INIT_MMIO_SAVE_RESTORE_INVALID: + case INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR: *success = false; return true; } @@ -241,6 +242,11 @@ static int guc_wait_ucode(struct intel_guc *guc) ret = -EPERM; break; + case INTEL_GUC_LOAD_STATUS_KLV_WORKAROUND_INIT_ERROR: + guc_info(guc, "invalid w/a KLV entry\n"); + ret = -EINVAL; + break; + case INTEL_GUC_LOAD_STATUS_HWCONFIG_START: guc_info(guc, "still extracting hwconfig table.\n"); ret = -ETIMEDOUT; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 8ae1846431da..14797e80bc92 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -96,8 +96,9 @@ #define GUC_WA_GAM_CREDITS BIT(10) #define GUC_WA_DUAL_QUEUE BIT(11) #define GUC_WA_RCS_RESET_BEFORE_RC6 BIT(13) -#define GUC_WA_CONTEXT_ISOLATION BIT(15) #define GUC_WA_PRE_PARSER BIT(14) +#define GUC_WA_CONTEXT_ISOLATION BIT(15) +#define GUC_WA_RCS_CCS_SWITCHOUT BIT(16) #define GUC_WA_HOLD_CCS_SWITCHOUT BIT(17) #define GUC_WA_POLLCS BIT(18) #define GUC_WA_RCS_REGS_IN_CCS_REGS_LIST BIT(21) @@ -430,7 +431,10 @@ struct guc_ads { u32 capture_instance[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; u32 capture_class[GUC_CAPTURE_LIST_INDEX_MAX][GUC_MAX_ENGINE_CLASSES]; u32 capture_global[GUC_CAPTURE_LIST_INDEX_MAX]; - u32 reserved[14]; + u32 wa_klv_addr_lo; + u32 wa_klv_addr_hi; + u32 wa_klv_size; + u32 reserved[11]; } __packed; /* Engine usage stats */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c index cc9569af7f0c..b67a15f74276 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c @@ -111,7 +111,7 @@ static bool has_table(struct drm_i915_private *i915) static int guc_hwconfig_init(struct intel_gt *gt) { struct intel_hwconfig *hwconfig = >->info.hwconfig; - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); int ret; if (!has_table(gt->i915)) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index 3e681ab6fbf9..706fffca698b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -537,6 +537,20 @@ int intel_guc_slpc_get_min_freq(struct intel_guc_slpc *slpc, u32 *val) return ret; } +int intel_guc_slpc_set_strategy(struct intel_guc_slpc *slpc, u32 val) +{ + struct drm_i915_private *i915 = slpc_to_i915(slpc); + intel_wakeref_t wakeref; + int ret = 0; + + with_intel_runtime_pm(&i915->runtime_pm, wakeref) + ret = slpc_set_param(slpc, + SLPC_PARAM_STRATEGIES, + val); + + return ret; +} + int intel_guc_slpc_set_media_ratio_mode(struct intel_guc_slpc *slpc, u32 val) { struct drm_i915_private *i915 = slpc_to_i915(slpc); @@ -711,6 +725,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc) /* Set cached media freq ratio mode */ intel_guc_slpc_set_media_ratio_mode(slpc, slpc->media_ratio_mode); + /* Enable SLPC Optimized Strategy for compute */ + intel_guc_slpc_set_strategy(slpc, SLPC_OPTIMIZED_STRATEGY_COMPUTE); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h index 6ac6503c39d4..1cb5fd44f05c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h @@ -45,5 +45,6 @@ void intel_guc_pm_intrmsk_enable(struct intel_gt *gt); void intel_guc_slpc_boost(struct intel_guc_slpc *slpc); void intel_guc_slpc_dec_waiters(struct intel_guc_slpc *slpc); int intel_guc_slpc_set_ignore_eff_freq(struct intel_guc_slpc *slpc, bool val); +int intel_guc_slpc_set_strategy(struct intel_guc_slpc *slpc, u32 val); #endif diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index f3dcae4b9d45..0eaa1064242c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -398,7 +398,7 @@ static inline void set_context_guc_id_invalid(struct intel_context *ce) static inline struct intel_guc *ce_to_guc(struct intel_context *ce) { - return &ce->engine->gt->uc.guc; + return gt_to_guc(ce->engine->gt); } static inline struct i915_priolist *to_priolist(struct rb_node *rb) @@ -1246,7 +1246,7 @@ static void __get_engine_usage_record(struct intel_engine_cs *engine, static void guc_update_engine_gt_clks(struct intel_engine_cs *engine) { struct intel_engine_guc_stats *stats = &engine->stats.guc; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); u32 last_switch, ctx_id, total; lockdep_assert_held(&guc->timestamp.lock); @@ -1311,7 +1311,7 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now) struct intel_engine_guc_stats stats_saved, *stats = &engine->stats.guc; struct i915_gpu_error *gpu_error = &engine->i915->gpu_error; struct intel_gt *gt = engine->gt; - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); u64 total, gt_stamp_saved; unsigned long flags; u32 reset_count; @@ -1403,14 +1403,17 @@ static void guc_cancel_busyness_worker(struct intel_guc *guc) * Trying to pass a 'need_sync' or 'in_reset' flag all the way down through * every possible call stack is unfeasible. It would be too intrusive to many * areas that really don't care about the GuC backend. However, there is the - * 'reset_in_progress' flag available, so just use that. + * I915_RESET_BACKOFF flag and the gt->reset.mutex can be tested for is_locked. + * So just use those. Note that testing both is required due to the hideously + * complex nature of the i915 driver's reset code paths. * * And note that in the case of a reset occurring during driver unload - * (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set - * is fine because there is another cancel in _finish (when the reset flag is - * not). + * (wedged_on_fini), skipping the cancel in reset_prepare/reset_fini (when the + * reset flag/mutex are set) is fine because there is another explicit cancel in + * intel_guc_submission_fini (when the reset flag/mutex are not). */ - if (guc_to_gt(guc)->uc.reset_in_progress) + if (mutex_is_locked(&guc_to_gt(guc)->reset.mutex) || + test_bit(I915_RESET_BACKOFF, &guc_to_gt(guc)->reset.flags)) cancel_delayed_work(&guc->timestamp.work); else cancel_delayed_work_sync(&guc->timestamp.work); @@ -1424,8 +1427,6 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) unsigned long flags; ktime_t unused; - guc_cancel_busyness_worker(guc); - spin_lock_irqsave(&guc->timestamp.lock, flags); guc_update_pm_timestamp(guc, &unused); @@ -1576,7 +1577,7 @@ static void guc_fini_engine_stats(struct intel_guc *guc) void intel_guc_busyness_park(struct intel_gt *gt) { - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); if (!guc_submission_initialized(guc)) return; @@ -1603,7 +1604,7 @@ void intel_guc_busyness_park(struct intel_gt *gt) void intel_guc_busyness_unpark(struct intel_gt *gt) { - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); unsigned long flags; ktime_t unused; @@ -2004,13 +2005,6 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc) void intel_guc_submission_reset_finish(struct intel_guc *guc) { - /* - * Ensure the busyness worker gets cancelled even on a fatal wedge. - * Note that reset_prepare is not allowed to because it confuses lockdep. - */ - if (guc_submission_initialized(guc)) - guc_cancel_busyness_worker(guc); - /* Reset called during driver load or during wedge? */ if (unlikely(!guc_submission_initialized(guc) || !intel_guc_is_fw_running(guc) || @@ -2136,6 +2130,7 @@ void intel_guc_submission_fini(struct intel_guc *guc) if (!guc->submission_initialized) return; + guc_fini_engine_stats(guc); guc_flush_destroyed_contexts(guc); guc_lrc_desc_pool_destroy_v69(guc); i915_sched_engine_put(guc->sched_engine); @@ -2194,7 +2189,7 @@ static bool need_tasklet(struct intel_guc *guc, struct i915_request *rq) static void guc_submit_request(struct i915_request *rq) { struct i915_sched_engine *sched_engine = rq->engine->sched_engine; - struct intel_guc *guc = &rq->engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(rq->engine->gt); unsigned long flags; /* Will be called from irq-context when using foreign fences. */ @@ -2220,11 +2215,10 @@ static int new_guc_id(struct intel_guc *guc, struct intel_context *ce) order_base_2(ce->parallel.number_children + 1)); else - ret = ida_simple_get(&guc->submission_state.guc_ids, - NUMBER_MULTI_LRC_GUC_ID(guc), - guc->submission_state.num_guc_ids, - GFP_KERNEL | __GFP_RETRY_MAYFAIL | - __GFP_NOWARN); + ret = ida_alloc_range(&guc->submission_state.guc_ids, + NUMBER_MULTI_LRC_GUC_ID(guc), + guc->submission_state.num_guc_ids - 1, + GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); if (unlikely(ret < 0)) return ret; @@ -2247,8 +2241,8 @@ static void __release_guc_id(struct intel_guc *guc, struct intel_context *ce) + 1)); } else { --guc->submission_state.guc_ids_in_use; - ida_simple_remove(&guc->submission_state.guc_ids, - ce->guc_id.id); + ida_free(&guc->submission_state.guc_ids, + ce->guc_id.id); } clr_ctx_id_mapping(guc, ce->guc_id.id); set_context_guc_id_invalid(ce); @@ -2645,6 +2639,7 @@ MAKE_CONTEXT_POLICY_ADD(execution_quantum, EXECUTION_QUANTUM) MAKE_CONTEXT_POLICY_ADD(preemption_timeout, PREEMPTION_TIMEOUT) MAKE_CONTEXT_POLICY_ADD(priority, SCHEDULING_PRIORITY) MAKE_CONTEXT_POLICY_ADD(preempt_to_idle, PREEMPT_TO_IDLE_ON_QUANTUM_EXPIRY) +MAKE_CONTEXT_POLICY_ADD(slpc_ctx_freq_req, SLPM_GT_FREQUENCY) #undef MAKE_CONTEXT_POLICY_ADD @@ -2660,10 +2655,11 @@ static int __guc_context_set_context_policies(struct intel_guc *guc, static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) { struct intel_engine_cs *engine = ce->engine; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); struct context_policy policy; u32 execution_quantum; u32 preemption_timeout; + u32 slpc_ctx_freq_req = 0; unsigned long flags; int ret; @@ -2675,11 +2671,15 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) execution_quantum = engine->props.timeslice_duration_ms * 1000; preemption_timeout = engine->props.preempt_timeout_ms * 1000; + if (ce->flags & BIT(CONTEXT_LOW_LATENCY)) + slpc_ctx_freq_req |= SLPC_CTX_FREQ_REQ_IS_COMPUTE; + __guc_context_policy_start_klv(&policy, ce->guc_id.id); __guc_context_policy_add_priority(&policy, ce->guc_state.prio); __guc_context_policy_add_execution_quantum(&policy, execution_quantum); __guc_context_policy_add_preemption_timeout(&policy, preemption_timeout); + __guc_context_policy_add_slpc_ctx_freq_req(&policy, slpc_ctx_freq_req); if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) __guc_context_policy_add_preempt_to_idle(&policy, 1); @@ -2736,7 +2736,7 @@ static u32 map_guc_prio_to_lrc_desc_prio(u8 prio) static void prepare_context_registration_info_v69(struct intel_context *ce) { struct intel_engine_cs *engine = ce->engine; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); u32 ctx_id = ce->guc_id.id; struct guc_lrc_desc_v69 *desc; struct intel_context *child; @@ -2805,7 +2805,7 @@ static void prepare_context_registration_info_v70(struct intel_context *ce, struct guc_ctxt_registration_info *info) { struct intel_engine_cs *engine = ce->engine; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); u32 ctx_id = ce->guc_id.id; GEM_BUG_ON(!engine->mask); @@ -2868,7 +2868,7 @@ static int try_context_registration(struct intel_context *ce, bool loop) { struct intel_engine_cs *engine = ce->engine; struct intel_runtime_pm *runtime_pm = engine->uncore->rpm; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); intel_wakeref_t wakeref; u32 ctx_id = ce->guc_id.id; bool context_registered; @@ -4496,7 +4496,13 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine) if (engine->class == COMPUTE_CLASS) if (IS_GFX_GT_IP_STEP(engine->gt, IP_VER(12, 70), STEP_A0, STEP_B0) || IS_DG2(engine->i915)) - engine->flags |= I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; + engine->flags |= I915_ENGINE_USES_WA_HOLD_SWITCHOUT; + + /* Wa_16019325821 */ + /* Wa_14019159160 */ + if ((engine->class == COMPUTE_CLASS || engine->class == RENDER_CLASS) && + IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71))) + engine->flags |= I915_ENGINE_USES_WA_HOLD_SWITCHOUT; /* * TODO: GuC supports timeslicing and semaphores as well, but they're @@ -4507,7 +4513,7 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine) */ engine->emit_bb_start = gen8_emit_bb_start; - if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55)) engine->emit_bb_start = xehp_emit_bb_start; } @@ -4549,7 +4555,7 @@ static void guc_sched_engine_destroy(struct kref *kref) int intel_guc_submission_setup(struct intel_engine_cs *engine) { struct drm_i915_private *i915 = engine->i915; - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); /* * The setup relies on several assumptions (e.g. irqs always enabled) @@ -5308,7 +5314,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, void intel_guc_find_hung_context(struct intel_engine_cs *engine) { - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); struct intel_context *ce; struct i915_request *rq; unsigned long index; @@ -5370,7 +5376,7 @@ void intel_guc_dump_active_requests(struct intel_engine_cs *engine, struct i915_request *hung_rq, struct drm_printer *m) { - struct intel_guc *guc = &engine->gt->uc.guc; + struct intel_guc *guc = gt_to_guc(engine->gt); struct intel_context *ce; unsigned long index; unsigned long flags; @@ -5822,7 +5828,7 @@ guc_create_virtual(struct intel_engine_cs **siblings, unsigned int count, if (!ve) return ERR_PTR(-ENOMEM); - guc = &siblings[0]->gt->uc.guc; + guc = gt_to_guc(siblings[0]->gt); ve->base.i915 = siblings[0]->i915; ve->base.gt = siblings[0]->gt; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index 0945b177d5f9..2d9152eb7282 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -385,7 +385,7 @@ int intel_huc_init(struct intel_huc *huc) if (HAS_ENGINE(gt, GSC0)) { struct i915_vma *vma; - vma = intel_guc_allocate_vma(>->uc.guc, PXP43_HUC_AUTH_INOUT_SIZE * 2); + vma = intel_guc_allocate_vma(gt_to_guc(gt), PXP43_HUC_AUTH_INOUT_SIZE * 2); if (IS_ERR(vma)) { err = PTR_ERR(vma); huc_info(huc, "Failed to allocate heci pkt\n"); @@ -540,7 +540,7 @@ int intel_huc_wait_for_auth_complete(struct intel_huc *huc, int intel_huc_auth(struct intel_huc *huc, enum intel_huc_authentication_type type) { struct intel_gt *gt = huc_to_gt(huc); - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); int ret; if (!intel_uc_fw_is_loaded(&huc->fw)) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 6dfe5d9456c6..7a63abf8f644 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -50,10 +50,6 @@ static void uc_expand_default_options(struct intel_uc *uc) /* Default: enable HuC authentication and GuC submission */ i915->params.enable_guc = ENABLE_GUC_LOAD_HUC | ENABLE_GUC_SUBMISSION; - - /* XEHPSDV and PVC do not use HuC */ - if (IS_XEHPSDV(i915) || IS_PONTEVECCHIO(i915)) - i915->params.enable_guc &= ~ENABLE_GUC_LOAD_HUC; } /* Reset GuC providing us with fresh state for both GuC and HuC. @@ -637,6 +633,10 @@ void intel_uc_reset_finish(struct intel_uc *uc) { struct intel_guc *guc = &uc->guc; + /* + * NB: The wedge code path results in prepare -> prepare -> finish -> finish. + * So this function is sometimes called with the in-progress flag not set. + */ uc->reset_in_progress = false; /* Firmware expected to be running when this function is called */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 756093eaf2ad..d80278eb45d7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -807,7 +807,7 @@ static int try_firmware_load(struct intel_uc_fw *uc_fw, const struct firmware ** static int check_mtl_huc_guc_compatibility(struct intel_gt *gt, struct intel_uc_fw_file *huc_selected) { - struct intel_uc_fw_file *guc_selected = >->uc.guc.fw.file_selected; + struct intel_uc_fw_file *guc_selected = >_to_guc(gt)->fw.file_selected; struct intel_uc_fw_ver *huc_ver = &huc_selected->ver; struct intel_uc_fw_ver *guc_ver = &guc_selected->ver; bool new_huc, new_guc; @@ -1209,7 +1209,7 @@ static int uc_fw_rsa_data_create(struct intel_uc_fw *uc_fw) * since its GGTT offset will be GuC accessible. */ GEM_BUG_ON(uc_fw->rsa_size > PAGE_SIZE); - vma = intel_guc_allocate_vma(>->uc.guc, PAGE_SIZE); + vma = intel_guc_allocate_vma(gt_to_guc(gt), PAGE_SIZE); if (IS_ERR(vma)) return PTR_ERR(vma); diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index c900aac85adb..68feb55654f7 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -144,7 +144,7 @@ static int intel_guc_scrub_ctbs(void *arg) static int intel_guc_steal_guc_ids(void *arg) { struct intel_gt *gt = arg; - struct intel_guc *guc = >->uc.guc; + struct intel_guc *guc = gt_to_guc(gt); int ret, sv, context_index = 0; intel_wakeref_t wakeref; struct intel_engine_cs *engine; diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c index e0c5dfb788eb..a0381fd230c0 100644 --- a/drivers/gpu/drm/i915/gvt/display.c +++ b/drivers/gpu/drm/i915/gvt/display.c @@ -36,6 +36,7 @@ #include "i915_reg.h" #include "gvt.h" +#include "display/bxt_dpio_phy_regs.h" #include "display/intel_display.h" #include "display/intel_dpio_phy.h" diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index efcb00472be2..f85bf59cdeaf 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -41,6 +41,7 @@ #include "gvt.h" #include "i915_pvinfo.h" #include "intel_mchbar_regs.h" +#include "display/bxt_dpio_phy_regs.h" #include "display/intel_display_types.h" #include "display/intel_dmc_regs.h" #include "display/intel_dp_aux_regs.h" @@ -2763,15 +2764,15 @@ static int init_bxt_mmio_info(struct intel_gvt *gvt) MMIO_DH(BXT_PORT_PCS_DW12_GRP(DPIO_PHY0, DPIO_CH0), D_BXT, NULL, bxt_pcs_dw12_grp_write); - MMIO_DH(BXT_PORT_TX_DW3_LN0(DPIO_PHY0, DPIO_CH0), D_BXT, + MMIO_DH(BXT_PORT_TX_DW3_LN(DPIO_PHY0, DPIO_CH0, 0), D_BXT, bxt_port_tx_dw3_read, NULL); MMIO_DH(BXT_PORT_PCS_DW12_GRP(DPIO_PHY0, DPIO_CH1), D_BXT, NULL, bxt_pcs_dw12_grp_write); - MMIO_DH(BXT_PORT_TX_DW3_LN0(DPIO_PHY0, DPIO_CH1), D_BXT, + MMIO_DH(BXT_PORT_TX_DW3_LN(DPIO_PHY0, DPIO_CH1, 0), D_BXT, bxt_port_tx_dw3_read, NULL); MMIO_DH(BXT_PORT_PCS_DW12_GRP(DPIO_PHY1, DPIO_CH0), D_BXT, NULL, bxt_pcs_dw12_grp_write); - MMIO_DH(BXT_PORT_TX_DW3_LN0(DPIO_PHY1, DPIO_CH0), D_BXT, + MMIO_DH(BXT_PORT_TX_DW3_LN(DPIO_PHY1, DPIO_CH0, 0), D_BXT, bxt_port_tx_dw3_read, NULL); MMIO_DH(BXT_DE_PLL_ENABLE, D_BXT, NULL, bxt_de_pll_enable_write); MMIO_DFH(GEN8_L3SQCREG1, D_BXT, F_CMD_ACCESS, NULL, NULL); diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 5b5def6ddef7..922711e0e30b 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -37,6 +37,7 @@ #include "i915_reg.h" #include "gvt.h" +#include "display/bxt_dpio_phy_regs.h" #include "display/intel_dpio_phy.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 990eaa029d9c..bc717cf544e4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -30,6 +30,7 @@ #include #include +#include #include #include "display/intel_display_params.h" @@ -156,18 +157,6 @@ static const char *i915_cache_level_str(struct drm_i915_gem_object *obj) case 4: return " WB (2-Way Coh)"; default: return " not defined"; } - } else if (IS_PONTEVECCHIO(i915)) { - switch (obj->pat_index) { - case 0: return " UC"; - case 1: return " WC"; - case 2: return " WT"; - case 3: return " WB"; - case 4: return " WT (CLOS1)"; - case 5: return " WB (CLOS1)"; - case 6: return " WT (CLOS2)"; - case 7: return " WT (CLOS2)"; - default: return " not defined"; - } } else if (GRAPHICS_VER(i915) >= 12) { switch (obj->pat_index) { case 0: return " WB"; diff --git a/drivers/gpu/drm/i915/i915_debugfs_params.c b/drivers/gpu/drm/i915/i915_debugfs_params.c index 8bca02025e09..33d2dcb0de65 100644 --- a/drivers/gpu/drm/i915/i915_debugfs_params.c +++ b/drivers/gpu/drm/i915/i915_debugfs_params.c @@ -4,6 +4,7 @@ */ #include +#include #include "i915_debugfs_params.h" #include "gt/intel_gt.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 4b9233c07a22..622a24305bc2 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -202,7 +202,7 @@ static void sanitize_gpu(struct drm_i915_private *i915) unsigned int i; for_each_gt(gt, i915, i) - __intel_gt_reset(gt, ALL_ENGINES); + intel_gt_reset_all_engines(gt); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e81b3b2858ac..ee0d7d5f135d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -235,25 +235,17 @@ struct drm_i915_private { /* protects the irq masks */ spinlock_t irq_lock; - bool display_irqs_enabled; - /* Sideband mailbox protection */ struct mutex sb_lock; struct pm_qos_request sb_qos; /** Cached value of IMR to avoid reads in updating the bitfield */ - union { - u32 irq_mask; - u32 de_irq_mask[I915_MAX_PIPES]; - }; - u32 pipestat_irq_mask[I915_MAX_PIPES]; + u32 irq_mask; bool preserve_bios_swizzle; unsigned int fsb_freq, mem_freq, is_ddr3; - unsigned int skl_preferred_vco_freq; - unsigned int max_dotclk_freq; unsigned int hpll_freq; unsigned int czclk_freq; @@ -350,9 +342,6 @@ struct drm_i915_private { struct intel_pxp *pxp; - /* For i915gm/i945gm vblank irq workaround */ - u8 vblank_enabled; - bool irq_enabled; struct i915_pmu pmu; @@ -544,9 +533,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_DG1(i915) IS_PLATFORM(i915, INTEL_DG1) #define IS_ALDERLAKE_S(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_S) #define IS_ALDERLAKE_P(i915) IS_PLATFORM(i915, INTEL_ALDERLAKE_P) -#define IS_XEHPSDV(i915) IS_PLATFORM(i915, INTEL_XEHPSDV) #define IS_DG2(i915) IS_PLATFORM(i915, INTEL_DG2) -#define IS_PONTEVECCHIO(i915) IS_PLATFORM(i915, INTEL_PONTEVECCHIO) #define IS_METEORLAKE(i915) IS_PLATFORM(i915, INTEL_METEORLAKE) #define IS_LUNARLAKE(i915) 0 @@ -621,17 +608,6 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_TIGERLAKE_UY(i915) \ IS_SUBPLATFORM(i915, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_UY) -#define IS_XEHPSDV_GRAPHICS_STEP(__i915, since, until) \ - (IS_XEHPSDV(__i915) && IS_GRAPHICS_STEP(__i915, since, until)) - -#define IS_PVC_BD_STEP(__i915, since, until) \ - (IS_PONTEVECCHIO(__i915) && \ - IS_BASEDIE_STEP(__i915, since, until)) - -#define IS_PVC_CT_STEP(__i915, since, until) \ - (IS_PONTEVECCHIO(__i915) && \ - IS_GRAPHICS_STEP(__i915, since, until)) - #define IS_LP(i915) (INTEL_INFO(i915)->is_lp) #define IS_GEN9_LP(i915) (GRAPHICS_VER(i915) == 9 && IS_LP(i915)) #define IS_GEN9_BC(i915) (GRAPHICS_VER(i915) == 9 && !IS_LP(i915)) diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index 5c3fec63cb4c..a62405787e77 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -155,12 +155,18 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, */ value = 1; break; + case I915_PARAM_HAS_CONTEXT_FREQ_HINT: + if (intel_uc_uses_guc_submission(&to_gt(i915)->uc)) + value = 1; + else + value = -EINVAL; + break; case I915_PARAM_HAS_CONTEXT_ISOLATION: value = intel_engines_has_context_isolation(i915); break; case I915_PARAM_SLICE_MASK: /* Not supported from Xe_HP onward; use topology queries */ - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) return -EINVAL; value = sseu->slice_mask; @@ -169,7 +175,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, break; case I915_PARAM_SUBSLICE_MASK: /* Not supported from Xe_HP onward; use topology queries */ - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) return -EINVAL; /* Only copy bits from the first slice */ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index a0b784ebaddd..625b3c024540 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -28,6 +28,7 @@ */ #include +#include #include #include #include @@ -1245,8 +1246,7 @@ static void engine_record_registers(struct intel_engine_coredump *ee) if (MEDIA_VER(i915) >= 13 && engine->gt->type == GT_MEDIA) ee->fault_reg = intel_uncore_read(engine->uncore, XELPMP_RING_FAULT_REG); - - else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) + else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) ee->fault_reg = intel_gt_mcr_read_any(engine->gt, XEHP_RING_FAULT_REG); else if (GRAPHICS_VER(i915) >= 12) @@ -1852,7 +1852,7 @@ static void gt_record_global_regs(struct intel_gt_coredump *gt) if (GRAPHICS_VER(i915) == 7) gt->err_int = intel_uncore_read(uncore, GEN7_ERR_INT); - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { gt->fault_data0 = intel_gt_mcr_read_any((struct intel_gt *)gt->_gt, XEHP_FAULT_TLB_DATA0); gt->fault_data1 = intel_gt_mcr_read_any((struct intel_gt *)gt->_gt, diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c index c0662a022f59..49db3e09826c 100644 --- a/drivers/gpu/drm/i915/i915_hwmon.c +++ b/drivers/gpu/drm/i915/i915_hwmon.c @@ -739,12 +739,6 @@ hwm_get_preregistration_info(struct drm_i915_private *i915) hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT; hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS; hwmon->rg.energy_status_tile = INVALID_MMIO_REG; - } else if (IS_XEHPSDV(i915)) { - hwmon->rg.pkg_power_sku_unit = GT0_PACKAGE_POWER_SKU_UNIT; - hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; - hwmon->rg.pkg_rapl_limit = GT0_PACKAGE_RAPL_LIMIT; - hwmon->rg.energy_status_all = GT0_PLATFORM_ENERGY_STATUS; - hwmon->rg.energy_status_tile = GT0_PACKAGE_ENERGY_STATUS; } else { hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG; hwmon->rg.pkg_power_sku = INVALID_MMIO_REG; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8130f043693b..678d632ed043 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -702,7 +702,7 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv) gen5_gt_irq_reset(to_gt(dev_priv)); spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) + if (dev_priv->display.irq.display_irqs_enabled) vlv_display_irq_reset(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); } @@ -767,7 +767,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv) GEN3_IRQ_RESET(uncore, GEN8_PCU_); spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) + if (dev_priv->display.irq.display_irqs_enabled) vlv_display_irq_reset(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); } @@ -784,7 +784,7 @@ static void valleyview_irq_postinstall(struct drm_i915_private *dev_priv) gen5_gt_irq_postinstall(to_gt(dev_priv)); spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) + if (dev_priv->display.irq.display_irqs_enabled) vlv_display_irq_postinstall(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); @@ -838,7 +838,7 @@ static void cherryview_irq_postinstall(struct drm_i915_private *dev_priv) gen8_gt_irq_postinstall(to_gt(dev_priv)); spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) + if (dev_priv->display.irq.display_irqs_enabled) vlv_display_irq_postinstall(dev_priv); spin_unlock_irq(&dev_priv->irq_lock); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index de43048543e8..8c00169e3ab7 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -108,9 +108,6 @@ i915_param_named_unsafe(guc_firmware_path, charp, 0400, i915_param_named_unsafe(huc_firmware_path, charp, 0400, "HuC firmware path to use instead of the default one"); -i915_param_named_unsafe(dmc_firmware_path, charp, 0400, - "DMC firmware path to use instead of the default one"); - i915_param_named_unsafe(gsc_firmware_path, charp, 0400, "GSC firmware path to use instead of the default one"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 1315d7fac850..2eb3f2115ff2 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -51,7 +51,6 @@ struct drm_printer; param(int, guc_log_level, -1, 0400) \ param(char *, guc_firmware_path, NULL, 0400) \ param(char *, huc_firmware_path, NULL, 0400) \ - param(char *, dmc_firmware_path, NULL, 0400) \ param(char *, gsc_firmware_path, NULL, 0400) \ param(bool, memtest, false, 0400) \ param(int, mmio_debug, -IS_ENABLED(CONFIG_DRM_I915_DEBUG_MMIO), 0600) \ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 8b4fdeabb12a..405ca17a990b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -38,6 +38,9 @@ #include "i915_reg.h" #include "intel_pci_config.h" +__diag_push(); +__diag_ignore_all("-Woverride-init", "Allow field initialization overrides for device info"); + #define PLATFORM(x) .platform = (x) #define GEN(x) \ .__runtime.graphics.ip.ver = (x), \ @@ -59,14 +62,6 @@ [I915_CACHE_WT] = 2, \ } -#define PVC_CACHELEVEL \ - .cachelevel_to_pat = { \ - [I915_CACHE_NONE] = 0, \ - [I915_CACHE_LLC] = 3, \ - [I915_CACHE_L3_LLC] = 3, \ - [I915_CACHE_WT] = 2, \ - } - #define MTL_CACHELEVEL \ .cachelevel_to_pat = { \ [I915_CACHE_NONE] = 2, \ @@ -705,8 +700,6 @@ static const struct intel_device_info adl_p_info = { I915_GTT_PAGE_SIZE_2M #define XE_HP_FEATURES \ - .__runtime.graphics.ip.ver = 12, \ - .__runtime.graphics.ip.rel = 50, \ XE_HP_PAGE_SIZES, \ TGL_CACHELEVEL, \ .dma_mask_size = 46, \ @@ -730,32 +723,12 @@ static const struct intel_device_info adl_p_info = { .__runtime.ppgtt_size = 48, \ .__runtime.ppgtt_type = INTEL_PPGTT_FULL -#define XE_HPM_FEATURES \ - .__runtime.media.ip.ver = 12, \ - .__runtime.media.ip.rel = 50 - -__maybe_unused -static const struct intel_device_info xehpsdv_info = { - XE_HP_FEATURES, - XE_HPM_FEATURES, - DGFX_FEATURES, - PLATFORM(INTEL_XEHPSDV), - .has_64k_pages = 1, - .has_media_ratio_mode = 1, - .platform_engine_mask = - BIT(RCS0) | BIT(BCS0) | - BIT(VECS0) | BIT(VECS1) | BIT(VECS2) | BIT(VECS3) | - BIT(VCS0) | BIT(VCS1) | BIT(VCS2) | BIT(VCS3) | - BIT(VCS4) | BIT(VCS5) | BIT(VCS6) | BIT(VCS7) | - BIT(CCS0) | BIT(CCS1) | BIT(CCS2) | BIT(CCS3), - .require_force_probe = 1, -}; - #define DG2_FEATURES \ XE_HP_FEATURES, \ - XE_HPM_FEATURES, \ DGFX_FEATURES, \ + .__runtime.graphics.ip.ver = 12, \ .__runtime.graphics.ip.rel = 55, \ + .__runtime.media.ip.ver = 12, \ .__runtime.media.ip.rel = 55, \ PLATFORM(INTEL_DG2), \ .has_64k_pages = 1, \ @@ -778,33 +751,6 @@ static const struct intel_device_info ats_m_info = { .tuning_thread_rr_after_dep = 1, }; -#define XE_HPC_FEATURES \ - XE_HP_FEATURES, \ - .dma_mask_size = 52, \ - .has_3d_pipeline = 0, \ - .has_guc_deprivilege = 1, \ - .has_l3_ccs_read = 1, \ - .has_mslice_steering = 0, \ - .has_one_eu_per_fuse_bit = 1 - -__maybe_unused -static const struct intel_device_info pvc_info = { - XE_HPC_FEATURES, - XE_HPM_FEATURES, - DGFX_FEATURES, - .__runtime.graphics.ip.rel = 60, - .__runtime.media.ip.rel = 60, - PLATFORM(INTEL_PONTEVECCHIO), - .has_flat_ccs = 0, - .max_pat_index = 7, - .platform_engine_mask = - BIT(BCS0) | - BIT(VCS0) | - BIT(CCS0) | BIT(CCS1) | BIT(CCS2) | BIT(CCS3), - .require_force_probe = 1, - PVC_CACHELEVEL, -}; - static const struct intel_gt_definition xelpmp_extra_gt[] = { { .type = GT_MEDIA, @@ -842,6 +788,8 @@ static const struct intel_device_info mtl_info = { #undef PLATFORM +__diag_pop(); + /* * Make sure any device matches here are from most specific to most * general. For example, since the Quanta match is based on the subsystem diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index bd9d812b1afa..0b1cd4c7a525 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -292,7 +292,7 @@ static u32 i915_perf_stream_paranoid = true; #define OAREPORT_REASON_CTX_SWITCH (1<<3) #define OAREPORT_REASON_CLK_RATIO (1<<5) -#define HAS_MI_SET_PREDICATE(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) +#define HAS_MI_SET_PREDICATE(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) /* For sysctl proc_dointvec_minmax of i915_oa_max_sample_rate * @@ -817,7 +817,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, */ if (oa_report_ctx_invalid(stream, report) && - GRAPHICS_VER_FULL(stream->engine->i915) < IP_VER(12, 50)) { + GRAPHICS_VER_FULL(stream->engine->i915) < IP_VER(12, 55)) { ctx_id = INVALID_CTX_ID; oa_context_id_squash(stream, report32); } @@ -1419,7 +1419,7 @@ static int gen12_get_render_context_id(struct i915_perf_stream *stream) mask = ((1U << GEN12_GUC_SW_CTX_ID_WIDTH) - 1) << (GEN12_GUC_SW_CTX_ID_SHIFT - 32); - } else if (GRAPHICS_VER_FULL(stream->engine->i915) >= IP_VER(12, 50)) { + } else if (GRAPHICS_VER_FULL(stream->engine->i915) >= IP_VER(12, 55)) { ctx_id = (XEHP_MAX_CONTEXT_HW_ID - 1) << (XEHP_SW_CTX_ID_SHIFT - 32); @@ -2881,11 +2881,11 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, int ret; /* - * Wa_1508761755:xehpsdv, dg2 + * Wa_1508761755 * EU NOA signals behave incorrectly if EU clock gating is enabled. * Disable thread stall DOP gating and EU DOP gating. */ - if (IS_XEHPSDV(i915) || IS_DG2(i915)) { + if (IS_DG2(i915)) { intel_gt_mcr_multicast_write(uncore->gt, GEN8_ROW_CHICKEN, _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE)); intel_uncore_write(uncore, GEN7_ROW_CHICKEN2, @@ -2911,7 +2911,7 @@ gen12_enable_metric_set(struct i915_perf_stream *stream, /* * Initialize Super Queue Internal Cnt Register * Set PMON Enable in order to collect valid metrics. - * Enable byets per clock reporting in OA for XEHPSDV onward. + * Enable bytes per clock reporting in OA. */ sqcnt1 = GEN12_SQCNT1_PMON_ENABLE | (HAS_OA_BPC_REPORTING(i915) ? GEN12_SQCNT1_OABPC : 0); @@ -2971,10 +2971,9 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream) u32 sqcnt1; /* - * Wa_1508761755:xehpsdv, dg2 - * Enable thread stall DOP gating and EU DOP gating. + * Wa_1508761755: Enable thread stall DOP gating and EU DOP gating. */ - if (IS_XEHPSDV(i915) || IS_DG2(i915)) { + if (IS_DG2(i915)) { intel_gt_mcr_multicast_write(uncore->gt, GEN8_ROW_CHICKEN, _MASKED_BIT_DISABLE(STALL_DOP_GATING_DISABLE)); intel_uncore_write(uncore, GEN7_ROW_CHICKEN2, @@ -4123,7 +4122,7 @@ static int read_properties_unlocked(struct i915_perf *perf, props->hold_preemption = !!value; break; case DRM_I915_PERF_PROP_GLOBAL_SSEU: { - if (GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 50)) { + if (GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 55)) { drm_dbg(&perf->i915->drm, "SSEU config not supported on gfx %x\n", GRAPHICS_VER_FULL(perf->i915)); diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 3baa2f54a86e..14d9ec0ed777 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -105,7 +105,7 @@ static int query_geometry_subslices(struct drm_i915_private *i915, struct intel_engine_cs *engine; struct i915_engine_class_instance classinstance; - if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) + if (GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) return -ENODEV; classinstance = *((struct i915_engine_class_instance *)&query_item->flags); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3b2e49ce29ba..8eb6c2bf4557 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -538,24 +538,6 @@ #define CHV_TX_DW14(ch, lane) _TXLANE(ch, lane, 0xb8) #define DPIO_UPAR_SHIFT 30 -/* BXT PHY registers */ -#define _BXT_PHY0_BASE 0x6C000 -#define _BXT_PHY1_BASE 0x162000 -#define _BXT_PHY2_BASE 0x163000 -#define BXT_PHY_BASE(phy) \ - _PICK_EVEN_2RANGES(phy, 1, \ - _BXT_PHY0_BASE, _BXT_PHY0_BASE, \ - _BXT_PHY1_BASE, _BXT_PHY2_BASE) - -#define _BXT_PHY(phy, reg) \ - _MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg)) - -#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ - (BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE, \ - (reg_ch1) - _BXT_PHY0_BASE)) -#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1) \ - _MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1)) - #define BXT_P_CR_GT_DISP_PWRON _MMIO(0x138090) #define MIPIO_RST_CTRL (1 << 2) @@ -577,250 +559,6 @@ _PHY_CTL_FAMILY_DDI, _PHY_CTL_FAMILY_DDI, \ _PHY_CTL_FAMILY_EDP, _PHY_CTL_FAMILY_DDI_C)) -/* BXT PHY PLL registers */ -#define _PORT_PLL_A 0x46074 -#define _PORT_PLL_B 0x46078 -#define _PORT_PLL_C 0x4607c -#define PORT_PLL_ENABLE REG_BIT(31) -#define PORT_PLL_LOCK REG_BIT(30) -#define PORT_PLL_REF_SEL REG_BIT(27) -#define PORT_PLL_POWER_ENABLE REG_BIT(26) -#define PORT_PLL_POWER_STATE REG_BIT(25) -#define BXT_PORT_PLL_ENABLE(port) _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B) - -#define _PORT_PLL_EBB_0_A 0x162034 -#define _PORT_PLL_EBB_0_B 0x6C034 -#define _PORT_PLL_EBB_0_C 0x6C340 -#define PORT_PLL_P1_MASK REG_GENMASK(15, 13) -#define PORT_PLL_P1(p1) REG_FIELD_PREP(PORT_PLL_P1_MASK, (p1)) -#define PORT_PLL_P2_MASK REG_GENMASK(12, 8) -#define PORT_PLL_P2(p2) REG_FIELD_PREP(PORT_PLL_P2_MASK, (p2)) -#define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PLL_EBB_0_B, \ - _PORT_PLL_EBB_0_C) - -#define _PORT_PLL_EBB_4_A 0x162038 -#define _PORT_PLL_EBB_4_B 0x6C038 -#define _PORT_PLL_EBB_4_C 0x6C344 -#define PORT_PLL_RECALIBRATE REG_BIT(14) -#define PORT_PLL_10BIT_CLK_ENABLE REG_BIT(13) -#define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PLL_EBB_4_B, \ - _PORT_PLL_EBB_4_C) - -#define _PORT_PLL_0_A 0x162100 -#define _PORT_PLL_0_B 0x6C100 -#define _PORT_PLL_0_C 0x6C380 -/* PORT_PLL_0_A */ -#define PORT_PLL_M2_INT_MASK REG_GENMASK(7, 0) -#define PORT_PLL_M2_INT(m2_int) REG_FIELD_PREP(PORT_PLL_M2_INT_MASK, (m2_int)) -/* PORT_PLL_1_A */ -#define PORT_PLL_N_MASK REG_GENMASK(11, 8) -#define PORT_PLL_N(n) REG_FIELD_PREP(PORT_PLL_N_MASK, (n)) -/* PORT_PLL_2_A */ -#define PORT_PLL_M2_FRAC_MASK REG_GENMASK(21, 0) -#define PORT_PLL_M2_FRAC(m2_frac) REG_FIELD_PREP(PORT_PLL_M2_FRAC_MASK, (m2_frac)) -/* PORT_PLL_3_A */ -#define PORT_PLL_M2_FRAC_ENABLE REG_BIT(16) -/* PORT_PLL_6_A */ -#define PORT_PLL_GAIN_CTL_MASK REG_GENMASK(18, 16) -#define PORT_PLL_GAIN_CTL(x) REG_FIELD_PREP(PORT_PLL_GAIN_CTL_MASK, (x)) -#define PORT_PLL_INT_COEFF_MASK REG_GENMASK(12, 8) -#define PORT_PLL_INT_COEFF(x) REG_FIELD_PREP(PORT_PLL_INT_COEFF_MASK, (x)) -#define PORT_PLL_PROP_COEFF_MASK REG_GENMASK(3, 0) -#define PORT_PLL_PROP_COEFF(x) REG_FIELD_PREP(PORT_PLL_PROP_COEFF_MASK, (x)) -/* PORT_PLL_8_A */ -#define PORT_PLL_TARGET_CNT_MASK REG_GENMASK(9, 0) -#define PORT_PLL_TARGET_CNT(x) REG_FIELD_PREP(PORT_PLL_TARGET_CNT_MASK, (x)) -/* PORT_PLL_9_A */ -#define PORT_PLL_LOCK_THRESHOLD_MASK REG_GENMASK(3, 1) -#define PORT_PLL_LOCK_THRESHOLD(x) REG_FIELD_PREP(PORT_PLL_LOCK_THRESHOLD_MASK, (x)) -/* PORT_PLL_10_A */ -#define PORT_PLL_DCO_AMP_OVR_EN_H REG_BIT(27) -#define PORT_PLL_DCO_AMP_MASK REG_GENMASK(13, 10) -#define PORT_PLL_DCO_AMP(x) REG_FIELD_PREP(PORT_PLL_DCO_AMP_MASK, (x)) -#define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \ - _PORT_PLL_0_B, \ - _PORT_PLL_0_C) -#define BXT_PORT_PLL(phy, ch, idx) _MMIO(_PORT_PLL_BASE(phy, ch) + \ - (idx) * 4) - -/* BXT PHY common lane registers */ -#define _PORT_CL1CM_DW0_A 0x162000 -#define _PORT_CL1CM_DW0_BC 0x6C000 -#define PHY_POWER_GOOD (1 << 16) -#define PHY_RESERVED (1 << 7) -#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC) - -#define _PORT_CL1CM_DW9_A 0x162024 -#define _PORT_CL1CM_DW9_BC 0x6C024 -#define IREF0RC_OFFSET_SHIFT 8 -#define IREF0RC_OFFSET_MASK (0xFF << IREF0RC_OFFSET_SHIFT) -#define BXT_PORT_CL1CM_DW9(phy) _BXT_PHY((phy), _PORT_CL1CM_DW9_BC) - -#define _PORT_CL1CM_DW10_A 0x162028 -#define _PORT_CL1CM_DW10_BC 0x6C028 -#define IREF1RC_OFFSET_SHIFT 8 -#define IREF1RC_OFFSET_MASK (0xFF << IREF1RC_OFFSET_SHIFT) -#define BXT_PORT_CL1CM_DW10(phy) _BXT_PHY((phy), _PORT_CL1CM_DW10_BC) - -#define _PORT_CL1CM_DW28_A 0x162070 -#define _PORT_CL1CM_DW28_BC 0x6C070 -#define OCL1_POWER_DOWN_EN (1 << 23) -#define DW28_OLDO_DYN_PWR_DOWN_EN (1 << 22) -#define SUS_CLK_CONFIG 0x3 -#define BXT_PORT_CL1CM_DW28(phy) _BXT_PHY((phy), _PORT_CL1CM_DW28_BC) - -#define _PORT_CL1CM_DW30_A 0x162078 -#define _PORT_CL1CM_DW30_BC 0x6C078 -#define OCL2_LDOFUSE_PWR_DIS (1 << 6) -#define BXT_PORT_CL1CM_DW30(phy) _BXT_PHY((phy), _PORT_CL1CM_DW30_BC) - -/* The spec defines this only for BXT PHY0, but lets assume that this - * would exist for PHY1 too if it had a second channel. - */ -#define _PORT_CL2CM_DW6_A 0x162358 -#define _PORT_CL2CM_DW6_BC 0x6C358 -#define BXT_PORT_CL2CM_DW6(phy) _BXT_PHY((phy), _PORT_CL2CM_DW6_BC) -#define DW6_OLDO_DYN_PWR_DOWN_EN (1 << 28) - -/* BXT PHY Ref registers */ -#define _PORT_REF_DW3_A 0x16218C -#define _PORT_REF_DW3_BC 0x6C18C -#define GRC_DONE (1 << 22) -#define BXT_PORT_REF_DW3(phy) _BXT_PHY((phy), _PORT_REF_DW3_BC) - -#define _PORT_REF_DW6_A 0x162198 -#define _PORT_REF_DW6_BC 0x6C198 -#define GRC_CODE_SHIFT 24 -#define GRC_CODE_MASK (0xFF << GRC_CODE_SHIFT) -#define GRC_CODE_FAST_SHIFT 16 -#define GRC_CODE_FAST_MASK (0xFF << GRC_CODE_FAST_SHIFT) -#define GRC_CODE_SLOW_SHIFT 8 -#define GRC_CODE_SLOW_MASK (0xFF << GRC_CODE_SLOW_SHIFT) -#define GRC_CODE_NOM_MASK 0xFF -#define BXT_PORT_REF_DW6(phy) _BXT_PHY((phy), _PORT_REF_DW6_BC) - -#define _PORT_REF_DW8_A 0x1621A0 -#define _PORT_REF_DW8_BC 0x6C1A0 -#define GRC_DIS (1 << 15) -#define GRC_RDY_OVRD (1 << 1) -#define BXT_PORT_REF_DW8(phy) _BXT_PHY((phy), _PORT_REF_DW8_BC) - -/* BXT PHY PCS registers */ -#define _PORT_PCS_DW10_LN01_A 0x162428 -#define _PORT_PCS_DW10_LN01_B 0x6C428 -#define _PORT_PCS_DW10_LN01_C 0x6C828 -#define _PORT_PCS_DW10_GRP_A 0x162C28 -#define _PORT_PCS_DW10_GRP_B 0x6CC28 -#define _PORT_PCS_DW10_GRP_C 0x6CE28 -#define BXT_PORT_PCS_DW10_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PCS_DW10_LN01_B, \ - _PORT_PCS_DW10_LN01_C) -#define BXT_PORT_PCS_DW10_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PCS_DW10_GRP_B, \ - _PORT_PCS_DW10_GRP_C) - -#define TX2_SWING_CALC_INIT (1 << 31) -#define TX1_SWING_CALC_INIT (1 << 30) - -#define _PORT_PCS_DW12_LN01_A 0x162430 -#define _PORT_PCS_DW12_LN01_B 0x6C430 -#define _PORT_PCS_DW12_LN01_C 0x6C830 -#define _PORT_PCS_DW12_LN23_A 0x162630 -#define _PORT_PCS_DW12_LN23_B 0x6C630 -#define _PORT_PCS_DW12_LN23_C 0x6CA30 -#define _PORT_PCS_DW12_GRP_A 0x162c30 -#define _PORT_PCS_DW12_GRP_B 0x6CC30 -#define _PORT_PCS_DW12_GRP_C 0x6CE30 -#define LANESTAGGER_STRAP_OVRD (1 << 6) -#define LANE_STAGGER_MASK 0x1F -#define BXT_PORT_PCS_DW12_LN01(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PCS_DW12_LN01_B, \ - _PORT_PCS_DW12_LN01_C) -#define BXT_PORT_PCS_DW12_LN23(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PCS_DW12_LN23_B, \ - _PORT_PCS_DW12_LN23_C) -#define BXT_PORT_PCS_DW12_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_PCS_DW12_GRP_B, \ - _PORT_PCS_DW12_GRP_C) - -/* BXT PHY TX registers */ -#define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \ - ((lane) & 1) * 0x80) - -#define _PORT_TX_DW2_LN0_A 0x162508 -#define _PORT_TX_DW2_LN0_B 0x6C508 -#define _PORT_TX_DW2_LN0_C 0x6C908 -#define _PORT_TX_DW2_GRP_A 0x162D08 -#define _PORT_TX_DW2_GRP_B 0x6CD08 -#define _PORT_TX_DW2_GRP_C 0x6CF08 -#define BXT_PORT_TX_DW2_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW2_LN0_B, \ - _PORT_TX_DW2_LN0_C) -#define BXT_PORT_TX_DW2_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW2_GRP_B, \ - _PORT_TX_DW2_GRP_C) -#define MARGIN_000_SHIFT 16 -#define MARGIN_000 (0xFF << MARGIN_000_SHIFT) -#define UNIQ_TRANS_SCALE_SHIFT 8 -#define UNIQ_TRANS_SCALE (0xFF << UNIQ_TRANS_SCALE_SHIFT) - -#define _PORT_TX_DW3_LN0_A 0x16250C -#define _PORT_TX_DW3_LN0_B 0x6C50C -#define _PORT_TX_DW3_LN0_C 0x6C90C -#define _PORT_TX_DW3_GRP_A 0x162D0C -#define _PORT_TX_DW3_GRP_B 0x6CD0C -#define _PORT_TX_DW3_GRP_C 0x6CF0C -#define BXT_PORT_TX_DW3_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW3_LN0_B, \ - _PORT_TX_DW3_LN0_C) -#define BXT_PORT_TX_DW3_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW3_GRP_B, \ - _PORT_TX_DW3_GRP_C) -#define SCALE_DCOMP_METHOD (1 << 26) -#define UNIQUE_TRANGE_EN_METHOD (1 << 27) - -#define _PORT_TX_DW4_LN0_A 0x162510 -#define _PORT_TX_DW4_LN0_B 0x6C510 -#define _PORT_TX_DW4_LN0_C 0x6C910 -#define _PORT_TX_DW4_GRP_A 0x162D10 -#define _PORT_TX_DW4_GRP_B 0x6CD10 -#define _PORT_TX_DW4_GRP_C 0x6CF10 -#define BXT_PORT_TX_DW4_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW4_LN0_B, \ - _PORT_TX_DW4_LN0_C) -#define BXT_PORT_TX_DW4_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW4_GRP_B, \ - _PORT_TX_DW4_GRP_C) -#define DEEMPH_SHIFT 24 -#define DE_EMPHASIS (0xFF << DEEMPH_SHIFT) - -#define _PORT_TX_DW5_LN0_A 0x162514 -#define _PORT_TX_DW5_LN0_B 0x6C514 -#define _PORT_TX_DW5_LN0_C 0x6C914 -#define _PORT_TX_DW5_GRP_A 0x162D14 -#define _PORT_TX_DW5_GRP_B 0x6CD14 -#define _PORT_TX_DW5_GRP_C 0x6CF14 -#define BXT_PORT_TX_DW5_LN0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW5_LN0_B, \ - _PORT_TX_DW5_LN0_C) -#define BXT_PORT_TX_DW5_GRP(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ - _PORT_TX_DW5_GRP_B, \ - _PORT_TX_DW5_GRP_C) -#define DCC_DELAY_RANGE_1 (1 << 9) -#define DCC_DELAY_RANGE_2 (1 << 8) - -#define _PORT_TX_DW14_LN0_A 0x162538 -#define _PORT_TX_DW14_LN0_B 0x6C538 -#define _PORT_TX_DW14_LN0_C 0x6C938 -#define LATENCY_OPTIM_SHIFT 30 -#define LATENCY_OPTIM (1 << LATENCY_OPTIM_SHIFT) -#define BXT_PORT_TX_DW14_LN(phy, ch, lane) \ - _MMIO(_BXT_PHY_CH(phy, ch, _PORT_TX_DW14_LN0_B, \ - _PORT_TX_DW14_LN0_C) + \ - _BXT_LANE_OFFSET(lane)) - /* UAIMI scratch pad register 1 */ #define UAIMI_SPR1 _MMIO(0x4F074) /* SKL VccIO mask */ @@ -1750,8 +1488,6 @@ #define BXT_RP_STATE_CAP _MMIO(0x138170) #define GEN9_RP_STATE_LIMITS _MMIO(0x138148) -#define XEHPSDV_RP_STATE_CAP _MMIO(0x250014) -#define PVC_RP_STATE_CAP _MMIO(0x281014) #define MTL_RP_STATE_CAP _MMIO(0x138000) #define MTL_MEDIAP_STATE_CAP _MMIO(0x138020) @@ -2095,6 +1831,13 @@ #define TRANS_PUSH_EN REG_BIT(31) #define TRANS_PUSH_SEND REG_BIT(30) +#define _TRANS_VRR_VSYNC_A 0x60078 +#define TRANS_VRR_VSYNC(trans) _MMIO_TRANS2(trans, _TRANS_VRR_VSYNC_A) +#define VRR_VSYNC_END_MASK REG_GENMASK(28, 16) +#define VRR_VSYNC_END(vsync_end) REG_FIELD_PREP(VRR_VSYNC_END_MASK, (vsync_end)) +#define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) +#define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA _MMIO(0xe1100) @@ -2312,6 +2055,7 @@ * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each byte * of the infoframe structure specified by CEA-861. */ #define VIDEO_DIP_DATA_SIZE 32 +#define VIDEO_DIP_ASYNC_DATA_SIZE 36 #define VIDEO_DIP_GMP_DATA_SIZE 36 #define VIDEO_DIP_VSC_DATA_SIZE 36 #define VIDEO_DIP_PPS_DATA_SIZE 132 @@ -2350,6 +2094,8 @@ #define VIDEO_DIP_ENABLE_VS_HSW (1 << 8) #define VIDEO_DIP_ENABLE_GMP_HSW (1 << 4) #define VIDEO_DIP_ENABLE_SPD_HSW (1 << 0) +/* ADL and later: */ +#define VIDEO_DIP_ENABLE_AS_ADL REG_BIT(23) /* Panel fitting */ #define PFIT_CONTROL _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x61230) @@ -2588,6 +2334,9 @@ #define TRANSCONF_DITHER_TYPE_ST1 REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 1) #define TRANSCONF_DITHER_TYPE_ST2 REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 2) #define TRANSCONF_DITHER_TYPE_TEMP REG_FIELD_PREP(TRANSCONF_DITHER_TYPE_MASK, 3) +#define TRANSCONF_PIXEL_COUNT_SCALING_MASK REG_GENMASK(1, 0) +#define TRANSCONF_PIXEL_COUNT_SCALING_X4 1 + #define _PIPEASTAT 0x70024 #define PIPE_FIFO_UNDERRUN_STATUS (1UL << 31) #define SPRITE1_FLIP_DONE_INT_EN_VLV (1UL << 30) @@ -3053,6 +2802,7 @@ #define MCURSOR_MODE_DISABLE 0x00 #define MCURSOR_MODE_128_32B_AX 0x02 #define MCURSOR_MODE_256_32B_AX 0x03 +#define MCURSOR_MODE_64_2B 0x04 #define MCURSOR_MODE_64_32B_AX 0x07 #define MCURSOR_MODE_128_ARGB_AX (0x20 | MCURSOR_MODE_128_32B_AX) #define MCURSOR_MODE_256_ARGB_AX (0x20 | MCURSOR_MODE_256_32B_AX) @@ -4555,6 +4305,11 @@ #define GLK_CL1_PWR_DOWN REG_BIT(11) #define GLK_CL0_PWR_DOWN REG_BIT(10) +#define CHICKEN_MISC_3 _MMIO(0x42088) +#define DP_MST_DPT_DPTP_ALIGN_WA(trans) REG_BIT(9 + (trans) - TRANSCODER_A) +#define DP_MST_SHORT_HBLANK_WA(trans) REG_BIT(5 + (trans) - TRANSCODER_A) +#define DP_MST_FEC_BS_JITTER_WA(trans) REG_BIT(0 + (trans) - TRANSCODER_A) + #define CHICKEN_MISC_4 _MMIO(0x4208c) #define CHICKEN_FBC_STRIDE_OVERRIDE REG_BIT(13) #define CHICKEN_FBC_STRIDE_MASK REG_GENMASK(12, 0) @@ -4611,7 +4366,9 @@ #define DDIE_TRAINING_OVERRIDE_ENABLE REG_BIT(17) /* CHICKEN_TRANS_A only */ #define DDIE_TRAINING_OVERRIDE_VALUE REG_BIT(16) /* CHICKEN_TRANS_A only */ #define PSR2_ADD_VERTICAL_LINE_COUNT REG_BIT(15) +#define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) +#define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) #define DISP_ARB_CTL _MMIO(0x45000) #define DISP_FBC_MEMORY_WAKE REG_BIT(31) @@ -5040,6 +4797,7 @@ #define _HSW_VIDEO_DIP_SPD_DATA_A 0x602A0 #define _HSW_VIDEO_DIP_GMP_DATA_A 0x602E0 #define _HSW_VIDEO_DIP_VSC_DATA_A 0x60320 +#define _ADL_VIDEO_DIP_AS_DATA_A 0x60484 #define _GLK_VIDEO_DIP_DRM_DATA_A 0x60440 #define _HSW_VIDEO_DIP_AVI_ECC_A 0x60240 #define _HSW_VIDEO_DIP_VS_ECC_A 0x60280 @@ -5054,6 +4812,7 @@ #define _HSW_VIDEO_DIP_SPD_DATA_B 0x612A0 #define _HSW_VIDEO_DIP_GMP_DATA_B 0x612E0 #define _HSW_VIDEO_DIP_VSC_DATA_B 0x61320 +#define _ADL_VIDEO_DIP_AS_DATA_B 0x61484 #define _GLK_VIDEO_DIP_DRM_DATA_B 0x61440 #define _HSW_VIDEO_DIP_BVI_ECC_B 0x61240 #define _HSW_VIDEO_DIP_VS_ECC_B 0x61280 @@ -5083,6 +4842,9 @@ #define GLK_TVIDEO_DIP_DRM_DATA(trans, i) _MMIO_TRANS2(trans, _GLK_VIDEO_DIP_DRM_DATA_A + (i) * 4) #define ICL_VIDEO_DIP_PPS_DATA(trans, i) _MMIO_TRANS2(trans, _ICL_VIDEO_DIP_PPS_DATA_A + (i) * 4) #define ICL_VIDEO_DIP_PPS_ECC(trans, i) _MMIO_TRANS2(trans, _ICL_VIDEO_DIP_PPS_ECC_A + (i) * 4) +/*ADLP and later: */ +#define ADL_TVIDEO_DIP_AS_SDP_DATA(trans, i) _MMIO_TRANS2(trans,\ + _ADL_VIDEO_DIP_AS_DATA_A + (i) * 4) #define _HSW_STEREO_3D_CTL_A 0x70020 #define S3D_ENABLE (1 << 31) @@ -5401,7 +5163,7 @@ #define POWER_SETUP_I1_SHIFT 6 /* 10.6 fixed point format */ #define POWER_SETUP_I1_DATA_MASK REG_GENMASK(15, 0) #define GEN12_PCODE_READ_SAGV_BLOCK_TIME_US 0x23 -#define XEHP_PCODE_FREQUENCY_CONFIG 0x6e /* xehpsdv, pvc */ +#define XEHP_PCODE_FREQUENCY_CONFIG 0x6e /* pvc */ /* XEHP_PCODE_FREQUENCY_CONFIG sub-commands (param1) */ #define PCODE_MBOX_FC_SC_READ_FUSED_P0 0x0 #define PCODE_MBOX_FC_SC_READ_FUSED_PN 0x1 @@ -5566,15 +5328,6 @@ enum skl_power_gate { ((pw_idx) - ICL_PW_CTL_IDX_PW_1 + SKL_PG1) #define SKL_FUSE_PG_DIST_STATUS(pg) (1 << (27 - (pg))) -#define _ICL_AUX_REG_IDX(pw_idx) ((pw_idx) - ICL_PW_CTL_IDX_AUX_A) -#define _ICL_AUX_ANAOVRD1_A 0x162398 -#define _ICL_AUX_ANAOVRD1_B 0x6C398 -#define ICL_AUX_ANAOVRD1(pw_idx) _MMIO(_PICK(_ICL_AUX_REG_IDX(pw_idx), \ - _ICL_AUX_ANAOVRD1_A, \ - _ICL_AUX_ANAOVRD1_B)) -#define ICL_AUX_ANAOVRD1_LDO_BYPASS (1 << 7) -#define ICL_AUX_ANAOVRD1_ENABLE (1 << 0) - /* Per-pipe DDI Function Control */ #define _TRANS_DDI_FUNC_CTL_A 0x60400 #define _TRANS_DDI_FUNC_CTL_B 0x61400 @@ -5900,7 +5653,9 @@ enum skl_power_gate { #define CDCLK_FREQ_540 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 1) #define CDCLK_FREQ_337_308 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 2) #define CDCLK_FREQ_675_617 REG_FIELD_PREP(CDCLK_FREQ_SEL_MASK, 3) -#define MDCLK_SOURCE_SEL_CDCLK_PLL REG_BIT(25) +#define MDCLK_SOURCE_SEL_MASK REG_GENMASK(25, 25) +#define MDCLK_SOURCE_SEL_CD2XCLK REG_FIELD_PREP(MDCLK_SOURCE_SEL_MASK, 0) +#define MDCLK_SOURCE_SEL_CDCLK_PLL REG_FIELD_PREP(MDCLK_SOURCE_SEL_MASK, 1) #define BXT_CDCLK_CD2X_DIV_SEL_MASK REG_GENMASK(23, 22) #define BXT_CDCLK_CD2X_DIV_SEL_1 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 0) #define BXT_CDCLK_CD2X_DIV_SEL_1_5 REG_FIELD_PREP(BXT_CDCLK_CD2X_DIV_SEL_MASK, 1) diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index 0d735d5c2b35..942345548bc3 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -126,7 +126,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, return 0; err_free_blocks: - drm_buddy_free_list(mm, &bman_res->blocks); + drm_buddy_free_list(mm, &bman_res->blocks, 0); mutex_unlock(&bman->lock); err_free_res: ttm_resource_fini(man, &bman_res->base); @@ -141,7 +141,7 @@ static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); mutex_lock(&bman->lock); - drm_buddy_free_list(&bman->mm, &bman_res->blocks); + drm_buddy_free_list(&bman->mm, &bman_res->blocks, 0); bman->visible_avail += bman_res->used_visible_size; mutex_unlock(&bman->lock); @@ -345,7 +345,7 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type) ttm_set_driver_manager(bdev, type, NULL); mutex_lock(&bman->lock); - drm_buddy_free_list(mm, &bman->reserved); + drm_buddy_free_list(mm, &bman->reserved, 0); drm_buddy_fini(mm); bman->visible_avail += bman->visible_reserved; WARN_ON_ONCE(bman->visible_avail != bman->visible_size); diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index b45ef0560611..06ec6ceb61d5 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -73,20 +73,6 @@ bool i915_error_injected(void); __i915_printk(i915, i915_error_injected() ? KERN_DEBUG : KERN_ERR, \ fmt, ##__VA_ARGS__) -#if defined(GCC_VERSION) && GCC_VERSION >= 70000 -#define add_overflows_t(T, A, B) \ - __builtin_add_overflow_p((A), (B), (T)0) -#else -#define add_overflows_t(T, A, B) ({ \ - typeof(A) a = (A); \ - typeof(B) b = (B); \ - (T)(a + b) < a; \ -}) -#endif - -#define add_overflows(A, B) \ - add_overflows_t(typeof((A) + (B)), (A), (B)) - #define range_overflows(start, size, max) ({ \ typeof(start) start__ = (start); \ typeof(size) size__ = (size); \ diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index b70715b1411d..d2f064d2525c 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1776,8 +1776,6 @@ static void release_references(struct i915_vma *vma, struct intel_gt *gt, if (vm_ddestroy) i915_vm_resv_put(vma->vm); - /* Wait for async active retire */ - i915_active_wait(&vma->active); i915_active_fini(&vma->active); GEM_WARN_ON(vma->resource); i915_vma_free(vma); diff --git a/drivers/gpu/drm/i915/intel_clock_gating.c b/drivers/gpu/drm/i915/intel_clock_gating.c index 9c21ce69bd98..7e70ee4fbd84 100644 --- a/drivers/gpu/drm/i915/intel_clock_gating.c +++ b/drivers/gpu/drm/i915/intel_clock_gating.c @@ -105,12 +105,6 @@ static void bxt_init_clock_gating(struct drm_i915_private *i915) * Display WA #0562: bxt */ intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcHighMemBwCorruptionAvoidance:bxt - * Display WA #0883: bxt - */ - intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); } static void glk_init_clock_gating(struct drm_i915_private *i915) @@ -349,13 +343,6 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *i915, intel_uncore_write(&i915->uncore, GEN7_MISCCPCTL, misccpctl); } -static void xehpsdv_init_clock_gating(struct drm_i915_private *i915) -{ - /* Wa_22010146351:xehpsdv */ - if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A0, STEP_B0)) - intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); -} - static void dg2_init_clock_gating(struct drm_i915_private *i915) { /* Wa_22010954014:dg2 */ @@ -363,17 +350,6 @@ static void dg2_init_clock_gating(struct drm_i915_private *i915) SGSI_SIDECLK_DIS); } -static void pvc_init_clock_gating(struct drm_i915_private *i915) -{ - /* Wa_14012385139:pvc */ - if (IS_PVC_BD_STEP(i915, STEP_A0, STEP_B0)) - intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGR_DIS); - - /* Wa_22010954014:pvc */ - if (IS_PVC_BD_STEP(i915, STEP_A0, STEP_B0)) - intel_uncore_rmw(&i915->uncore, XEHP_CLOCK_GATE_DIS, 0, SGSI_SIDECLK_DIS); -} - static void cnp_init_clock_gating(struct drm_i915_private *i915) { if (!HAS_PCH_CNP(i915)) @@ -396,13 +372,6 @@ static void cfl_init_clock_gating(struct drm_i915_private *i915) * Display WA #0562: cfl */ intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:cfl - * Display WA #0873: cfl - */ - intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); } static void kbl_init_clock_gating(struct drm_i915_private *i915) @@ -427,13 +396,6 @@ static void kbl_init_clock_gating(struct drm_i915_private *i915) * Display WA #0562: kbl */ intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:kbl - * Display WA #0873: kbl - */ - intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); } static void skl_init_clock_gating(struct drm_i915_private *i915) @@ -452,19 +414,6 @@ static void skl_init_clock_gating(struct drm_i915_private *i915) * Display WA #0562: skl */ intel_uncore_rmw(&i915->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS); - - /* - * WaFbcNukeOnHostModify:skl - * Display WA #0873: skl - */ - intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), - 0, DPFC_NUKE_ON_ANY_MODIFICATION); - - /* - * WaFbcHighMemBwCorruptionAvoidance:skl - * Display WA #0883: skl - */ - intel_uncore_rmw(&i915->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0); } static void bdw_init_clock_gating(struct drm_i915_private *i915) @@ -762,9 +711,7 @@ static const struct drm_i915_clock_gating_funcs platform##_clock_gating_funcs = .init_clock_gating = platform##_init_clock_gating, \ } -CG_FUNCS(pvc); CG_FUNCS(dg2); -CG_FUNCS(xehpsdv); CG_FUNCS(cfl); CG_FUNCS(skl); CG_FUNCS(kbl); @@ -797,12 +744,8 @@ CG_FUNCS(nop); */ void intel_clock_gating_hooks_init(struct drm_i915_private *i915) { - if (IS_PONTEVECCHIO(i915)) - i915->clock_gating_funcs = &pvc_clock_gating_funcs; - else if (IS_DG2(i915)) + if (IS_DG2(i915)) i915->clock_gating_funcs = &dg2_clock_gating_funcs; - else if (IS_XEHPSDV(i915)) - i915->clock_gating_funcs = &xehpsdv_clock_gating_funcs; else if (IS_COFFEELAKE(i915) || IS_COMETLAKE(i915)) i915->clock_gating_funcs = &cfl_clock_gating_funcs; else if (IS_SKYLAKE(i915)) diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 59bea1398c91..a0a43ea07f11 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -70,9 +70,7 @@ static const char * const platform_names[] = { PLATFORM_NAME(DG1), PLATFORM_NAME(ALDERLAKE_S), PLATFORM_NAME(ALDERLAKE_P), - PLATFORM_NAME(XEHPSDV), PLATFORM_NAME(DG2), - PLATFORM_NAME(PONTEVECCHIO), PLATFORM_NAME(METEORLAKE), }; #undef PLATFORM_NAME diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index eba2f0b919c8..d1a2abc7e513 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -87,9 +87,7 @@ enum intel_platform { INTEL_DG1, INTEL_ALDERLAKE_S, INTEL_ALDERLAKE_P, - INTEL_XEHPSDV, INTEL_DG2, - INTEL_PONTEVECCHIO, INTEL_METEORLAKE, INTEL_MAX_PLATFORMS }; diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c index 87ecc5104fd9..d0f111ff0ada 100644 --- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c +++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c @@ -3,6 +3,7 @@ * Copyright © 2020 Intel Corporation */ +#include "display/bxt_dpio_phy_regs.h" #include "display/intel_audio_regs.h" #include "display/intel_backlight_regs.h" #include "display/intel_color_regs.h" @@ -1155,11 +1156,11 @@ static int iterate_bxt_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(BXT_PORT_PCS_DW12_LN01(DPIO_PHY0, DPIO_CH0)); MMIO_D(BXT_PORT_PCS_DW12_LN23(DPIO_PHY0, DPIO_CH0)); MMIO_D(BXT_PORT_PCS_DW12_GRP(DPIO_PHY0, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW2_LN0(DPIO_PHY0, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW2_LN(DPIO_PHY0, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW2_GRP(DPIO_PHY0, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW3_LN0(DPIO_PHY0, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW3_LN(DPIO_PHY0, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW3_GRP(DPIO_PHY0, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW4_LN0(DPIO_PHY0, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW4_LN(DPIO_PHY0, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW4_GRP(DPIO_PHY0, DPIO_CH0)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY0, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY0, DPIO_CH0, 1)); @@ -1180,11 +1181,11 @@ static int iterate_bxt_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(BXT_PORT_PCS_DW12_LN01(DPIO_PHY0, DPIO_CH1)); MMIO_D(BXT_PORT_PCS_DW12_LN23(DPIO_PHY0, DPIO_CH1)); MMIO_D(BXT_PORT_PCS_DW12_GRP(DPIO_PHY0, DPIO_CH1)); - MMIO_D(BXT_PORT_TX_DW2_LN0(DPIO_PHY0, DPIO_CH1)); + MMIO_D(BXT_PORT_TX_DW2_LN(DPIO_PHY0, DPIO_CH1, 0)); MMIO_D(BXT_PORT_TX_DW2_GRP(DPIO_PHY0, DPIO_CH1)); - MMIO_D(BXT_PORT_TX_DW3_LN0(DPIO_PHY0, DPIO_CH1)); + MMIO_D(BXT_PORT_TX_DW3_LN(DPIO_PHY0, DPIO_CH1, 0)); MMIO_D(BXT_PORT_TX_DW3_GRP(DPIO_PHY0, DPIO_CH1)); - MMIO_D(BXT_PORT_TX_DW4_LN0(DPIO_PHY0, DPIO_CH1)); + MMIO_D(BXT_PORT_TX_DW4_LN(DPIO_PHY0, DPIO_CH1, 0)); MMIO_D(BXT_PORT_TX_DW4_GRP(DPIO_PHY0, DPIO_CH1)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY0, DPIO_CH1, 0)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY0, DPIO_CH1, 1)); @@ -1205,11 +1206,11 @@ static int iterate_bxt_mmio(struct intel_gvt_mmio_table_iter *iter) MMIO_D(BXT_PORT_PCS_DW12_LN01(DPIO_PHY1, DPIO_CH0)); MMIO_D(BXT_PORT_PCS_DW12_LN23(DPIO_PHY1, DPIO_CH0)); MMIO_D(BXT_PORT_PCS_DW12_GRP(DPIO_PHY1, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW2_LN0(DPIO_PHY1, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW2_LN(DPIO_PHY1, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW2_GRP(DPIO_PHY1, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW3_LN0(DPIO_PHY1, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW3_LN(DPIO_PHY1, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW3_GRP(DPIO_PHY1, DPIO_CH0)); - MMIO_D(BXT_PORT_TX_DW4_LN0(DPIO_PHY1, DPIO_CH0)); + MMIO_D(BXT_PORT_TX_DW4_LN(DPIO_PHY1, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW4_GRP(DPIO_PHY1, DPIO_CH0)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY1, DPIO_CH0, 0)); MMIO_D(BXT_PORT_TX_DW14_LN(DPIO_PHY1, DPIO_CH0, 1)); diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c index b4162f1be765..a5adfb5d8fd2 100644 --- a/drivers/gpu/drm/i915/intel_step.c +++ b/drivers/gpu/drm/i915/intel_step.c @@ -102,13 +102,6 @@ static const struct intel_step_info adlp_revids[] = { [0xC] = { COMMON_GT_MEDIA_STEP(C0), .display_step = STEP_D0 }, }; -static const struct intel_step_info xehpsdv_revids[] = { - [0x0] = { COMMON_GT_MEDIA_STEP(A0) }, - [0x1] = { COMMON_GT_MEDIA_STEP(A1) }, - [0x4] = { COMMON_GT_MEDIA_STEP(B0) }, - [0x8] = { COMMON_GT_MEDIA_STEP(C0) }, -}; - static const struct intel_step_info dg2_g10_revid_step_tbl[] = { [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_A0 }, [0x1] = { COMMON_GT_MEDIA_STEP(A1), .display_step = STEP_A0 }, @@ -153,8 +146,6 @@ static u8 gmd_to_intel_step(struct drm_i915_private *i915, return step; } -static void pvc_step_init(struct drm_i915_private *i915, int pci_revid); - void intel_step_init(struct drm_i915_private *i915) { const struct intel_step_info *revids = NULL; @@ -178,10 +169,7 @@ void intel_step_init(struct drm_i915_private *i915) return; } - if (IS_PONTEVECCHIO(i915)) { - pvc_step_init(i915, revid); - return; - } else if (IS_DG2_G10(i915)) { + if (IS_DG2_G10(i915)) { revids = dg2_g10_revid_step_tbl; size = ARRAY_SIZE(dg2_g10_revid_step_tbl); } else if (IS_DG2_G11(i915)) { @@ -190,9 +178,6 @@ void intel_step_init(struct drm_i915_private *i915) } else if (IS_DG2_G12(i915)) { revids = dg2_g12_revid_step_tbl; size = ARRAY_SIZE(dg2_g12_revid_step_tbl); - } else if (IS_XEHPSDV(i915)) { - revids = xehpsdv_revids; - size = ARRAY_SIZE(xehpsdv_revids); } else if (IS_ALDERLAKE_P_N(i915)) { revids = adlp_n_revids; size = ARRAY_SIZE(adlp_n_revids); @@ -277,69 +262,6 @@ void intel_step_init(struct drm_i915_private *i915) RUNTIME_INFO(i915)->step = step; } -#define PVC_BD_REVID GENMASK(5, 3) -#define PVC_CT_REVID GENMASK(2, 0) - -static const int pvc_bd_subids[] = { - [0x0] = STEP_A0, - [0x3] = STEP_B0, - [0x4] = STEP_B1, - [0x5] = STEP_B3, -}; - -static const int pvc_ct_subids[] = { - [0x3] = STEP_A0, - [0x5] = STEP_B0, - [0x6] = STEP_B1, - [0x7] = STEP_C0, -}; - -static int -pvc_step_lookup(struct drm_i915_private *i915, const char *type, - const int *table, int size, int subid) -{ - if (subid < size && table[subid] != STEP_NONE) - return table[subid]; - - drm_warn(&i915->drm, "Unknown %s id 0x%02x\n", type, subid); - - /* - * As on other platforms, try to use the next higher ID if we land on a - * gap in the table. - */ - while (subid < size && table[subid] == STEP_NONE) - subid++; - - if (subid < size) { - drm_dbg(&i915->drm, "Using steppings for %s id 0x%02x\n", - type, subid); - return table[subid]; - } - - drm_dbg(&i915->drm, "Using future steppings\n"); - return STEP_FUTURE; -} - -/* - * PVC needs special handling since we don't lookup the - * revid in a table, but rather specific bitfields within - * the revid for various components. - */ -static void pvc_step_init(struct drm_i915_private *i915, int pci_revid) -{ - int ct_subid, bd_subid; - - bd_subid = FIELD_GET(PVC_BD_REVID, pci_revid); - ct_subid = FIELD_GET(PVC_CT_REVID, pci_revid); - - RUNTIME_INFO(i915)->step.basedie_step = - pvc_step_lookup(i915, "Base Die", pvc_bd_subids, - ARRAY_SIZE(pvc_bd_subids), bd_subid); - RUNTIME_INFO(i915)->step.graphics_step = - pvc_step_lookup(i915, "Compute Tile", pvc_ct_subids, - ARRAY_SIZE(pvc_ct_subids), ct_subid); -} - #define STEP_NAME_CASE(name) \ case STEP_##name: \ return #name; diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 76400e9c40f0..729409a4bada 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -1106,45 +1106,6 @@ static const struct i915_range dg2_shadowed_regs[] = { { .start = 0x1F8510, .end = 0x1F8550 }, }; -static const struct i915_range pvc_shadowed_regs[] = { - { .start = 0x2030, .end = 0x2030 }, - { .start = 0x2510, .end = 0x2550 }, - { .start = 0xA008, .end = 0xA00C }, - { .start = 0xA188, .end = 0xA188 }, - { .start = 0xA278, .end = 0xA278 }, - { .start = 0xA540, .end = 0xA56C }, - { .start = 0xC4C8, .end = 0xC4C8 }, - { .start = 0xC4E0, .end = 0xC4E0 }, - { .start = 0xC600, .end = 0xC600 }, - { .start = 0xC658, .end = 0xC658 }, - { .start = 0x22030, .end = 0x22030 }, - { .start = 0x22510, .end = 0x22550 }, - { .start = 0x1C0030, .end = 0x1C0030 }, - { .start = 0x1C0510, .end = 0x1C0550 }, - { .start = 0x1C4030, .end = 0x1C4030 }, - { .start = 0x1C4510, .end = 0x1C4550 }, - { .start = 0x1C8030, .end = 0x1C8030 }, - { .start = 0x1C8510, .end = 0x1C8550 }, - { .start = 0x1D0030, .end = 0x1D0030 }, - { .start = 0x1D0510, .end = 0x1D0550 }, - { .start = 0x1D4030, .end = 0x1D4030 }, - { .start = 0x1D4510, .end = 0x1D4550 }, - { .start = 0x1D8030, .end = 0x1D8030 }, - { .start = 0x1D8510, .end = 0x1D8550 }, - { .start = 0x1E0030, .end = 0x1E0030 }, - { .start = 0x1E0510, .end = 0x1E0550 }, - { .start = 0x1E4030, .end = 0x1E4030 }, - { .start = 0x1E4510, .end = 0x1E4550 }, - { .start = 0x1E8030, .end = 0x1E8030 }, - { .start = 0x1E8510, .end = 0x1E8550 }, - { .start = 0x1F0030, .end = 0x1F0030 }, - { .start = 0x1F0510, .end = 0x1F0550 }, - { .start = 0x1F4030, .end = 0x1F4030 }, - { .start = 0x1F4510, .end = 0x1F4550 }, - { .start = 0x1F8030, .end = 0x1F8030 }, - { .start = 0x1F8510, .end = 0x1F8550 }, -}; - static const struct i915_range mtl_shadowed_regs[] = { { .start = 0x2030, .end = 0x2030 }, { .start = 0x2510, .end = 0x2550 }, @@ -1471,195 +1432,31 @@ static const struct intel_forcewake_range __gen12_fw_ranges[] = { 0x1d3f00 - 0x1d3fff: VD2 */ }; -/* - * Graphics IP version 12.55 brings a slight change to the 0xd800 range, - * switching it from the GT domain to the render domain. - */ -#define XEHP_FWRANGES(FW_RANGE_D800) \ - GEN_FW_RANGE(0x0, 0x1fff, 0), /* \ - 0x0 - 0xaff: reserved \ - 0xb00 - 0x1fff: always on */ \ - GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x2700, 0x4aff, FORCEWAKE_GT), \ - GEN_FW_RANGE(0x4b00, 0x51ff, 0), /* \ - 0x4b00 - 0x4fff: reserved \ - 0x5000 - 0x51ff: always on */ \ - GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x8000, 0x813f, FORCEWAKE_GT), \ - GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x8160, 0x81ff, 0), /* \ - 0x8160 - 0x817f: reserved \ - 0x8180 - 0x81ff: always on */ \ - GEN_FW_RANGE(0x8200, 0x82ff, FORCEWAKE_GT), \ - GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x8500, 0x8cff, FORCEWAKE_GT), /* \ - 0x8500 - 0x87ff: gt \ - 0x8800 - 0x8c7f: reserved \ - 0x8c80 - 0x8cff: gt (DG2 only) */ \ - GEN_FW_RANGE(0x8d00, 0x8fff, FORCEWAKE_RENDER), /* \ - 0x8d00 - 0x8dff: render (DG2 only) \ - 0x8e00 - 0x8fff: reserved */ \ - GEN_FW_RANGE(0x9000, 0x94cf, FORCEWAKE_GT), /* \ - 0x9000 - 0x947f: gt \ - 0x9480 - 0x94cf: reserved */ \ - GEN_FW_RANGE(0x94d0, 0x955f, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x9560, 0x967f, 0), /* \ - 0x9560 - 0x95ff: always on \ - 0x9600 - 0x967f: reserved */ \ - GEN_FW_RANGE(0x9680, 0x97ff, FORCEWAKE_RENDER), /* \ - 0x9680 - 0x96ff: render (DG2 only) \ - 0x9700 - 0x97ff: reserved */ \ - GEN_FW_RANGE(0x9800, 0xcfff, FORCEWAKE_GT), /* \ - 0x9800 - 0xb4ff: gt \ - 0xb500 - 0xbfff: reserved \ - 0xc000 - 0xcfff: gt */ \ - GEN_FW_RANGE(0xd000, 0xd7ff, 0), \ - GEN_FW_RANGE(0xd800, 0xd87f, FW_RANGE_D800), \ - GEN_FW_RANGE(0xd880, 0xdbff, FORCEWAKE_GT), \ - GEN_FW_RANGE(0xdc00, 0xdcff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0xdd00, 0xde7f, FORCEWAKE_GT), /* \ - 0xdd00 - 0xddff: gt \ - 0xde00 - 0xde7f: reserved */ \ - GEN_FW_RANGE(0xde80, 0xe8ff, FORCEWAKE_RENDER), /* \ - 0xde80 - 0xdfff: render \ - 0xe000 - 0xe0ff: reserved \ - 0xe100 - 0xe8ff: render */ \ - GEN_FW_RANGE(0xe900, 0xffff, FORCEWAKE_GT), /* \ - 0xe900 - 0xe9ff: gt \ - 0xea00 - 0xefff: reserved \ - 0xf000 - 0xffff: gt */ \ - GEN_FW_RANGE(0x10000, 0x12fff, 0), /* \ - 0x10000 - 0x11fff: reserved \ - 0x12000 - 0x127ff: always on \ - 0x12800 - 0x12fff: reserved */ \ - GEN_FW_RANGE(0x13000, 0x131ff, FORCEWAKE_MEDIA_VDBOX0), /* DG2 only */ \ - GEN_FW_RANGE(0x13200, 0x13fff, FORCEWAKE_MEDIA_VDBOX2), /* \ - 0x13200 - 0x133ff: VD2 (DG2 only) \ - 0x13400 - 0x13fff: reserved */ \ - GEN_FW_RANGE(0x14000, 0x141ff, FORCEWAKE_MEDIA_VDBOX0), /* XEHPSDV only */ \ - GEN_FW_RANGE(0x14200, 0x143ff, FORCEWAKE_MEDIA_VDBOX2), /* XEHPSDV only */ \ - GEN_FW_RANGE(0x14400, 0x145ff, FORCEWAKE_MEDIA_VDBOX4), /* XEHPSDV only */ \ - GEN_FW_RANGE(0x14600, 0x147ff, FORCEWAKE_MEDIA_VDBOX6), /* XEHPSDV only */ \ - GEN_FW_RANGE(0x14800, 0x14fff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x15000, 0x16dff, FORCEWAKE_GT), /* \ - 0x15000 - 0x15fff: gt (DG2 only) \ - 0x16000 - 0x16dff: reserved */ \ - GEN_FW_RANGE(0x16e00, 0x1ffff, FORCEWAKE_RENDER), \ - GEN_FW_RANGE(0x20000, 0x21fff, FORCEWAKE_MEDIA_VDBOX0), /* \ - 0x20000 - 0x20fff: VD0 (XEHPSDV only) \ - 0x21000 - 0x21fff: reserved */ \ - GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT), \ - GEN_FW_RANGE(0x24000, 0x2417f, 0), /* \ - 0x24000 - 0x2407f: always on \ - 0x24080 - 0x2417f: reserved */ \ - GEN_FW_RANGE(0x24180, 0x249ff, FORCEWAKE_GT), /* \ - 0x24180 - 0x241ff: gt \ - 0x24200 - 0x249ff: reserved */ \ - GEN_FW_RANGE(0x24a00, 0x251ff, FORCEWAKE_RENDER), /* \ - 0x24a00 - 0x24a7f: render \ - 0x24a80 - 0x251ff: reserved */ \ - GEN_FW_RANGE(0x25200, 0x25fff, FORCEWAKE_GT), /* \ - 0x25200 - 0x252ff: gt \ - 0x25300 - 0x25fff: reserved */ \ - GEN_FW_RANGE(0x26000, 0x2ffff, FORCEWAKE_RENDER), /* \ - 0x26000 - 0x27fff: render \ - 0x28000 - 0x29fff: reserved \ - 0x2a000 - 0x2ffff: undocumented */ \ - GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT), \ - GEN_FW_RANGE(0x40000, 0x1bffff, 0), \ - GEN_FW_RANGE(0x1c0000, 0x1c3fff, FORCEWAKE_MEDIA_VDBOX0), /* \ - 0x1c0000 - 0x1c2bff: VD0 \ - 0x1c2c00 - 0x1c2cff: reserved \ - 0x1c2d00 - 0x1c2dff: VD0 \ - 0x1c2e00 - 0x1c3eff: VD0 (DG2 only) \ - 0x1c3f00 - 0x1c3fff: VD0 */ \ - GEN_FW_RANGE(0x1c4000, 0x1c7fff, FORCEWAKE_MEDIA_VDBOX1), /* \ - 0x1c4000 - 0x1c6bff: VD1 \ - 0x1c6c00 - 0x1c6cff: reserved \ - 0x1c6d00 - 0x1c6dff: VD1 \ - 0x1c6e00 - 0x1c7fff: reserved */ \ - GEN_FW_RANGE(0x1c8000, 0x1cbfff, FORCEWAKE_MEDIA_VEBOX0), /* \ - 0x1c8000 - 0x1ca0ff: VE0 \ - 0x1ca100 - 0x1cbfff: reserved */ \ - GEN_FW_RANGE(0x1cc000, 0x1ccfff, FORCEWAKE_MEDIA_VDBOX0), \ - GEN_FW_RANGE(0x1cd000, 0x1cdfff, FORCEWAKE_MEDIA_VDBOX2), \ - GEN_FW_RANGE(0x1ce000, 0x1cefff, FORCEWAKE_MEDIA_VDBOX4), \ - GEN_FW_RANGE(0x1cf000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX6), \ - GEN_FW_RANGE(0x1d0000, 0x1d3fff, FORCEWAKE_MEDIA_VDBOX2), /* \ - 0x1d0000 - 0x1d2bff: VD2 \ - 0x1d2c00 - 0x1d2cff: reserved \ - 0x1d2d00 - 0x1d2dff: VD2 \ - 0x1d2e00 - 0x1d3dff: VD2 (DG2 only) \ - 0x1d3e00 - 0x1d3eff: reserved \ - 0x1d3f00 - 0x1d3fff: VD2 */ \ - GEN_FW_RANGE(0x1d4000, 0x1d7fff, FORCEWAKE_MEDIA_VDBOX3), /* \ - 0x1d4000 - 0x1d6bff: VD3 \ - 0x1d6c00 - 0x1d6cff: reserved \ - 0x1d6d00 - 0x1d6dff: VD3 \ - 0x1d6e00 - 0x1d7fff: reserved */ \ - GEN_FW_RANGE(0x1d8000, 0x1dffff, FORCEWAKE_MEDIA_VEBOX1), /* \ - 0x1d8000 - 0x1da0ff: VE1 \ - 0x1da100 - 0x1dffff: reserved */ \ - GEN_FW_RANGE(0x1e0000, 0x1e3fff, FORCEWAKE_MEDIA_VDBOX4), /* \ - 0x1e0000 - 0x1e2bff: VD4 \ - 0x1e2c00 - 0x1e2cff: reserved \ - 0x1e2d00 - 0x1e2dff: VD4 \ - 0x1e2e00 - 0x1e3eff: reserved \ - 0x1e3f00 - 0x1e3fff: VD4 */ \ - GEN_FW_RANGE(0x1e4000, 0x1e7fff, FORCEWAKE_MEDIA_VDBOX5), /* \ - 0x1e4000 - 0x1e6bff: VD5 \ - 0x1e6c00 - 0x1e6cff: reserved \ - 0x1e6d00 - 0x1e6dff: VD5 \ - 0x1e6e00 - 0x1e7fff: reserved */ \ - GEN_FW_RANGE(0x1e8000, 0x1effff, FORCEWAKE_MEDIA_VEBOX2), /* \ - 0x1e8000 - 0x1ea0ff: VE2 \ - 0x1ea100 - 0x1effff: reserved */ \ - GEN_FW_RANGE(0x1f0000, 0x1f3fff, FORCEWAKE_MEDIA_VDBOX6), /* \ - 0x1f0000 - 0x1f2bff: VD6 \ - 0x1f2c00 - 0x1f2cff: reserved \ - 0x1f2d00 - 0x1f2dff: VD6 \ - 0x1f2e00 - 0x1f3eff: reserved \ - 0x1f3f00 - 0x1f3fff: VD6 */ \ - GEN_FW_RANGE(0x1f4000, 0x1f7fff, FORCEWAKE_MEDIA_VDBOX7), /* \ - 0x1f4000 - 0x1f6bff: VD7 \ - 0x1f6c00 - 0x1f6cff: reserved \ - 0x1f6d00 - 0x1f6dff: VD7 \ - 0x1f6e00 - 0x1f7fff: reserved */ \ - GEN_FW_RANGE(0x1f8000, 0x1fa0ff, FORCEWAKE_MEDIA_VEBOX3), - -static const struct intel_forcewake_range __xehp_fw_ranges[] = { - XEHP_FWRANGES(FORCEWAKE_GT) -}; - static const struct intel_forcewake_range __dg2_fw_ranges[] = { - XEHP_FWRANGES(FORCEWAKE_RENDER) -}; - -static const struct intel_forcewake_range __pvc_fw_ranges[] = { - GEN_FW_RANGE(0x0, 0xaff, 0), - GEN_FW_RANGE(0xb00, 0xbff, FORCEWAKE_GT), - GEN_FW_RANGE(0xc00, 0xfff, 0), - GEN_FW_RANGE(0x1000, 0x1fff, FORCEWAKE_GT), + GEN_FW_RANGE(0x0, 0x1fff, 0), /* + 0x0 - 0xaff: reserved + 0xb00 - 0x1fff: always on */ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_GT), - GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER), - GEN_FW_RANGE(0x4000, 0x813f, FORCEWAKE_GT), /* - 0x4000 - 0x4aff: gt + GEN_FW_RANGE(0x2700, 0x4aff, FORCEWAKE_GT), + GEN_FW_RANGE(0x4b00, 0x51ff, 0), /* 0x4b00 - 0x4fff: reserved - 0x5000 - 0x51ff: gt - 0x5200 - 0x52ff: reserved - 0x5300 - 0x53ff: gt - 0x5400 - 0x7fff: reserved - 0x8000 - 0x813f: gt */ - GEN_FW_RANGE(0x8140, 0x817f, FORCEWAKE_RENDER), - GEN_FW_RANGE(0x8180, 0x81ff, 0), - GEN_FW_RANGE(0x8200, 0x94cf, FORCEWAKE_GT), /* - 0x8200 - 0x82ff: gt - 0x8300 - 0x84ff: reserved - 0x8500 - 0x887f: gt - 0x8880 - 0x8a7f: reserved - 0x8a80 - 0x8aff: gt - 0x8b00 - 0x8fff: reserved + 0x5000 - 0x51ff: always on */ + GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8000, 0x813f, FORCEWAKE_GT), + GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8160, 0x81ff, 0), /* + 0x8160 - 0x817f: reserved + 0x8180 - 0x81ff: always on */ + GEN_FW_RANGE(0x8200, 0x82ff, FORCEWAKE_GT), + GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x8500, 0x8cff, FORCEWAKE_GT), /* + 0x8500 - 0x87ff: gt + 0x8800 - 0x8c7f: reserved + 0x8c80 - 0x8cff: gt (DG2 only) */ + GEN_FW_RANGE(0x8d00, 0x8fff, FORCEWAKE_RENDER), /* + 0x8d00 - 0x8dff: render (DG2 only) + 0x8e00 - 0x8fff: reserved */ + GEN_FW_RANGE(0x9000, 0x94cf, FORCEWAKE_GT), /* 0x9000 - 0x947f: gt 0x9480 - 0x94cf: reserved */ GEN_FW_RANGE(0x94d0, 0x955f, FORCEWAKE_RENDER), @@ -1673,65 +1470,114 @@ static const struct intel_forcewake_range __pvc_fw_ranges[] = { 0x9800 - 0xb4ff: gt 0xb500 - 0xbfff: reserved 0xc000 - 0xcfff: gt */ - GEN_FW_RANGE(0xd000, 0xd3ff, 0), - GEN_FW_RANGE(0xd400, 0xdbff, FORCEWAKE_GT), + GEN_FW_RANGE(0xd000, 0xd7ff, 0), + GEN_FW_RANGE(0xd800, 0xd87f, FORCEWAKE_RENDER), + GEN_FW_RANGE(0xd880, 0xdbff, FORCEWAKE_GT), GEN_FW_RANGE(0xdc00, 0xdcff, FORCEWAKE_RENDER), GEN_FW_RANGE(0xdd00, 0xde7f, FORCEWAKE_GT), /* 0xdd00 - 0xddff: gt 0xde00 - 0xde7f: reserved */ GEN_FW_RANGE(0xde80, 0xe8ff, FORCEWAKE_RENDER), /* - 0xde80 - 0xdeff: render - 0xdf00 - 0xe1ff: reserved - 0xe200 - 0xe7ff: render - 0xe800 - 0xe8ff: reserved */ - GEN_FW_RANGE(0xe900, 0x11fff, FORCEWAKE_GT), /* - 0xe900 - 0xe9ff: gt - 0xea00 - 0xebff: reserved - 0xec00 - 0xffff: gt - 0x10000 - 0x11fff: reserved */ - GEN_FW_RANGE(0x12000, 0x12fff, 0), /* + 0xde80 - 0xdfff: render + 0xe000 - 0xe0ff: reserved + 0xe100 - 0xe8ff: render */ + GEN_FW_RANGE(0xe900, 0xffff, FORCEWAKE_GT), /* + 0xe900 - 0xe9ff: gt + 0xea00 - 0xefff: reserved + 0xf000 - 0xffff: gt */ + GEN_FW_RANGE(0x10000, 0x12fff, 0), /* + 0x10000 - 0x11fff: reserved 0x12000 - 0x127ff: always on 0x12800 - 0x12fff: reserved */ - GEN_FW_RANGE(0x13000, 0x19fff, FORCEWAKE_GT), /* - 0x13000 - 0x135ff: gt - 0x13600 - 0x147ff: reserved - 0x14800 - 0x153ff: gt - 0x15400 - 0x19fff: reserved */ - GEN_FW_RANGE(0x1a000, 0x21fff, FORCEWAKE_RENDER), /* - 0x1a000 - 0x1ffff: render + GEN_FW_RANGE(0x13000, 0x131ff, FORCEWAKE_MEDIA_VDBOX0), + GEN_FW_RANGE(0x13200, 0x147ff, FORCEWAKE_MEDIA_VDBOX2), /* + 0x13200 - 0x133ff: VD2 (DG2 only) + 0x13400 - 0x147ff: reserved */ + GEN_FW_RANGE(0x14800, 0x14fff, FORCEWAKE_RENDER), + GEN_FW_RANGE(0x15000, 0x16dff, FORCEWAKE_GT), /* + 0x15000 - 0x15fff: gt (DG2 only) + 0x16000 - 0x16dff: reserved */ + GEN_FW_RANGE(0x16e00, 0x21fff, FORCEWAKE_RENDER), /* + 0x16e00 - 0x1ffff: render 0x20000 - 0x21fff: reserved */ GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT), GEN_FW_RANGE(0x24000, 0x2417f, 0), /* - 24000 - 0x2407f: always on - 24080 - 0x2417f: reserved */ - GEN_FW_RANGE(0x24180, 0x25fff, FORCEWAKE_GT), /* + 0x24000 - 0x2407f: always on + 0x24080 - 0x2417f: reserved */ + GEN_FW_RANGE(0x24180, 0x249ff, FORCEWAKE_GT), /* 0x24180 - 0x241ff: gt - 0x24200 - 0x251ff: reserved + 0x24200 - 0x249ff: reserved */ + GEN_FW_RANGE(0x24a00, 0x251ff, FORCEWAKE_RENDER), /* + 0x24a00 - 0x24a7f: render + 0x24a80 - 0x251ff: reserved */ + GEN_FW_RANGE(0x25200, 0x25fff, FORCEWAKE_GT), /* 0x25200 - 0x252ff: gt 0x25300 - 0x25fff: reserved */ GEN_FW_RANGE(0x26000, 0x2ffff, FORCEWAKE_RENDER), /* 0x26000 - 0x27fff: render - 0x28000 - 0x2ffff: reserved */ + 0x28000 - 0x29fff: reserved + 0x2a000 - 0x2ffff: undocumented */ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT), GEN_FW_RANGE(0x40000, 0x1bffff, 0), GEN_FW_RANGE(0x1c0000, 0x1c3fff, FORCEWAKE_MEDIA_VDBOX0), /* 0x1c0000 - 0x1c2bff: VD0 0x1c2c00 - 0x1c2cff: reserved 0x1c2d00 - 0x1c2dff: VD0 - 0x1c2e00 - 0x1c3eff: reserved + 0x1c2e00 - 0x1c3eff: VD0 0x1c3f00 - 0x1c3fff: VD0 */ - GEN_FW_RANGE(0x1c4000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX1), /* - 0x1c4000 - 0x1c6aff: VD1 - 0x1c6b00 - 0x1c7eff: reserved - 0x1c7f00 - 0x1c7fff: VD1 - 0x1c8000 - 0x1cffff: reserved */ - GEN_FW_RANGE(0x1d0000, 0x23ffff, FORCEWAKE_MEDIA_VDBOX2), /* - 0x1d0000 - 0x1d2aff: VD2 - 0x1d2b00 - 0x1d3eff: reserved - 0x1d3f00 - 0x1d3fff: VD2 - 0x1d4000 - 0x23ffff: reserved */ - GEN_FW_RANGE(0x240000, 0x3dffff, 0), - GEN_FW_RANGE(0x3e0000, 0x3effff, FORCEWAKE_GT), + GEN_FW_RANGE(0x1c4000, 0x1c7fff, FORCEWAKE_MEDIA_VDBOX1), /* + 0x1c4000 - 0x1c6bff: VD1 + 0x1c6c00 - 0x1c6cff: reserved + 0x1c6d00 - 0x1c6dff: VD1 + 0x1c6e00 - 0x1c7fff: reserved */ + GEN_FW_RANGE(0x1c8000, 0x1cbfff, FORCEWAKE_MEDIA_VEBOX0), /* + 0x1c8000 - 0x1ca0ff: VE0 + 0x1ca100 - 0x1cbfff: reserved */ + GEN_FW_RANGE(0x1cc000, 0x1ccfff, FORCEWAKE_MEDIA_VDBOX0), + GEN_FW_RANGE(0x1cd000, 0x1cdfff, FORCEWAKE_MEDIA_VDBOX2), + GEN_FW_RANGE(0x1ce000, 0x1cefff, FORCEWAKE_MEDIA_VDBOX4), + GEN_FW_RANGE(0x1cf000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX6), + GEN_FW_RANGE(0x1d0000, 0x1d3fff, FORCEWAKE_MEDIA_VDBOX2), /* + 0x1d0000 - 0x1d2bff: VD2 + 0x1d2c00 - 0x1d2cff: reserved + 0x1d2d00 - 0x1d2dff: VD2 + 0x1d2e00 - 0x1d3dff: VD2 + 0x1d3e00 - 0x1d3eff: reserved + 0x1d3f00 - 0x1d3fff: VD2 */ + GEN_FW_RANGE(0x1d4000, 0x1d7fff, FORCEWAKE_MEDIA_VDBOX3), /* + 0x1d4000 - 0x1d6bff: VD3 + 0x1d6c00 - 0x1d6cff: reserved + 0x1d6d00 - 0x1d6dff: VD3 + 0x1d6e00 - 0x1d7fff: reserved */ + GEN_FW_RANGE(0x1d8000, 0x1dffff, FORCEWAKE_MEDIA_VEBOX1), /* + 0x1d8000 - 0x1da0ff: VE1 + 0x1da100 - 0x1dffff: reserved */ + GEN_FW_RANGE(0x1e0000, 0x1e3fff, FORCEWAKE_MEDIA_VDBOX4), /* + 0x1e0000 - 0x1e2bff: VD4 + 0x1e2c00 - 0x1e2cff: reserved + 0x1e2d00 - 0x1e2dff: VD4 + 0x1e2e00 - 0x1e3eff: reserved + 0x1e3f00 - 0x1e3fff: VD4 */ + GEN_FW_RANGE(0x1e4000, 0x1e7fff, FORCEWAKE_MEDIA_VDBOX5), /* + 0x1e4000 - 0x1e6bff: VD5 + 0x1e6c00 - 0x1e6cff: reserved + 0x1e6d00 - 0x1e6dff: VD5 + 0x1e6e00 - 0x1e7fff: reserved */ + GEN_FW_RANGE(0x1e8000, 0x1effff, FORCEWAKE_MEDIA_VEBOX2), /* + 0x1e8000 - 0x1ea0ff: VE2 + 0x1ea100 - 0x1effff: reserved */ + GEN_FW_RANGE(0x1f0000, 0x1f3fff, FORCEWAKE_MEDIA_VDBOX6), /* + 0x1f0000 - 0x1f2bff: VD6 + 0x1f2c00 - 0x1f2cff: reserved + 0x1f2d00 - 0x1f2dff: VD6 + 0x1f2e00 - 0x1f3eff: reserved + 0x1f3f00 - 0x1f3fff: VD6 */ + GEN_FW_RANGE(0x1f4000, 0x1f7fff, FORCEWAKE_MEDIA_VDBOX7), /* + 0x1f4000 - 0x1f6bff: VD7 + 0x1f6c00 - 0x1f6cff: reserved + 0x1f6d00 - 0x1f6dff: VD7 + 0x1f6e00 - 0x1f7fff: reserved */ + GEN_FW_RANGE(0x1f8000, 0x1fa0ff, FORCEWAKE_MEDIA_VEBOX3), }; static const struct intel_forcewake_range __mtl_fw_ranges[] = { @@ -2576,18 +2422,10 @@ static int uncore_forcewake_init(struct intel_uncore *uncore) ASSIGN_FW_DOMAINS_TABLE(uncore, __mtl_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, mtl_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60)) { - ASSIGN_FW_DOMAINS_TABLE(uncore, __pvc_fw_ranges); - ASSIGN_SHADOW_TABLE(uncore, pvc_shadowed_regs); - ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { ASSIGN_FW_DOMAINS_TABLE(uncore, __dg2_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, dg2_shadowed_regs); ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); - } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { - ASSIGN_FW_DOMAINS_TABLE(uncore, __xehp_fw_ranges); - ASSIGN_SHADOW_TABLE(uncore, gen12_shadowed_regs); - ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable); } else if (GRAPHICS_VER(i915) >= 12) { ASSIGN_FW_DOMAINS_TABLE(uncore, __gen12_fw_ranges); ASSIGN_SHADOW_TABLE(uncore, gen12_shadowed_regs); @@ -2734,7 +2572,7 @@ void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore, * the forcewake domain if any of the other engines * in the same media slice are present. */ - if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 50) && i % 2 == 0) { + if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 55) && i % 2 == 0) { if ((i + 1 < I915_MAX_VCS) && HAS_ENGINE(gt, _VCS(i + 1))) continue; diff --git a/drivers/gpu/drm/i915/selftests/i915_selftest.c b/drivers/gpu/drm/i915/selftests/i915_selftest.c index ee79e0809a6d..fee76c1d2f45 100644 --- a/drivers/gpu/drm/i915/selftests/i915_selftest.c +++ b/drivers/gpu/drm/i915/selftests/i915_selftest.c @@ -154,6 +154,30 @@ __wait_gsc_proxy_completed(struct drm_i915_private *i915) pr_warn(DRIVER_NAME "Timed out waiting for gsc_proxy_completion!\n"); } +static void +__wait_gsc_huc_load_completed(struct drm_i915_private *i915) +{ + /* this only applies to DG2, so we only care about GT0 */ + struct intel_huc *huc = &to_gt(i915)->uc.huc; + bool need_to_wait = (IS_ENABLED(CONFIG_INTEL_MEI_PXP) && + intel_huc_wait_required(huc)); + /* + * The GSC and PXP mei bringup depends on the kernel boot ordering, so + * to account for the worst case scenario the HuC code waits for up to + * 10s for the GSC driver to load and then another 5s for the PXP + * component to bind before giving up, even though those steps normally + * complete in less than a second from the i915 load. We match that + * timeout here, but we expect to bail early due to the fence being + * signalled even in a failure case, as it is extremely unlikely that + * both components will use their full timeout. + */ + unsigned long timeout_ms = 15000; + + if (need_to_wait && + wait_for(i915_sw_fence_done(&huc->delayed_load.fence), timeout_ms)) + pr_warn(DRIVER_NAME "Timed out waiting for huc load via GSC!\n"); +} + static int __run_selftests(const char *name, struct selftest *st, unsigned int count, @@ -228,14 +252,16 @@ int i915_mock_selftests(void) int i915_live_selftests(struct pci_dev *pdev) { + struct drm_i915_private *i915 = pdev_to_i915(pdev); int err; if (!i915_selftest.live) return 0; - __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + __wait_gsc_proxy_completed(i915); + __wait_gsc_huc_load_completed(i915); - err = run_selftests(live, pdev_to_i915(pdev)); + err = run_selftests(live, i915); if (err) { i915_selftest.live = err; return err; @@ -251,14 +277,16 @@ int i915_live_selftests(struct pci_dev *pdev) int i915_perf_selftests(struct pci_dev *pdev) { + struct drm_i915_private *i915 = pdev_to_i915(pdev); int err; if (!i915_selftest.perf) return 0; - __wait_gsc_proxy_completed(pdev_to_i915(pdev)); + __wait_gsc_proxy_completed(i915); + __wait_gsc_huc_load_completed(i915); - err = run_selftests(perf, pdev_to_i915(pdev)); + err = run_selftests(perf, i915); if (err) { i915_selftest.perf = err; return err; diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c index 4f98aa8a861e..41eaa9b7f67d 100644 --- a/drivers/gpu/drm/i915/selftests/intel_uncore.c +++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c @@ -71,7 +71,6 @@ static int intel_shadow_table_check(void) { gen11_shadowed_regs, ARRAY_SIZE(gen11_shadowed_regs) }, { gen12_shadowed_regs, ARRAY_SIZE(gen12_shadowed_regs) }, { dg2_shadowed_regs, ARRAY_SIZE(dg2_shadowed_regs) }, - { pvc_shadowed_regs, ARRAY_SIZE(pvc_shadowed_regs) }, { mtl_shadowed_regs, ARRAY_SIZE(mtl_shadowed_regs) }, { xelpmp_shadowed_regs, ARRAY_SIZE(xelpmp_shadowed_regs) }, }; @@ -119,8 +118,6 @@ int intel_uncore_mock_selftests(void) { __gen9_fw_ranges, ARRAY_SIZE(__gen9_fw_ranges), true }, { __gen11_fw_ranges, ARRAY_SIZE(__gen11_fw_ranges), true }, { __gen12_fw_ranges, ARRAY_SIZE(__gen12_fw_ranges), true }, - { __xehp_fw_ranges, ARRAY_SIZE(__xehp_fw_ranges), true }, - { __pvc_fw_ranges, ARRAY_SIZE(__pvc_fw_ranges), true }, { __mtl_fw_ranges, ARRAY_SIZE(__mtl_fw_ranges), true }, { __xelpmp_fw_ranges, ARRAY_SIZE(__xelpmp_fw_ranges), true }, }; diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index 15492b69f698..e3287f1de774 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -681,6 +681,8 @@ void intel_dram_detect(struct drm_i915_private *i915) if (ret) return; + drm_dbg_kms(&i915->drm, "Num qgv points %u\n", dram_info->num_qgv_points); + drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n", diff --git a/drivers/gpu/drm/imagination/pvr_fw_trace.c b/drivers/gpu/drm/imagination/pvr_fw_trace.c index 31199e45b72e..73707daa4e52 100644 --- a/drivers/gpu/drm/imagination/pvr_fw_trace.c +++ b/drivers/gpu/drm/imagination/pvr_fw_trace.c @@ -12,6 +12,7 @@ #include #include +#include #include #include diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c index dade8b59feae..704c549750f9 100644 --- a/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-plane.c @@ -773,6 +773,13 @@ static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = { .atomic_update = ipu_plane_atomic_update, }; +static const struct drm_plane_helper_funcs ipu_primary_plane_helper_funcs = { + .atomic_check = ipu_plane_atomic_check, + .atomic_disable = ipu_plane_atomic_disable, + .atomic_update = ipu_plane_atomic_update, + .get_scanout_buffer = drm_fb_dma_get_scanout_buffer, +}; + bool ipu_plane_atomic_update_pending(struct drm_plane *plane) { struct ipu_plane *ipu_plane = to_ipu_plane(plane); @@ -916,7 +923,10 @@ struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, ipu_plane->dma = dma; ipu_plane->dp_flow = dp; - drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs); + if (type == DRM_PLANE_TYPE_PRIMARY) + drm_plane_helper_add(&ipu_plane->base, &ipu_primary_plane_helper_funcs); + else + drm_plane_helper_add(&ipu_plane->base, &ipu_plane_helper_funcs); if (dp == IPU_DP_FLOW_SYNC_BG || dp == IPU_DP_FLOW_SYNC_FG) ret = drm_plane_create_zpos_property(&ipu_plane->base, zpos, 0, diff --git a/drivers/gpu/drm/lima/lima_bcast.c b/drivers/gpu/drm/lima/lima_bcast.c index fbc43f243c54..6d000504e1a4 100644 --- a/drivers/gpu/drm/lima/lima_bcast.c +++ b/drivers/gpu/drm/lima/lima_bcast.c @@ -43,6 +43,18 @@ void lima_bcast_suspend(struct lima_ip *ip) } +int lima_bcast_mask_irq(struct lima_ip *ip) +{ + bcast_write(LIMA_BCAST_BROADCAST_MASK, 0); + bcast_write(LIMA_BCAST_INTERRUPT_MASK, 0); + return 0; +} + +int lima_bcast_reset(struct lima_ip *ip) +{ + return lima_bcast_hw_init(ip); +} + int lima_bcast_init(struct lima_ip *ip) { int i; diff --git a/drivers/gpu/drm/lima/lima_bcast.h b/drivers/gpu/drm/lima/lima_bcast.h index 465ee587bceb..cd08841e4787 100644 --- a/drivers/gpu/drm/lima/lima_bcast.h +++ b/drivers/gpu/drm/lima/lima_bcast.h @@ -13,4 +13,7 @@ void lima_bcast_fini(struct lima_ip *ip); void lima_bcast_enable(struct lima_device *dev, int num_pp); +int lima_bcast_mask_irq(struct lima_ip *ip); +int lima_bcast_reset(struct lima_ip *ip); + #endif diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c index 10fd9154cc46..739c865b556f 100644 --- a/drivers/gpu/drm/lima/lima_drv.c +++ b/drivers/gpu/drm/lima/lima_drv.c @@ -371,6 +371,7 @@ static int lima_pdev_probe(struct platform_device *pdev) { struct lima_device *ldev; struct drm_device *ddev; + const struct lima_compatible *comp; int err; err = lima_sched_slab_init(); @@ -384,7 +385,13 @@ static int lima_pdev_probe(struct platform_device *pdev) } ldev->dev = &pdev->dev; - ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev); + comp = of_device_get_match_data(&pdev->dev); + if (!comp) { + err = -ENODEV; + goto err_out0; + } + + ldev->id = comp->id; platform_set_drvdata(pdev, ldev); @@ -459,9 +466,17 @@ static void lima_pdev_remove(struct platform_device *pdev) lima_sched_slab_fini(); } +static const struct lima_compatible lima_mali400_data = { + .id = lima_gpu_mali400, +}; + +static const struct lima_compatible lima_mali450_data = { + .id = lima_gpu_mali450, +}; + static const struct of_device_id dt_match[] = { - { .compatible = "arm,mali-400", .data = (void *)lima_gpu_mali400 }, - { .compatible = "arm,mali-450", .data = (void *)lima_gpu_mali450 }, + { .compatible = "arm,mali-400", .data = &lima_mali400_data }, + { .compatible = "arm,mali-450", .data = &lima_mali450_data }, {} }; MODULE_DEVICE_TABLE(of, dt_match); diff --git a/drivers/gpu/drm/lima/lima_drv.h b/drivers/gpu/drm/lima/lima_drv.h index c738d288547b..6706c19b166e 100644 --- a/drivers/gpu/drm/lima/lima_drv.h +++ b/drivers/gpu/drm/lima/lima_drv.h @@ -7,6 +7,7 @@ #include #include "lima_ctx.h" +#include "lima_device.h" extern int lima_sched_timeout_ms; extern uint lima_heap_init_nr_pages; @@ -39,6 +40,10 @@ struct lima_submit { struct lima_sched_task *task; }; +struct lima_compatible { + enum lima_gpu_id id; +}; + static inline struct lima_drm_priv * to_lima_drm_priv(struct drm_file *file) { diff --git a/drivers/gpu/drm/lima/lima_gp.c b/drivers/gpu/drm/lima/lima_gp.c index 6b354e2fb61d..3282997a0358 100644 --- a/drivers/gpu/drm/lima/lima_gp.c +++ b/drivers/gpu/drm/lima/lima_gp.c @@ -233,6 +233,13 @@ static void lima_gp_task_mmu_error(struct lima_sched_pipe *pipe) lima_sched_pipe_task_done(pipe); } +static void lima_gp_task_mask_irq(struct lima_sched_pipe *pipe) +{ + struct lima_ip *ip = pipe->processor[0]; + + gp_write(LIMA_GP_INT_MASK, 0); +} + static int lima_gp_task_recover(struct lima_sched_pipe *pipe) { struct lima_ip *ip = pipe->processor[0]; @@ -338,7 +345,9 @@ int lima_gp_init(struct lima_ip *ip) void lima_gp_fini(struct lima_ip *ip) { + struct lima_device *dev = ip->dev; + devm_free_irq(dev->dev, ip->irq, ip); } int lima_gp_pipe_init(struct lima_device *dev) @@ -365,6 +374,7 @@ int lima_gp_pipe_init(struct lima_device *dev) pipe->task_error = lima_gp_task_error; pipe->task_mmu_error = lima_gp_task_mmu_error; pipe->task_recover = lima_gp_task_recover; + pipe->task_mask_irq = lima_gp_task_mask_irq; return 0; } diff --git a/drivers/gpu/drm/lima/lima_mmu.c b/drivers/gpu/drm/lima/lima_mmu.c index e18317c5ca8c..6611e2836bf0 100644 --- a/drivers/gpu/drm/lima/lima_mmu.c +++ b/drivers/gpu/drm/lima/lima_mmu.c @@ -118,7 +118,12 @@ int lima_mmu_init(struct lima_ip *ip) void lima_mmu_fini(struct lima_ip *ip) { + struct lima_device *dev = ip->dev; + if (ip->id == lima_ip_ppmmu_bcast) + return; + + devm_free_irq(dev->dev, ip->irq, ip); } void lima_mmu_flush_tlb(struct lima_ip *ip) diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c index d0d2db0ef1ce..eaab4788dff4 100644 --- a/drivers/gpu/drm/lima/lima_pp.c +++ b/drivers/gpu/drm/lima/lima_pp.c @@ -286,7 +286,9 @@ int lima_pp_init(struct lima_ip *ip) void lima_pp_fini(struct lima_ip *ip) { + struct lima_device *dev = ip->dev; + devm_free_irq(dev->dev, ip->irq, ip); } int lima_pp_bcast_resume(struct lima_ip *ip) @@ -319,7 +321,9 @@ int lima_pp_bcast_init(struct lima_ip *ip) void lima_pp_bcast_fini(struct lima_ip *ip) { + struct lima_device *dev = ip->dev; + devm_free_irq(dev->dev, ip->irq, ip); } static int lima_pp_task_validate(struct lima_sched_pipe *pipe, @@ -429,6 +433,9 @@ static void lima_pp_task_error(struct lima_sched_pipe *pipe) lima_pp_hard_reset(ip); } + + if (pipe->bcast_processor) + lima_bcast_reset(pipe->bcast_processor); } static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe) @@ -437,6 +444,20 @@ static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe) lima_sched_pipe_task_done(pipe); } +static void lima_pp_task_mask_irq(struct lima_sched_pipe *pipe) +{ + int i; + + for (i = 0; i < pipe->num_processor; i++) { + struct lima_ip *ip = pipe->processor[i]; + + pp_write(LIMA_PP_INT_MASK, 0); + } + + if (pipe->bcast_processor) + lima_bcast_mask_irq(pipe->bcast_processor); +} + static struct kmem_cache *lima_pp_task_slab; static int lima_pp_task_slab_refcnt; @@ -468,6 +489,7 @@ int lima_pp_pipe_init(struct lima_device *dev) pipe->task_fini = lima_pp_task_fini; pipe->task_error = lima_pp_task_error; pipe->task_mmu_error = lima_pp_task_mmu_error; + pipe->task_mask_irq = lima_pp_task_mask_irq; return 0; } diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c index 00b19adfc888..bbf3f8feab94 100644 --- a/drivers/gpu/drm/lima/lima_sched.c +++ b/drivers/gpu/drm/lima/lima_sched.c @@ -422,12 +422,21 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job */ for (i = 0; i < pipe->num_processor; i++) synchronize_irq(pipe->processor[i]->irq); + if (pipe->bcast_processor) + synchronize_irq(pipe->bcast_processor->irq); if (dma_fence_is_signaled(task->fence)) { DRM_WARN("%s unexpectedly high interrupt latency\n", lima_ip_name(ip)); return DRM_GPU_SCHED_STAT_NOMINAL; } + /* + * The task might still finish while this timeout handler runs. + * To prevent a race condition on its completion, mask all irqs + * on the running core until the next hard reset completes. + */ + pipe->task_mask_irq(pipe); + if (!pipe->error) DRM_ERROR("%s job timeout\n", lima_ip_name(ip)); diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h index 6bd4f3b70109..85b23ba901d5 100644 --- a/drivers/gpu/drm/lima/lima_sched.h +++ b/drivers/gpu/drm/lima/lima_sched.h @@ -80,6 +80,7 @@ struct lima_sched_pipe { void (*task_error)(struct lima_sched_pipe *pipe); void (*task_mmu_error)(struct lima_sched_pipe *pipe); int (*task_recover)(struct lima_sched_pipe *pipe); + void (*task_mask_irq)(struct lima_sched_pipe *pipe); struct work_struct recover_work; }; diff --git a/drivers/gpu/drm/loongson/lsdc_crtc.c b/drivers/gpu/drm/loongson/lsdc_crtc.c index 827acab580fa..03958b79f251 100644 --- a/drivers/gpu/drm/loongson/lsdc_crtc.c +++ b/drivers/gpu/drm/loongson/lsdc_crtc.c @@ -3,6 +3,7 @@ * Copyright (C) 2023 Loongson Technology Corporation Limited */ +#include #include #include diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 5e4436403b8d..32a2ed6c0cfe 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 -mediatek-drm-y := mtk_disp_aal.o \ +mediatek-drm-y := mtk_crtc.o \ + mtk_ddp_comp.o \ + mtk_disp_aal.o \ mtk_disp_ccorr.o \ mtk_disp_color.o \ mtk_disp_gamma.o \ @@ -8,16 +10,14 @@ mediatek-drm-y := mtk_disp_aal.o \ mtk_disp_ovl.o \ mtk_disp_ovl_adaptor.o \ mtk_disp_rdma.o \ - mtk_drm_crtc.o \ - mtk_drm_ddp_comp.o \ mtk_drm_drv.o \ - mtk_drm_gem.o \ - mtk_drm_plane.o \ mtk_dsi.o \ mtk_dpi.o \ mtk_ethdr.o \ + mtk_gem.o \ mtk_mdp_rdma.o \ - mtk_padding.o + mtk_padding.o \ + mtk_plane.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_crtc.c similarity index 82% rename from drivers/gpu/drm/mediatek/mtk_drm_crtc.c rename to drivers/gpu/drm/mediatek/mtk_crtc.c index a04499c4f9ca..6f34f573e127 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_crtc.c @@ -19,14 +19,14 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_drm_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" -#include "mtk_drm_gem.h" -#include "mtk_drm_plane.h" +#include "mtk_gem.h" +#include "mtk_plane.h" /* - * struct mtk_drm_crtc - MediaTek specific crtc structure. + * struct mtk_crtc - MediaTek specific crtc structure. * @base: crtc object. * @enabled: records whether crtc_enable succeeded * @planes: array of 4 drm_plane structures, one for each overlay plane @@ -38,7 +38,7 @@ * * TODO: Needs update: this header is missing a bunch of member descriptions. */ -struct mtk_drm_crtc { +struct mtk_crtc { struct drm_crtc base; bool enabled; @@ -80,9 +80,9 @@ struct mtk_crtc_state { unsigned int pending_vrefresh; }; -static inline struct mtk_drm_crtc *to_mtk_crtc(struct drm_crtc *c) +static inline struct mtk_crtc *to_mtk_crtc(struct drm_crtc *c) { - return container_of(c, struct mtk_drm_crtc, base); + return container_of(c, struct mtk_crtc, base); } static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s) @@ -90,7 +90,7 @@ static inline struct mtk_crtc_state *to_mtk_crtc_state(struct drm_crtc_state *s) return container_of(s, struct mtk_crtc_state, base); } -static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) +static void mtk_crtc_finish_page_flip(struct mtk_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; unsigned long flags; @@ -104,11 +104,11 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) } } -static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc) +static void mtk_drm_finish_page_flip(struct mtk_crtc *mtk_crtc) { drm_crtc_handle_vblank(&mtk_crtc->base); if (!mtk_crtc->config_updating && mtk_crtc->pending_needs_vblank) { - mtk_drm_crtc_finish_page_flip(mtk_crtc); + mtk_crtc_finish_page_flip(mtk_crtc); mtk_crtc->pending_needs_vblank = false; } } @@ -151,9 +151,9 @@ static void mtk_drm_cmdq_pkt_destroy(struct cmdq_pkt *pkt) } #endif -static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) +static void mtk_crtc_destroy(struct drm_crtc *crtc) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); int i; mtk_mutex_put(mtk_crtc->mutex); @@ -176,7 +176,7 @@ static void mtk_drm_crtc_destroy(struct drm_crtc *crtc) drm_crtc_cleanup(crtc); } -static void mtk_drm_crtc_reset(struct drm_crtc *crtc) +static void mtk_crtc_reset(struct drm_crtc *crtc) { struct mtk_crtc_state *state; @@ -191,7 +191,7 @@ static void mtk_drm_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &state->base); } -static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc) +static struct drm_crtc_state *mtk_crtc_duplicate_state(struct drm_crtc *crtc) { struct mtk_crtc_state *state; @@ -208,18 +208,17 @@ static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc return &state->base; } -static void mtk_drm_crtc_destroy_state(struct drm_crtc *crtc, - struct drm_crtc_state *state) +static void mtk_crtc_destroy_state(struct drm_crtc *crtc, + struct drm_crtc_state *state) { __drm_atomic_helper_crtc_destroy_state(state); kfree(to_mtk_crtc_state(state)); } static enum drm_mode_status -mtk_drm_crtc_mode_valid(struct drm_crtc *crtc, - const struct drm_display_mode *mode) +mtk_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); enum drm_mode_status status = MODE_OK; int i; @@ -231,15 +230,15 @@ mtk_drm_crtc_mode_valid(struct drm_crtc *crtc, return status; } -static bool mtk_drm_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) +static bool mtk_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { /* Nothing to do here, but this callback is mandatory. */ return true; } -static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) +static void mtk_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct mtk_crtc_state *state = to_mtk_crtc_state(crtc->state); @@ -250,7 +249,7 @@ static void mtk_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) state->pending_config = true; } -static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc) +static int mtk_crtc_ddp_clk_enable(struct mtk_crtc *mtk_crtc) { int ret; int i; @@ -270,7 +269,7 @@ static int mtk_crtc_ddp_clk_enable(struct mtk_drm_crtc *mtk_crtc) return ret; } -static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc) +static void mtk_crtc_ddp_clk_disable(struct mtk_crtc *mtk_crtc) { int i; @@ -279,11 +278,11 @@ static void mtk_crtc_ddp_clk_disable(struct mtk_drm_crtc *mtk_crtc) } static -struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc, - struct drm_plane *plane, - unsigned int *local_layer) +struct mtk_ddp_comp *mtk_ddp_comp_for_plane(struct drm_crtc *crtc, + struct drm_plane *plane, + unsigned int *local_layer) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp; int i, count = 0; unsigned int local_index = plane - mtk_crtc->planes; @@ -306,7 +305,7 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) { struct cmdq_cb_data *data = mssg; struct cmdq_client *cmdq_cl = container_of(cl, struct cmdq_client, client); - struct mtk_drm_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_drm_crtc, cmdq_client); + struct mtk_crtc *mtk_crtc = container_of(cmdq_cl, struct mtk_crtc, cmdq_client); struct mtk_crtc_state *state; unsigned int i; @@ -346,7 +345,7 @@ static void ddp_cmdq_cb(struct mbox_client *cl, void *mssg) } #endif -static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) +static int mtk_crtc_ddp_hw_init(struct mtk_crtc *mtk_crtc) { struct drm_crtc *crtc = &mtk_crtc->base; struct drm_connector *connector; @@ -431,7 +430,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) /* should not enable layer before crtc enabled */ plane_state->pending.enable = false; - comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer); + comp = mtk_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) mtk_ddp_comp_layer_config(comp, local_layer, plane_state, NULL); @@ -446,7 +445,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) return ret; } -static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) +static void mtk_crtc_ddp_hw_fini(struct mtk_crtc *mtk_crtc) { struct drm_device *drm = mtk_crtc->base.dev; struct drm_crtc *crtc = &mtk_crtc->base; @@ -491,7 +490,7 @@ static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc) static void mtk_crtc_ddp_config(struct drm_crtc *crtc, struct cmdq_pkt *cmdq_handle) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_crtc_state *state = to_mtk_crtc_state(mtk_crtc->base.state); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; unsigned int i; @@ -522,8 +521,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, if (!plane_state->pending.config) continue; - comp = mtk_drm_ddp_comp_for_plane(crtc, plane, - &local_layer); + comp = mtk_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) mtk_ddp_comp_layer_config(comp, local_layer, @@ -547,8 +545,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, if (!plane_state->pending.async_config) continue; - comp = mtk_drm_ddp_comp_for_plane(crtc, plane, - &local_layer); + comp = mtk_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) mtk_ddp_comp_layer_config(comp, local_layer, @@ -563,8 +560,7 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc, } } -static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, - bool needs_vblank) +static void mtk_crtc_update_config(struct mtk_crtc *mtk_crtc, bool needs_vblank) { #if IS_REACHABLE(CONFIG_MTK_CMDQ) struct cmdq_pkt *cmdq_handle = &mtk_crtc->cmdq_handle; @@ -636,7 +632,7 @@ static void mtk_drm_crtc_update_config(struct mtk_drm_crtc *mtk_crtc, static void mtk_crtc_ddp_irq(void *data) { struct drm_crtc *crtc = data; - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv = crtc->dev->dev_private; #if IS_REACHABLE(CONFIG_MTK_CMDQ) @@ -652,9 +648,9 @@ static void mtk_crtc_ddp_irq(void *data) mtk_drm_finish_page_flip(mtk_crtc); } -static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc) +static int mtk_crtc_enable_vblank(struct drm_crtc *crtc) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; mtk_ddp_comp_enable_vblank(comp); @@ -662,22 +658,22 @@ static int mtk_drm_crtc_enable_vblank(struct drm_crtc *crtc) return 0; } -static void mtk_drm_crtc_disable_vblank(struct drm_crtc *crtc) +static void mtk_crtc_disable_vblank(struct drm_crtc *crtc) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; mtk_ddp_comp_disable_vblank(comp); } -static void mtk_drm_crtc_update_output(struct drm_crtc *crtc, - struct drm_atomic_state *state) +static void mtk_crtc_update_output(struct drm_crtc *crtc, + struct drm_atomic_state *state) { int crtc_index = drm_crtc_index(crtc); int i; struct device *dev; struct drm_crtc_state *crtc_state = state->crtcs[crtc_index].new_state; - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_drm_private *priv; unsigned int encoder_mask = crtc_state->encoder_mask; @@ -707,33 +703,33 @@ static void mtk_drm_crtc_update_output(struct drm_crtc *crtc, } } -int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, - struct mtk_plane_state *state) +int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, + struct mtk_plane_state *state) { unsigned int local_layer; struct mtk_ddp_comp *comp; - comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer); + comp = mtk_ddp_comp_for_plane(crtc, plane, &local_layer); if (comp) return mtk_ddp_comp_layer_check(comp, local_layer, state); return 0; } -void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, - struct drm_atomic_state *state) +void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, + struct drm_atomic_state *state) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); if (!mtk_crtc->enabled) return; - mtk_drm_crtc_update_config(mtk_crtc, false); + mtk_crtc_update_config(mtk_crtc, false); } -static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) +static void mtk_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; int ret; @@ -745,7 +741,7 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, return; } - mtk_drm_crtc_update_output(crtc, state); + mtk_crtc_update_output(crtc, state); ret = mtk_crtc_ddp_hw_init(mtk_crtc); if (ret) { @@ -757,10 +753,10 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc, mtk_crtc->enabled = true; } -static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *state) +static void mtk_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0]; int i; @@ -779,7 +775,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, } mtk_crtc->pending_planes = true; - mtk_drm_crtc_update_config(mtk_crtc, false); + mtk_crtc_update_config(mtk_crtc, false); #if IS_REACHABLE(CONFIG_MTK_CMDQ) /* Wait for planes to be disabled by cmdq */ if (mtk_crtc->cmdq_client.chan) @@ -797,13 +793,13 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc, mtk_crtc->enabled = false; } -static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc, - struct drm_atomic_state *state) +static void mtk_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_atomic_state *state) { struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc); struct mtk_crtc_state *mtk_crtc_state = to_mtk_crtc_state(crtc_state); - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); unsigned long flags; if (mtk_crtc->event && mtk_crtc_state->base.event) @@ -821,10 +817,10 @@ static void mtk_drm_crtc_atomic_begin(struct drm_crtc *crtc, } } -static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_atomic_state *state) +static void mtk_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) { - struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc); + struct mtk_crtc *mtk_crtc = to_mtk_crtc(crtc); int i; if (crtc->state->color_mgmt_changed) @@ -832,33 +828,32 @@ static void mtk_drm_crtc_atomic_flush(struct drm_crtc *crtc, mtk_ddp_gamma_set(mtk_crtc->ddp_comp[i], crtc->state); mtk_ddp_ctm_set(mtk_crtc->ddp_comp[i], crtc->state); } - mtk_drm_crtc_update_config(mtk_crtc, !!mtk_crtc->event); + mtk_crtc_update_config(mtk_crtc, !!mtk_crtc->event); } static const struct drm_crtc_funcs mtk_crtc_funcs = { .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .destroy = mtk_drm_crtc_destroy, - .reset = mtk_drm_crtc_reset, - .atomic_duplicate_state = mtk_drm_crtc_duplicate_state, - .atomic_destroy_state = mtk_drm_crtc_destroy_state, - .enable_vblank = mtk_drm_crtc_enable_vblank, - .disable_vblank = mtk_drm_crtc_disable_vblank, + .destroy = mtk_crtc_destroy, + .reset = mtk_crtc_reset, + .atomic_duplicate_state = mtk_crtc_duplicate_state, + .atomic_destroy_state = mtk_crtc_destroy_state, + .enable_vblank = mtk_crtc_enable_vblank, + .disable_vblank = mtk_crtc_disable_vblank, }; static const struct drm_crtc_helper_funcs mtk_crtc_helper_funcs = { - .mode_fixup = mtk_drm_crtc_mode_fixup, - .mode_set_nofb = mtk_drm_crtc_mode_set_nofb, - .mode_valid = mtk_drm_crtc_mode_valid, - .atomic_begin = mtk_drm_crtc_atomic_begin, - .atomic_flush = mtk_drm_crtc_atomic_flush, - .atomic_enable = mtk_drm_crtc_atomic_enable, - .atomic_disable = mtk_drm_crtc_atomic_disable, + .mode_fixup = mtk_crtc_mode_fixup, + .mode_set_nofb = mtk_crtc_mode_set_nofb, + .mode_valid = mtk_crtc_mode_valid, + .atomic_begin = mtk_crtc_atomic_begin, + .atomic_flush = mtk_crtc_atomic_flush, + .atomic_enable = mtk_crtc_atomic_enable, + .atomic_disable = mtk_crtc_atomic_disable, }; -static int mtk_drm_crtc_init(struct drm_device *drm, - struct mtk_drm_crtc *mtk_crtc, - unsigned int pipe) +static int mtk_crtc_init(struct drm_device *drm, struct mtk_crtc *mtk_crtc, + unsigned int pipe) { struct drm_plane *primary = NULL; struct drm_plane *cursor = NULL; @@ -885,8 +880,7 @@ static int mtk_drm_crtc_init(struct drm_device *drm, return ret; } -static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc, - int comp_idx) +static int mtk_crtc_num_comp_planes(struct mtk_crtc *mtk_crtc, int comp_idx) { struct mtk_ddp_comp *comp; @@ -904,8 +898,8 @@ static int mtk_drm_crtc_num_comp_planes(struct mtk_drm_crtc *mtk_crtc, } static inline -enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx, - unsigned int num_planes) +enum drm_plane_type mtk_crtc_plane_type(unsigned int plane_idx, + unsigned int num_planes) { if (plane_idx == 0) return DRM_PLANE_TYPE_PRIMARY; @@ -916,11 +910,11 @@ enum drm_plane_type mtk_drm_crtc_plane_type(unsigned int plane_idx, } -static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev, - struct mtk_drm_crtc *mtk_crtc, - int comp_idx, int pipe) +static int mtk_crtc_init_comp_planes(struct drm_device *drm_dev, + struct mtk_crtc *mtk_crtc, + int comp_idx, int pipe) { - int num_planes = mtk_drm_crtc_num_comp_planes(mtk_crtc, comp_idx); + int num_planes = mtk_crtc_num_comp_planes(mtk_crtc, comp_idx); struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[comp_idx]; int i, ret; @@ -928,8 +922,7 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev, ret = mtk_plane_init(drm_dev, &mtk_crtc->planes[mtk_crtc->layer_nr], BIT(pipe), - mtk_drm_crtc_plane_type(mtk_crtc->layer_nr, - num_planes), + mtk_crtc_plane_type(mtk_crtc->layer_nr, num_planes), mtk_ddp_comp_supported_rotations(comp), mtk_ddp_comp_get_formats(comp), mtk_ddp_comp_get_num_formats(comp)); @@ -941,9 +934,9 @@ static int mtk_drm_crtc_init_comp_planes(struct drm_device *drm_dev, return 0; } -struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc) +struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc) { - struct mtk_drm_crtc *mtk_crtc = NULL; + struct mtk_crtc *mtk_crtc = NULL; if (!crtc) return NULL; @@ -955,14 +948,14 @@ struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc) return mtk_crtc->dma_dev; } -int mtk_drm_crtc_create(struct drm_device *drm_dev, - const unsigned int *path, unsigned int path_len, - int priv_data_index, const struct mtk_drm_route *conn_routes, - unsigned int num_conn_routes) +int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path, + unsigned int path_len, int priv_data_index, + const struct mtk_drm_route *conn_routes, + unsigned int num_conn_routes) { struct mtk_drm_private *priv = drm_dev->dev_private; struct device *dev = drm_dev->dev; - struct mtk_drm_crtc *mtk_crtc; + struct mtk_crtc *mtk_crtc; unsigned int num_comp_planes = 0; int ret; int i; @@ -1009,10 +1002,10 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->mmsys_dev = priv->mmsys_dev; mtk_crtc->ddp_comp_nr = path_len; - mtk_crtc->ddp_comp = devm_kmalloc_array(dev, - mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), - sizeof(*mtk_crtc->ddp_comp), - GFP_KERNEL); + mtk_crtc->ddp_comp = devm_kcalloc(dev, + mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0), + sizeof(*mtk_crtc->ddp_comp), + GFP_KERNEL); if (!mtk_crtc->ddp_comp) return -ENOMEM; @@ -1047,7 +1040,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, } for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) - num_comp_planes += mtk_drm_crtc_num_comp_planes(mtk_crtc, i); + num_comp_planes += mtk_crtc_num_comp_planes(mtk_crtc, i); mtk_crtc->planes = devm_kcalloc(dev, num_comp_planes, sizeof(struct drm_plane), GFP_KERNEL); @@ -1055,8 +1048,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, return -ENOMEM; for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) { - ret = mtk_drm_crtc_init_comp_planes(drm_dev, mtk_crtc, i, - crtc_i); + ret = mtk_crtc_init_comp_planes(drm_dev, mtk_crtc, i, crtc_i); if (ret) return ret; } @@ -1068,7 +1060,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, */ mtk_crtc->dma_dev = mtk_ddp_comp_dma_dev_get(&priv->ddp_comp[path[0]]); - ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, crtc_i); + ret = mtk_crtc_init(drm_dev, mtk_crtc, crtc_i); if (ret < 0) return ret; @@ -1138,7 +1130,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev, mtk_crtc->num_conn_routes = num_conn_routes; mtk_crtc->conn_routes = conn_routes; - /* increase ddp_comp_nr at the end of mtk_drm_crtc_create */ + /* increase ddp_comp_nr at the end of mtk_crtc_create */ mtk_crtc->ddp_comp_nr++; } diff --git a/drivers/gpu/drm/mediatek/mtk_crtc.h b/drivers/gpu/drm/mediatek/mtk_crtc.h new file mode 100644 index 000000000000..388e900b6f4d --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_crtc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015 MediaTek Inc. + */ + +#ifndef MTK_CRTC_H +#define MTK_CRTC_H + +#include +#include "mtk_ddp_comp.h" +#include "mtk_drm_drv.h" +#include "mtk_plane.h" + +#define MTK_MAX_BPC 10 +#define MTK_MIN_BPC 3 + +void mtk_crtc_commit(struct drm_crtc *crtc); +int mtk_crtc_create(struct drm_device *drm_dev, const unsigned int *path, + unsigned int path_len, int priv_data_index, + const struct mtk_drm_route *conn_routes, + unsigned int num_conn_routes); +int mtk_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, + struct mtk_plane_state *state); +void mtk_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, + struct drm_atomic_state *plane_state); +struct device *mtk_crtc_dma_dev_get(struct drm_crtc *crtc); + +#endif /* MTK_CRTC_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c similarity index 94% rename from drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c rename to drivers/gpu/drm/mediatek/mtk_ddp_comp.c index a515e96cfefc..17b036411292 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.c @@ -14,11 +14,11 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" #include "mtk_drm_drv.h" -#include "mtk_drm_plane.h" -#include "mtk_drm_ddp_comp.h" -#include "mtk_drm_crtc.h" +#include "mtk_plane.h" #define DISP_REG_DITHER_EN 0x0000 @@ -497,10 +497,10 @@ static const struct mtk_ddp_comp_match mtk_ddp_matches[DDP_COMPONENT_DRM_ID_MAX] [DDP_COMPONENT_WDMA1] = { MTK_DISP_WDMA, 1, NULL }, }; -static bool mtk_drm_find_comp_in_ddp(struct device *dev, - const unsigned int *path, - unsigned int path_len, - struct mtk_ddp_comp *ddp_comp) +static bool mtk_ddp_comp_find(struct device *dev, + const unsigned int *path, + unsigned int path_len, + struct mtk_ddp_comp *ddp_comp) { unsigned int i; @@ -514,10 +514,10 @@ static bool mtk_drm_find_comp_in_ddp(struct device *dev, return false; } -static unsigned int mtk_drm_find_comp_in_ddp_conn_path(struct device *dev, - const struct mtk_drm_route *routes, - unsigned int num_routes, - struct mtk_ddp_comp *ddp_comp) +static unsigned int mtk_ddp_comp_find_in_route(struct device *dev, + const struct mtk_drm_route *routes, + unsigned int num_routes, + struct mtk_ddp_comp *ddp_comp) { int ret; unsigned int i; @@ -554,26 +554,31 @@ int mtk_ddp_comp_get_id(struct device_node *node, return -EINVAL; } -unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, - struct device *dev) +unsigned int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev) { struct mtk_drm_private *private = drm->dev_private; unsigned int ret = 0; - if (mtk_drm_find_comp_in_ddp(dev, private->data->main_path, private->data->main_len, - private->ddp_comp)) + if (mtk_ddp_comp_find(dev, + private->data->main_path, + private->data->main_len, + private->ddp_comp)) ret = BIT(0); - else if (mtk_drm_find_comp_in_ddp(dev, private->data->ext_path, - private->data->ext_len, private->ddp_comp)) + else if (mtk_ddp_comp_find(dev, + private->data->ext_path, + private->data->ext_len, + private->ddp_comp)) ret = BIT(1); - else if (mtk_drm_find_comp_in_ddp(dev, private->data->third_path, - private->data->third_len, private->ddp_comp)) + else if (mtk_ddp_comp_find(dev, + private->data->third_path, + private->data->third_len, + private->ddp_comp)) ret = BIT(2); else - ret = mtk_drm_find_comp_in_ddp_conn_path(dev, - private->data->conn_routes, - private->data->num_conn_routes, - private->ddp_comp); + ret = mtk_ddp_comp_find_in_route(dev, + private->data->conn_routes, + private->data->num_conn_routes, + private->ddp_comp); return ret; } diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h similarity index 98% rename from drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h rename to drivers/gpu/drm/mediatek/mtk_ddp_comp.h index 93d79a1366e9..26236691ce4c 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h +++ b/drivers/gpu/drm/mediatek/mtk_ddp_comp.h @@ -3,8 +3,8 @@ * Copyright (c) 2015 MediaTek Inc. */ -#ifndef MTK_DRM_DDP_COMP_H -#define MTK_DRM_DDP_COMP_H +#ifndef MTK_DDP_COMP_H +#define MTK_DDP_COMP_H #include #include @@ -326,8 +326,7 @@ static inline void mtk_ddp_comp_encoder_index_set(struct mtk_ddp_comp *comp) int mtk_ddp_comp_get_id(struct device_node *node, enum mtk_ddp_comp_type comp_type); -unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm, - struct device *dev); +unsigned int mtk_find_possible_crtcs(struct drm_device *drm, struct device *dev); int mtk_ddp_comp_init(struct device_node *comp_node, struct mtk_ddp_comp *comp, unsigned int comp_id); enum mtk_ddp_comp_type mtk_ddp_comp_get_type(unsigned int comp_id); @@ -340,4 +339,4 @@ void mtk_ddp_write_relaxed(struct cmdq_pkt *cmdq_pkt, unsigned int value, void mtk_ddp_write_mask(struct cmdq_pkt *cmdq_pkt, unsigned int value, struct cmdq_client_reg *cmdq_reg, void __iomem *regs, unsigned int offset, unsigned int mask); -#endif /* MTK_DRM_DDP_COMP_H */ +#endif /* MTK_DDP_COMP_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_disp_aal.c b/drivers/gpu/drm/mediatek/mtk_disp_aal.c index 40fe403086c3..3ce8f32b06d5 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_aal.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_aal.c @@ -11,9 +11,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_AAL_EN 0x0000 @@ -223,7 +223,6 @@ struct platform_driver mtk_disp_aal_driver = { .remove_new = mtk_disp_aal_remove, .driver = { .name = "mediatek-disp-aal", - .owner = THIS_MODULE, .of_match_table = mtk_disp_aal_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c index 465cddce0d32..df35e90dd25f 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c @@ -10,9 +10,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_CCORR_EN 0x0000 @@ -214,7 +214,6 @@ struct platform_driver mtk_disp_ccorr_driver = { .remove_new = mtk_disp_ccorr_remove, .driver = { .name = "mediatek-disp-ccorr", - .owner = THIS_MODULE, .of_match_table = mtk_disp_ccorr_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c index 78ea99f1444f..7f0085be5671 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_color.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c @@ -10,9 +10,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_COLOR_CFG_MAIN 0x0400 @@ -164,7 +164,6 @@ struct platform_driver mtk_disp_color_driver = { .remove_new = mtk_disp_color_remove, .driver = { .name = "mediatek-disp-color", - .owner = THIS_MODULE, .of_match_table = mtk_disp_color_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_drv.h b/drivers/gpu/drm/mediatek/mtk_disp_drv.h index 90e64467ea8f..082ac18fe04a 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_disp_drv.h @@ -9,8 +9,8 @@ #include #include #include -#include "mtk_drm_plane.h" #include "mtk_mdp_rdma.h" +#include "mtk_plane.h" int mtk_aal_clk_enable(struct device *dev); void mtk_aal_clk_disable(struct device *dev); diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c index c1bc8b00d938..ca8d1f3aca03 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c @@ -11,9 +11,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_GAMMA_EN 0x0000 @@ -334,7 +334,6 @@ struct platform_driver mtk_disp_gamma_driver = { .remove_new = mtk_disp_gamma_remove, .driver = { .name = "mediatek-disp-gamma", - .owner = THIS_MODULE, .of_match_table = mtk_disp_gamma_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.c b/drivers/gpu/drm/mediatek/mtk_disp_merge.c index 32a29924bd54..77c057e0e671 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_merge.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_merge.c @@ -10,7 +10,7 @@ #include #include -#include "mtk_drm_ddp_comp.h" +#include "mtk_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_disp_drv.h" @@ -376,7 +376,6 @@ struct platform_driver mtk_disp_merge_driver = { .remove_new = mtk_disp_merge_remove, .driver = { .name = "mediatek-disp-merge", - .owner = THIS_MODULE, .of_match_table = mtk_disp_merge_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index 2bffe4245466..b552a02d7eae 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -15,9 +15,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_REG_OVL_INTEN 0x0004 @@ -659,7 +659,6 @@ struct platform_driver mtk_disp_ovl_driver = { .remove_new = mtk_disp_ovl_remove, .driver = { .name = "mediatek-disp-ovl", - .owner = THIS_MODULE, .of_match_table = mtk_disp_ovl_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c index 034d31824d4d..02dd7dcdfedb 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c @@ -17,9 +17,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_ethdr.h" @@ -629,6 +629,5 @@ struct platform_driver mtk_disp_ovl_adaptor_driver = { .remove_new = mtk_disp_ovl_adaptor_remove, .driver = { .name = "mediatek-disp-ovl-adaptor", - .owner = THIS_MODULE, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index faa907f2f443..7b1a6e631200 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -13,9 +13,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DISP_REG_RDMA_INT_ENABLE 0x0000 @@ -428,7 +428,6 @@ struct platform_driver mtk_disp_rdma_driver = { .remove_new = mtk_disp_rdma_remove, .driver = { .name = "mediatek-disp-rdma", - .owner = THIS_MODULE, .of_match_table = mtk_disp_rdma_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c index 0ba72102636a..536366956447 100644 --- a/drivers/gpu/drm/mediatek/mtk_dp.c +++ b/drivers/gpu/drm/mediatek/mtk_dp.c @@ -2104,7 +2104,7 @@ static ssize_t mtk_dp_aux_transfer(struct drm_dp_aux *mtk_aux, if (mtk_dp->bridge.type != DRM_MODE_CONNECTOR_eDP && !mtk_dp->train_info.cable_plugged_in) { - ret = -EAGAIN; + ret = -EIO; goto err; } diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index beb7d9d08e97..bfe8653005db 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -26,9 +26,9 @@ #include #include +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" #include "mtk_dpi_regs.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" enum mtk_dpi_out_bit_num { @@ -805,7 +805,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) return ret; } - dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->dev); + dpi->encoder.possible_crtcs = mtk_find_possible_crtcs(drm_dev, dpi->dev); ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h b/drivers/gpu/drm/mediatek/mtk_drm_crtc.h deleted file mode 100644 index 1f988ff1bf9f..000000000000 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015 MediaTek Inc. - */ - -#ifndef MTK_DRM_CRTC_H -#define MTK_DRM_CRTC_H - -#include -#include "mtk_drm_ddp_comp.h" -#include "mtk_drm_drv.h" -#include "mtk_drm_plane.h" - -#define MTK_MAX_BPC 10 -#define MTK_MIN_BPC 3 - -void mtk_drm_crtc_commit(struct drm_crtc *crtc); -int mtk_drm_crtc_create(struct drm_device *drm_dev, - const unsigned int *path, - unsigned int path_len, - int priv_data_index, - const struct mtk_drm_route *conn_routes, - unsigned int num_conn_routes); -int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane, - struct mtk_plane_state *state); -void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane, - struct drm_atomic_state *plane_state); -struct device *mtk_drm_crtc_dma_dev_get(struct drm_crtc *crtc); - -#endif /* MTK_DRM_CRTC_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 74832c213092..b5f605751b0a 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -24,10 +24,10 @@ #include #include -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_drm_drv.h" -#include "mtk_drm_gem.h" +#include "mtk_gem.h" #define DRIVER_NAME "mediatek" #define DRIVER_DESC "Mediatek SoC DRM" @@ -494,24 +494,24 @@ static int mtk_drm_kms_init(struct drm_device *drm) priv_n = private->all_drm_private[j]; if (i == CRTC_MAIN && priv_n->data->main_len) { - ret = mtk_drm_crtc_create(drm, priv_n->data->main_path, - priv_n->data->main_len, j, - priv_n->data->conn_routes, - priv_n->data->num_conn_routes); + ret = mtk_crtc_create(drm, priv_n->data->main_path, + priv_n->data->main_len, j, + priv_n->data->conn_routes, + priv_n->data->num_conn_routes); if (ret) goto err_component_unbind; continue; } else if (i == CRTC_EXT && priv_n->data->ext_len) { - ret = mtk_drm_crtc_create(drm, priv_n->data->ext_path, - priv_n->data->ext_len, j, NULL, 0); + ret = mtk_crtc_create(drm, priv_n->data->ext_path, + priv_n->data->ext_len, j, NULL, 0); if (ret) goto err_component_unbind; continue; } else if (i == CRTC_THIRD && priv_n->data->third_len) { - ret = mtk_drm_crtc_create(drm, priv_n->data->third_path, - priv_n->data->third_len, j, NULL, 0); + ret = mtk_crtc_create(drm, priv_n->data->third_path, + priv_n->data->third_len, j, NULL, 0); if (ret) goto err_component_unbind; @@ -523,7 +523,7 @@ static int mtk_drm_kms_init(struct drm_device *drm) /* Use OVL device for all DMA memory allocations */ crtc = drm_crtc_from_index(drm, 0); if (crtc) - dma_dev = mtk_drm_crtc_dma_dev_get(crtc); + dma_dev = mtk_crtc_dma_dev_get(crtc); if (!dma_dev) { ret = -ENODEV; dev_err(drm->dev, "Need at least one OVL device\n"); @@ -576,8 +576,8 @@ DEFINE_DRM_GEM_FOPS(mtk_drm_fops); * We need to override this because the device used to import the memory is * not dev->dev, as drm_gem_prime_import() expects. */ -static struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev, - struct dma_buf *dma_buf) +static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev, + struct dma_buf *dma_buf) { struct mtk_drm_private *private = dev->dev_private; @@ -587,9 +587,9 @@ static struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev, static const struct drm_driver mtk_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, - .dumb_create = mtk_drm_gem_dumb_create, + .dumb_create = mtk_gem_dumb_create, - .gem_prime_import = mtk_drm_gem_prime_import, + .gem_prime_import = mtk_gem_prime_import, .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, .fops = &mtk_drm_fops, @@ -709,6 +709,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8183-disp-gamma", .data = (void *)MTK_DISP_GAMMA, }, + { .compatible = "mediatek,mt8195-disp-gamma", + .data = (void *)MTK_DISP_GAMMA, }, { .compatible = "mediatek,mt8195-disp-merge", .data = (void *)MTK_DISP_MERGE }, { .compatible = "mediatek,mt2701-disp-mutex", diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 33fadb08dc1c..78d698ede1bf 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -7,13 +7,13 @@ #define MTK_DRM_DRV_H #include -#include "mtk_drm_ddp_comp.h" +#include "mtk_ddp_comp.h" #define MAX_CONNECTOR 2 #define DDP_COMPONENT_DRM_OVL_ADAPTOR (DDP_COMPONENT_ID_MAX + 1) #define DDP_COMPONENT_DRM_ID_MAX (DDP_COMPONENT_DRM_OVL_ADAPTOR + 1) -enum mtk_drm_crtc_path { +enum mtk_crtc_path { CRTC_MAIN, CRTC_EXT, CRTC_THIRD, diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 9501f4019199..c255559cc56e 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -28,8 +28,8 @@ #include #include +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #define DSI_START 0x00 @@ -242,22 +242,23 @@ static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi) u32 data_rate_mhz = DIV_ROUND_UP(dsi->data_rate, HZ_PER_MHZ); struct mtk_phy_timing *timing = &dsi->phy_timing; - timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1; - timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000; - timing->da_hs_zero = (170 * data_rate_mhz + 10 * 1000) / 8000 + 1 - + timing->lpx = (80 * data_rate_mhz / (8 * 1000)) + 1; + timing->da_hs_prepare = (59 * data_rate_mhz + 4 * 1000) / 8000 + 1; + timing->da_hs_zero = (163 * data_rate_mhz + 11 * 1000) / 8000 + 1 - timing->da_hs_prepare; - timing->da_hs_trail = timing->da_hs_prepare + 1; + timing->da_hs_trail = (78 * data_rate_mhz + 7 * 1000) / 8000 + 1; - timing->ta_go = 4 * timing->lpx - 2; - timing->ta_sure = timing->lpx + 2; - timing->ta_get = 4 * timing->lpx; - timing->da_hs_exit = 2 * timing->lpx + 1; + timing->ta_go = 4 * timing->lpx; + timing->ta_sure = 3 * timing->lpx / 2; + timing->ta_get = 5 * timing->lpx; + timing->da_hs_exit = (118 * data_rate_mhz / (8 * 1000)) + 1; - timing->clk_hs_prepare = 70 * data_rate_mhz / (8 * 1000); - timing->clk_hs_post = timing->clk_hs_prepare + 8; - timing->clk_hs_trail = timing->clk_hs_prepare; - timing->clk_hs_zero = timing->clk_hs_trail * 4; - timing->clk_hs_exit = 2 * timing->clk_hs_trail; + timing->clk_hs_prepare = (57 * data_rate_mhz / (8 * 1000)) + 1; + timing->clk_hs_post = (65 * data_rate_mhz + 53 * 1000) / 8000 + 1; + timing->clk_hs_trail = (78 * data_rate_mhz + 7 * 1000) / 8000 + 1; + timing->clk_hs_zero = (330 * data_rate_mhz / (8 * 1000)) + 1 - + timing->clk_hs_prepare; + timing->clk_hs_exit = (118 * data_rate_mhz / (8 * 1000)) + 1; timcon0 = FIELD_PREP(LPX, timing->lpx) | FIELD_PREP(HS_PREP, timing->da_hs_prepare) | @@ -662,7 +663,7 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi) /* * mtk_dsi_stop() and mtk_dsi_start() is asymmetric, since - * mtk_dsi_stop() should be called after mtk_drm_crtc_atomic_disable(), + * mtk_dsi_stop() should be called after mtk_crtc_atomic_disable(), * which needs irq for vblank, and mtk_dsi_stop() will disable irq. * mtk_dsi_start() needs to be called in mtk_output_dsi_enable(), * after dsi is fully set. @@ -836,7 +837,7 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi) return ret; } - dsi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm, dsi->host.dev); + dsi->encoder.possible_crtcs = mtk_find_possible_crtcs(drm, dsi->host.dev); ret = drm_bridge_attach(&dsi->encoder, &dsi->bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR); diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c index 6a5d0c345aab..156c6ff547e8 100644 --- a/drivers/gpu/drm/mediatek/mtk_ethdr.c +++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c @@ -14,8 +14,8 @@ #include #include -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_ethdr.h" @@ -363,7 +363,6 @@ struct platform_driver mtk_ethdr_driver = { .remove_new = mtk_ethdr_remove, .driver = { .name = "mediatek-disp-ethdr", - .owner = THIS_MODULE, .of_match_table = mtk_ethdr_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_gem.c similarity index 76% rename from drivers/gpu/drm/mediatek/mtk_drm_gem.c rename to drivers/gpu/drm/mediatek/mtk_gem.c index 4f2e3feabc0f..5a82d7cf3ed0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_gem.c @@ -12,37 +12,40 @@ #include #include "mtk_drm_drv.h" -#include "mtk_drm_gem.h" +#include "mtk_gem.h" -static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); +static int mtk_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); static const struct vm_operations_struct vm_ops = { .open = drm_gem_vm_open, .close = drm_gem_vm_close, }; -static const struct drm_gem_object_funcs mtk_drm_gem_object_funcs = { - .free = mtk_drm_gem_free_object, +static const struct drm_gem_object_funcs mtk_gem_object_funcs = { + .free = mtk_gem_free_object, .get_sg_table = mtk_gem_prime_get_sg_table, - .vmap = mtk_drm_gem_prime_vmap, - .vunmap = mtk_drm_gem_prime_vunmap, - .mmap = mtk_drm_gem_object_mmap, + .vmap = mtk_gem_prime_vmap, + .vunmap = mtk_gem_prime_vunmap, + .mmap = mtk_gem_object_mmap, .vm_ops = &vm_ops, }; -static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, - unsigned long size) +static struct mtk_gem_obj *mtk_gem_init(struct drm_device *dev, + unsigned long size) { - struct mtk_drm_gem_obj *mtk_gem_obj; + struct mtk_gem_obj *mtk_gem_obj; int ret; size = round_up(size, PAGE_SIZE); + if (size == 0) + return ERR_PTR(-EINVAL); + mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL); if (!mtk_gem_obj) return ERR_PTR(-ENOMEM); - mtk_gem_obj->base.funcs = &mtk_drm_gem_object_funcs; + mtk_gem_obj->base.funcs = &mtk_gem_object_funcs; ret = drm_gem_object_init(dev, &mtk_gem_obj->base, size); if (ret < 0) { @@ -54,15 +57,15 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev, return mtk_gem_obj; } -struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, - size_t size, bool alloc_kmap) +struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev, + size_t size, bool alloc_kmap) { struct mtk_drm_private *priv = dev->dev_private; - struct mtk_drm_gem_obj *mtk_gem; + struct mtk_gem_obj *mtk_gem; struct drm_gem_object *obj; int ret; - mtk_gem = mtk_drm_gem_init(dev, size); + mtk_gem = mtk_gem_init(dev, size); if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); @@ -97,9 +100,9 @@ struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, return ERR_PTR(ret); } -void mtk_drm_gem_free_object(struct drm_gem_object *obj) +void mtk_gem_free_object(struct drm_gem_object *obj) { - struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); + struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct mtk_drm_private *priv = obj->dev->dev_private; if (mtk_gem->sg) @@ -114,10 +117,10 @@ void mtk_drm_gem_free_object(struct drm_gem_object *obj) kfree(mtk_gem); } -int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, - struct drm_mode_create_dumb *args) +int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, + struct drm_mode_create_dumb *args) { - struct mtk_drm_gem_obj *mtk_gem; + struct mtk_gem_obj *mtk_gem; int ret; args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8); @@ -130,7 +133,7 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch; args->size *= args->height; - mtk_gem = mtk_drm_gem_create(dev, args->size, false); + mtk_gem = mtk_gem_create(dev, args->size, false); if (IS_ERR(mtk_gem)) return PTR_ERR(mtk_gem); @@ -148,16 +151,16 @@ int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, return 0; err_handle_create: - mtk_drm_gem_free_object(&mtk_gem->base); + mtk_gem_free_object(&mtk_gem->base); return ret; } -static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, - struct vm_area_struct *vma) +static int mtk_gem_object_mmap(struct drm_gem_object *obj, + struct vm_area_struct *vma) { int ret; - struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); + struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct mtk_drm_private *priv = obj->dev->dev_private; /* @@ -188,7 +191,7 @@ static int mtk_drm_gem_object_mmap(struct drm_gem_object *obj, */ struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj) { - struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); + struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct mtk_drm_private *priv = obj->dev->dev_private; struct sg_table *sgt; int ret; @@ -212,7 +215,7 @@ struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj) struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { - struct mtk_drm_gem_obj *mtk_gem; + struct mtk_gem_obj *mtk_gem; /* check if the entries in the sg_table are contiguous */ if (drm_prime_get_contiguous_size(sg) < attach->dmabuf->size) { @@ -220,7 +223,7 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, return ERR_PTR(-EINVAL); } - mtk_gem = mtk_drm_gem_init(dev, attach->dmabuf->size); + mtk_gem = mtk_gem_init(dev, attach->dmabuf->size); if (IS_ERR(mtk_gem)) return ERR_CAST(mtk_gem); @@ -230,9 +233,9 @@ struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, return &mtk_gem->base; } -int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) +int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) { - struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); + struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); struct sg_table *sgt = NULL; unsigned int npages; @@ -270,10 +273,9 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map) return 0; } -void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, - struct iosys_map *map) +void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map) { - struct mtk_drm_gem_obj *mtk_gem = to_mtk_gem_obj(obj); + struct mtk_gem_obj *mtk_gem = to_mtk_gem_obj(obj); void *vaddr = map->vaddr; if (!mtk_gem->pages) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.h b/drivers/gpu/drm/mediatek/mtk_gem.h similarity index 62% rename from drivers/gpu/drm/mediatek/mtk_drm_gem.h rename to drivers/gpu/drm/mediatek/mtk_gem.h index 78f23b07a02e..66e5f154f698 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.h +++ b/drivers/gpu/drm/mediatek/mtk_gem.h @@ -3,8 +3,8 @@ * Copyright (c) 2015 MediaTek Inc. */ -#ifndef _MTK_DRM_GEM_H_ -#define _MTK_DRM_GEM_H_ +#ifndef _MTK_GEM_H_ +#define _MTK_GEM_H_ #include @@ -22,7 +22,7 @@ * P.S. this object would be transferred to user as kms_bo.handle so * user can access the buffer through kms_bo.handle. */ -struct mtk_drm_gem_obj { +struct mtk_gem_obj { struct drm_gem_object base; void *cookie; void *kvaddr; @@ -32,18 +32,17 @@ struct mtk_drm_gem_obj { struct page **pages; }; -#define to_mtk_gem_obj(x) container_of(x, struct mtk_drm_gem_obj, base) +#define to_mtk_gem_obj(x) container_of(x, struct mtk_gem_obj, base) -void mtk_drm_gem_free_object(struct drm_gem_object *gem); -struct mtk_drm_gem_obj *mtk_drm_gem_create(struct drm_device *dev, size_t size, - bool alloc_kmap); -int mtk_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, - struct drm_mode_create_dumb *args); +void mtk_gem_free_object(struct drm_gem_object *gem); +struct mtk_gem_obj *mtk_gem_create(struct drm_device *dev, size_t size, + bool alloc_kmap); +int mtk_gem_dumb_create(struct drm_file *file_priv, struct drm_device *dev, + struct drm_mode_create_dumb *args); struct sg_table *mtk_gem_prime_get_sg_table(struct drm_gem_object *obj); struct drm_gem_object *mtk_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg); -int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map); -void mtk_drm_gem_prime_vunmap(struct drm_gem_object *obj, - struct iosys_map *map); +int mtk_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map); +void mtk_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map); #endif diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index c6bdc565e4a9..6e1cca97a654 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -1695,7 +1695,7 @@ static int mtk_hdmi_register_audio_driver(struct device *dev) return 0; } -static int mtk_drm_hdmi_probe(struct platform_device *pdev) +static int mtk_hdmi_probe(struct platform_device *pdev) { struct mtk_hdmi *hdmi; struct device *dev = &pdev->dev; @@ -1754,7 +1754,7 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; } -static void mtk_drm_hdmi_remove(struct platform_device *pdev) +static void mtk_hdmi_remove(struct platform_device *pdev) { struct mtk_hdmi *hdmi = platform_get_drvdata(pdev); @@ -1798,7 +1798,7 @@ static const struct mtk_hdmi_conf mtk_hdmi_conf_mt8167 = { .cea_modes_only = true, }; -static const struct of_device_id mtk_drm_hdmi_of_ids[] = { +static const struct of_device_id mtk_hdmi_of_ids[] = { { .compatible = "mediatek,mt2701-hdmi", .data = &mtk_hdmi_conf_mt2701, }, @@ -1809,14 +1809,14 @@ static const struct of_device_id mtk_drm_hdmi_of_ids[] = { }, {} }; -MODULE_DEVICE_TABLE(of, mtk_drm_hdmi_of_ids); +MODULE_DEVICE_TABLE(of, mtk_hdmi_of_ids); static struct platform_driver mtk_hdmi_driver = { - .probe = mtk_drm_hdmi_probe, - .remove_new = mtk_drm_hdmi_remove, + .probe = mtk_hdmi_probe, + .remove_new = mtk_hdmi_remove, .driver = { .name = "mediatek-drm-hdmi", - .of_match_table = mtk_drm_hdmi_of_ids, + .of_match_table = mtk_hdmi_of_ids, .pm = &mtk_hdmi_pm_ops, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c index 54e46e440e0f..52d55861f954 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c @@ -284,8 +284,7 @@ static int mtk_hdmi_ddc_probe(struct platform_device *pdev) return PTR_ERR(ddc->clk); } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ddc->regs = devm_ioremap_resource(&pdev->dev, mem); + ddc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); if (IS_ERR(ddc->regs)) return PTR_ERR(ddc->regs); diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c index ee9ce9b6d078..925cbb7471ec 100644 --- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c @@ -346,7 +346,6 @@ struct platform_driver mtk_mdp_rdma_driver = { .remove_new = mtk_mdp_rdma_remove, .driver = { .name = "mediatek-mdp-rdma", - .owner = THIS_MODULE, .of_match_table = mtk_mdp_rdma_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_padding.c b/drivers/gpu/drm/mediatek/mtk_padding.c index 0d6451c149b6..85bc6768b6bc 100644 --- a/drivers/gpu/drm/mediatek/mtk_padding.c +++ b/drivers/gpu/drm/mediatek/mtk_padding.c @@ -11,9 +11,9 @@ #include #include +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_disp_drv.h" -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" #define PADDING_CONTROL_REG 0x00 #define PADDING_BYPASS BIT(0) @@ -154,7 +154,6 @@ struct platform_driver mtk_padding_driver = { .remove = mtk_padding_remove, .driver = { .name = "mediatek-disp-padding", - .owner = THIS_MODULE, .of_match_table = mtk_padding_driver_dt_match, }, }; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_plane.c similarity index 94% rename from drivers/gpu/drm/mediatek/mtk_drm_plane.c rename to drivers/gpu/drm/mediatek/mtk_plane.c index ddc9355b06d5..4625deb21d40 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_plane.c @@ -13,11 +13,11 @@ #include #include -#include "mtk_drm_crtc.h" -#include "mtk_drm_ddp_comp.h" +#include "mtk_crtc.h" +#include "mtk_ddp_comp.h" #include "mtk_drm_drv.h" -#include "mtk_drm_gem.h" -#include "mtk_drm_plane.h" +#include "mtk_gem.h" +#include "mtk_plane.h" static const u64 modifiers[] = { DRM_FORMAT_MOD_LINEAR, @@ -93,8 +93,8 @@ static bool mtk_plane_format_mod_supported(struct drm_plane *plane, return true; } -static void mtk_drm_plane_destroy_state(struct drm_plane *plane, - struct drm_plane_state *state) +static void mtk_plane_destroy_state(struct drm_plane *plane, + struct drm_plane_state *state) { __drm_atomic_helper_plane_destroy_state(state); kfree(to_mtk_plane_state(state)); @@ -117,8 +117,8 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane, if (!plane->state->fb) return -EINVAL; - ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane, - to_mtk_plane_state(new_plane_state)); + ret = mtk_crtc_plane_check(new_plane_state->crtc, plane, + to_mtk_plane_state(new_plane_state)); if (ret) return ret; @@ -135,7 +135,7 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state, { struct drm_framebuffer *fb = new_state->fb; struct drm_gem_object *gem; - struct mtk_drm_gem_obj *mtk_gem; + struct mtk_gem_obj *mtk_gem; unsigned int pitch, format; u64 modifier; dma_addr_t addr; @@ -232,7 +232,7 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane, swap(plane->state->fb, new_state->fb); wmb(); /* Make sure the above parameters are set before update */ new_plane_state->pending.async_dirty = true; - mtk_drm_crtc_async_update(new_state->crtc, plane, state); + mtk_crtc_async_update(new_state->crtc, plane, state); } static const struct drm_plane_funcs mtk_plane_funcs = { @@ -241,7 +241,7 @@ static const struct drm_plane_funcs mtk_plane_funcs = { .destroy = drm_plane_cleanup, .reset = mtk_plane_reset, .atomic_duplicate_state = mtk_plane_duplicate_state, - .atomic_destroy_state = mtk_drm_plane_destroy_state, + .atomic_destroy_state = mtk_plane_destroy_state, .format_mod_supported = mtk_plane_format_mod_supported, }; @@ -260,8 +260,8 @@ static int mtk_plane_atomic_check(struct drm_plane *plane, if (WARN_ON(!new_plane_state->crtc)) return 0; - ret = mtk_drm_crtc_plane_check(new_plane_state->crtc, plane, - to_mtk_plane_state(new_plane_state)); + ret = mtk_crtc_plane_check(new_plane_state->crtc, plane, + to_mtk_plane_state(new_plane_state)); if (ret) return ret; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.h b/drivers/gpu/drm/mediatek/mtk_plane.h similarity index 95% rename from drivers/gpu/drm/mediatek/mtk_drm_plane.h rename to drivers/gpu/drm/mediatek/mtk_plane.h index 99aff7da0831..231bb7aac947 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.h +++ b/drivers/gpu/drm/mediatek/mtk_plane.h @@ -4,8 +4,8 @@ * Author: CK Hu */ -#ifndef _MTK_DRM_PLANE_H_ -#define _MTK_DRM_PLANE_H_ +#ifndef _MTK_PLANE_H_ +#define _MTK_PLANE_H_ #include #include diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c index a6bc1bdb3d0d..a10cff3ca1fe 100644 --- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c +++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c @@ -95,6 +95,7 @@ static int dw_mipi_dsi_phy_init(void *priv_data) return ret; } + clk_disable_unprepare(mipi_dsi->px_clk); ret = clk_set_rate(mipi_dsi->px_clk, mipi_dsi->mode->clock * 1000); if (ret) { @@ -103,6 +104,12 @@ static int dw_mipi_dsi_phy_init(void *priv_data) return ret; } + ret = clk_prepare_enable(mipi_dsi->px_clk); + if (ret) { + dev_err(mipi_dsi->dev, "Failed to enable DSI Pixel clock (ret %d)\n", ret); + return ret; + } + switch (mipi_dsi->dsi_device->format) { case MIPI_DSI_FMT_RGB888: dpi_data_format = DPI_COLOR_24BIT; diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 765e49fd8911..58a0e62eaf18 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -366,6 +366,7 @@ struct drm_crtc_state; struct drm_display_mode; struct drm_plane; struct drm_atomic_state; +struct drm_scanout_buffer; extern const uint32_t mgag200_primary_plane_formats[]; extern const size_t mgag200_primary_plane_formats_size; @@ -379,12 +380,16 @@ void mgag200_primary_plane_helper_atomic_enable(struct drm_plane *plane, struct drm_atomic_state *state); void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, struct drm_atomic_state *old_state); +int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb); + #define MGAG200_PRIMARY_PLANE_HELPER_FUNCS \ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, \ .atomic_check = mgag200_primary_plane_helper_atomic_check, \ .atomic_update = mgag200_primary_plane_helper_atomic_update, \ .atomic_enable = mgag200_primary_plane_helper_atomic_enable, \ - .atomic_disable = mgag200_primary_plane_helper_atomic_disable + .atomic_disable = mgag200_primary_plane_helper_atomic_disable, \ + .get_scanout_buffer = mgag200_primary_plane_helper_get_scanout_buffer #define MGAG200_PRIMARY_PLANE_FUNCS \ .update_plane = drm_atomic_helper_update_plane, \ diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index e17cb4c5f774..fc54851d3384 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "mgag200_drv.h" @@ -546,6 +547,23 @@ void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane, msleep(20); } +int mgag200_primary_plane_helper_get_scanout_buffer(struct drm_plane *plane, + struct drm_scanout_buffer *sb) +{ + struct mga_device *mdev = to_mga_device(plane->dev); + struct iosys_map map = IOSYS_MAP_INIT_VADDR_IOMEM(mdev->vram); + + if (plane->state && plane->state->fb) { + sb->format = plane->state->fb->format; + sb->width = plane->state->fb->width; + sb->height = plane->state->fb->height; + sb->pitch[0] = plane->state->fb->pitches[0]; + sb->map[0] = map; + return 0; + } + return -ENODEV; +} + /* * CRTC */ diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 0674aca0f8a3..cf0b1de1c071 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1377,6 +1377,10 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu) if (adreno_is_a618(gpu)) gpu->ubwc_config.highest_bank_bit = 14; + if (adreno_is_a619(gpu)) + /* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */ + gpu->ubwc_config.highest_bank_bit = 13; + if (adreno_is_a619_holi(gpu)) gpu->ubwc_config.highest_bank_bit = 13; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 1f5245fc2cdc..a847a0f7a73c 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -852,7 +852,7 @@ static void a6xx_get_shader_block(struct msm_gpu *gpu, (block->type << 8) | i); in += CRASHDUMP_READ(in, REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE, - block->size, dumper->iova + A6XX_CD_DATA_OFFSET); + block->size, out); out += block->size * sizeof(u32); } diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h index 9a9f7092c526..a3e60ac70689 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h @@ -324,6 +324,7 @@ static const struct dpu_wb_cfg x1e80100_wb[] = { }, }; +/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */ static const struct dpu_intf_cfg x1e80100_intf[] = { { .name = "intf_0", .id = INTF_0, @@ -358,8 +359,8 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, .features = INTF_SC7280_MASK, - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), @@ -368,7 +369,7 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .base = 0x38000, .len = 0x280, .features = INTF_SC7280_MASK, .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_2, + .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), @@ -381,6 +382,33 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), + }, { + .name = "intf_6", .id = INTF_6, + .base = 0x3A000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_2, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), + }, { + .name = "intf_7", .id = INTF_7, + .base = 0x3b000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19), + }, { + .name = "intf_8", .id = INTF_8, + .base = 0x3c000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index ef871239adb2..68fae048a9a8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -459,15 +459,15 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent) &perf->core_clk_rate); debugfs_create_u32("enable_bw_release", 0600, entry, (u32 *)&perf->enable_bw_release); - debugfs_create_u32("threshold_low", 0600, entry, + debugfs_create_u32("threshold_low", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_low); - debugfs_create_u32("threshold_high", 0600, entry, + debugfs_create_u32("threshold_high", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_high); - debugfs_create_u32("min_core_ib", 0600, entry, + debugfs_create_u32("min_core_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_core_ib); - debugfs_create_u32("min_llcc_ib", 0600, entry, + debugfs_create_u32("min_llcc_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_llcc_ib); - debugfs_create_u32("min_dram_ib", 0600, entry, + debugfs_create_u32("min_dram_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_dram_ib); debugfs_create_file("perf_mode", 0600, entry, (u32 *)perf, &dpu_core_perf_mode_fops); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 946dd0135dff..6a0a74832fb6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -525,14 +525,14 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int ret; if (!irq_cb) { - DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", - DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); + DPU_ERROR("IRQ=[%d, %d] NULL callback\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } if (!dpu_core_irq_is_valid(irq_idx)) { - DPU_ERROR("invalid IRQ=[%d, %d]\n", - DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); + DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); return -EINVAL; } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c index 0bf8a83e8df3..8586f2761782 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c @@ -2,6 +2,8 @@ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ +#include + #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_lm.h" diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index c4cb82af5c2f..ffbfde922589 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -484,7 +484,7 @@ static void dp_display_handle_video_request(struct dp_display_private *dp) } } -static int dp_display_handle_port_ststus_changed(struct dp_display_private *dp) +static int dp_display_handle_port_status_changed(struct dp_display_private *dp) { int rc = 0; @@ -541,7 +541,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) drm_dbg_dp(dp->drm_dev, "hpd_state=%d sink_request=%d\n", dp->hpd_state, sink_request); if (sink_request & DS_PORT_STATUS_CHANGED) - rc = dp_display_handle_port_ststus_changed(dp); + rc = dp_display_handle_port_status_changed(dp); else rc = dp_display_handle_irq_hpd(dp); } @@ -588,6 +588,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) ret = dp_display_usbpd_configure_cb(&pdev->dev); if (ret) { /* link train failed */ dp->hpd_state = ST_DISCONNECTED; + pm_runtime_put_sync(&pdev->dev); } else { dp->hpd_state = ST_MAINLINK_READY; } @@ -645,6 +646,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_display_host_phy_exit(dp); dp->hpd_state = ST_DISCONNECTED; dp_display_notify_disconnect(&dp->dp_display.pdev->dev); + pm_runtime_put_sync(&pdev->dev); mutex_unlock(&dp->event_mutex); return 0; } diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index e3f61c39df69..80166f702a0d 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -89,7 +89,7 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, for (i = 0; i < n; i++) { ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]); - drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", + drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n", fb->base.id, i, msm_fb->iova[i], ret); if (ret) return ret; @@ -176,7 +176,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, const struct msm_format *format; int ret, i, n; - drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)", + drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)\n", mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); @@ -232,7 +232,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, refcount_set(&msm_fb->dirtyfb, 1); - drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb); + drm_dbg_state(dev, "create: FB ID: %d (%p)\n", fb->base.id, fb); return fb; diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index 84c21ec2ceea..af6a6fcb1173 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -149,7 +149,7 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc) struct msm_kms *kms = priv->kms; if (!kms) return -ENXIO; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id); return vblank_ctrl_queue_work(priv, crtc, true); } @@ -160,7 +160,7 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc) struct msm_kms *kms = priv->kms; if (!kms) return; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id); vblank_ctrl_queue_work(priv, crtc, false); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c index 9c942fbd836d..5936b6b3b15d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +#include #include + #include #include #include diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 479effcf607e..79cfab53f80e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -23,6 +23,7 @@ */ #include "nouveau_drv.h" +#include "nouveau_bios.h" #include "nouveau_reg.h" #include "dispnv04/hw.h" #include "nouveau_encoder.h" @@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) */ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { if (*conn == 0xf2005014 && *conf == 0xffffffff) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B); return false; } } @@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) #ifdef __powerpc__ /* Apple iMac G4 NV17 */ if (of_machine_is_compatible("PowerMac4,5")) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1); - fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B); + fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C); return; } #endif /* Make up some sane defaults */ fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, - bios->legacy.i2c_indices.crt, 1, 1); + bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B); if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) fabricate_dcb_output(dcb, DCB_OUTPUT_TV, bios->legacy.i2c_indices.tv, - all_heads, 0); + all_heads, DCB_OUTPUT_A); else if (bios->tmds.output0_script_ptr || bios->tmds.output1_script_ptr) fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, bios->legacy.i2c_indices.panel, - all_heads, 1); + all_heads, DCB_OUTPUT_B); } static int diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index f28f9a857458..aed5d5b51b43 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -83,7 +83,7 @@ static bool nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime) { - struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; + struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc); struct nvif_head *head = &nouveau_crtc(crtc)->head; struct nvif_head_scanoutpos_v0 args; int retry = 20; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 7de7707ec6a8..bcda0105160f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -181,7 +181,7 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, if (nouveau_mst) { mstm = outp->dp.mstm; if (mstm) - mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); + mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd) == DRM_DP_MST; } if (nouveau_dp_has_sink_count(connector, outp)) { @@ -225,12 +225,18 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, u8 *dpcd = nv_encoder->dp.dpcd; int ret = NOUVEAU_DP_NONE, hpd; - /* If we've already read the DPCD on an eDP device, we don't need to - * reread it as it won't change + /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we + * haven't probed them once before. */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - dpcd[DP_DPCD_REV] != 0) - return NOUVEAU_DP_SST; + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if (connector->status == connector_status_connected) + return NOUVEAU_DP_SST; + else if (connector->status == connector_status_disconnected) + return NOUVEAU_DP_NONE; + } + + // Ensure that the aux bus is enabled for probing + drm_dp_dpcd_set_powered(&nv_connector->aux, true); mutex_lock(&nv_encoder->dp.hpd_irq_lock); if (mstm) { @@ -293,6 +299,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST) nv50_mstm_remove(mstm); + /* GSP doesn't like when we try to do aux transactions on a port it considers disconnected, + * and since we don't really have a usecase for that anyway - just disable the aux bus here + * if we've decided the connector is disconnected + */ + if (ret == NOUVEAU_DP_NONE) + drm_dp_dpcd_set_powered(&nv_connector->aux, false); + mutex_unlock(&nv_encoder->dp.hpd_irq_lock); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c index 0a0a11dc9ec0..ee02cd833c5e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c @@ -812,15 +812,15 @@ op_remap(struct drm_gpuva_op_remap *r, struct drm_gpuva_op_unmap *u = r->unmap; struct nouveau_uvma *uvma = uvma_from_va(u->va); u64 addr = uvma->va.va.addr; - u64 range = uvma->va.va.range; + u64 end = uvma->va.va.addr + uvma->va.va.range; if (r->prev) addr = r->prev->va.addr + r->prev->va.range; if (r->next) - range = r->next->va.addr - addr; + end = r->next->va.addr; - op_unmap_range(u, addr, range); + op_unmap_range(u, addr, end - addr); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 986e8d547c94..060c74a80eb1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -420,7 +420,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_chan *fifoch, return ret; } else { ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb, - &args, sizeof(args));; + &args, sizeof(args)); if (ret) return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c index 4bf486b57101..cb05f7f48a98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c @@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name) return ERR_PTR(-EINVAL); } +static void of_fini(void *p) +{ + kfree(p); +} + const struct nvbios_source nvbios_of = { .name = "OpenFirmware", .init = of_init, - .fini = (void(*)(void *))kfree, + .fini = of_fini, .read = of_read, .size = of_size, .rw = false, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c index 7bcbc4895ec2..271bfa038f5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c @@ -25,6 +25,7 @@ #include #include +#include void gm107_devinit_disable(struct nvkm_devinit *init) @@ -33,10 +34,13 @@ gm107_devinit_disable(struct nvkm_devinit *init) u32 r021c00 = nvkm_rd32(device, 0x021c00); u32 r021c04 = nvkm_rd32(device, 0x021c04); - if (r021c00 & 0x00000001) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - if (r021c00 & 0x00000004) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + /* gsp only wants to enable/disable display */ + if (!nvkm_gsp_rm(device->gsp)) { + if (r021c00 & 0x00000001) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); + if (r021c00 & 0x00000004) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + } if (r021c04 & 0x00000001) nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c index 11b4c9c274a1..666eb93b1742 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c @@ -41,6 +41,7 @@ r535_devinit_new(const struct nvkm_devinit_func *hw, rm->dtor = r535_devinit_dtor; rm->post = hw->post; + rm->disable = hw->disable; ret = nv50_devinit_new_(rm, device, type, inst, pdevinit); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 9994cbd6f1c4..9858c1438aa7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -1112,7 +1112,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); - strings = (char *)&rpc->entries[NV_GSP_REG_NUM_ENTRIES]; + strings = (char *)rpc + str_offset; for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { int name_len = strlen(r535_registry_entries[i].name) + 1; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index a7f3fc342d87..dd5b5a17ece0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory) void __iomem *map = NULL; /* Already mapped? */ - if (refcount_inc_not_zero(&iobj->maps)) + if (refcount_inc_not_zero(&iobj->maps)) { + /* read barrier match the wmb on refcount set */ + smp_rmb(); return iobj->map; + } /* Take the lock, and re-check that another thread hasn't * already mapped the object in the meantime. @@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory) iobj->base.memory.ptrs = &nv50_instobj_fast; else iobj->base.memory.ptrs = &nv50_instobj_slow; + /* barrier to ensure the ptrs are written before refcount is set */ + smp_wmb(); refcount_set(&iobj->maps, 1); } diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 1d414b33fee3..449d521c78fe 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -5,6 +5,7 @@ */ #include +#include #include #include diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index 154f5bf82980..e54f6f5604ed 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -335,6 +335,17 @@ config DRM_PANEL_LG_LG4573 Say Y here if you want to enable support for LG4573 RGB panel. To compile this driver as a module, choose M here. +config DRM_PANEL_LG_SW43408 + tristate "LG SW43408 panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for LG sw43408 panel. + The panel has a 1080x2160@60Hz resolution and uses 24 bit RGB per + pixel. It provides a MIPI DSI interface to the host and has a + built-in LED backlight. + config DRM_PANEL_MAGNACHIP_D53E6EA8966 tristate "Magnachip D53E6EA8966 DSI panel" depends on OF && SPI @@ -542,6 +553,18 @@ config DRM_PANEL_RAYDIUM_RM692E5 Say Y here if you want to enable support for Raydium RM692E5-based display panels, such as the one found in the Fairphone 5 smartphone. +config DRM_PANEL_RAYDIUM_RM69380 + tristate "Raydium RM69380-based DSI panel" + depends on OF && GPIOLIB + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Raydium RM69380-based + display panels. + + This panel controller can be found in the Lenovo Xiaoxin Pad Pro 2021 + in combination with an EDO OLED panel. + config DRM_PANEL_RONBO_RB070D30 tristate "Ronbo Electronics RB070D30 panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index 24a02655d726..f0203f6e02f4 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK050H3146W) += panel-leadtek-ltk050h3146w.o obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o +obj-$(CONFIG_DRM_PANEL_LG_SW43408) += panel-lg-sw43408.o obj-$(CONFIG_DRM_PANEL_MAGNACHIP_D53E6EA8966) += panel-magnachip-d53e6ea8966.o obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o @@ -55,6 +56,7 @@ obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM692E5) += panel-raydium-rm692e5.o +obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM69380) += panel-raydium-rm69380.o obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_ATNA33XC20) += panel-samsung-atna33xc20.o obj-$(CONFIG_DRM_PANEL_SAMSUNG_DB7430) += panel-samsung-db7430.o diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index d29bacf25c12..6db277efcbb7 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -242,7 +242,7 @@ struct panel_edp { const struct edp_panel_entry *detected_panel; - struct edid *edid; + const struct drm_edid *drm_edid; struct drm_display_mode override_mode; @@ -617,13 +617,16 @@ static int panel_edp_get_modes(struct drm_panel *panel, if (p->ddc) { pm_runtime_get_sync(panel->dev); - if (!p->edid) - p->edid = drm_get_edid(connector, p->ddc); + if (!p->drm_edid) + p->drm_edid = drm_edid_read_ddc(connector, p->ddc); + + drm_edid_connector_update(connector, p->drm_edid); + /* * If both edid and hard-coded modes exists, skip edid modes to * avoid multiple preferred modes. */ - if (p->edid && !has_hard_coded_modes) { + if (p->drm_edid && !has_hard_coded_modes) { if (has_override_edid_mode) { /* * override_edid_mode is specified. Use @@ -632,7 +635,7 @@ static int panel_edp_get_modes(struct drm_panel *panel, num += panel_edp_override_edid_mode(p, connector, p->detected_panel->override_edid_mode); } else { - num += drm_add_edid_modes(connector, p->edid); + num += drm_edid_connector_add_modes(connector); } } @@ -981,8 +984,8 @@ static void panel_edp_remove(struct device *dev) if (panel->ddc && (!panel->aux || panel->ddc != &panel->aux->ddc)) put_device(&panel->ddc->dev); - kfree(panel->edid); - panel->edid = NULL; + drm_edid_free(panel->drm_edid); + panel->drm_edid = NULL; } static void panel_edp_shutdown(struct device *dev) @@ -2075,6 +2078,8 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('C', 'S', 'O', 0x1200, &delay_200_500_e50_p2e200, "MNC207QS1-1"), + EDP_PANEL_ENTRY('C', 'S', 'W', 0x1100, &delay_200_500_e80_d50, "MNB601LS1-1"), + EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d51, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5b, &delay_200_500_e200, "Unknown"), EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5c, &delay_200_500_e200, "MB116AN01-2"), diff --git a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c index 3e0a8e0d58a0..483dc88d16d8 100644 --- a/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c +++ b/drivers/gpu/drm/panel/panel-jdi-fhd-r63452.c @@ -247,6 +247,7 @@ static int jdi_fhd_r63452_probe(struct mipi_dsi_device *dsi) drm_panel_init(&ctx->panel, dev, &jdi_fhd_r63452_panel_funcs, DRM_MODE_CONNECTOR_DSI); + ctx->panel.prepare_prev_first = true; ret = drm_panel_of_backlight(&ctx->panel); if (ret) diff --git a/drivers/gpu/drm/panel/panel-khadas-ts050.c b/drivers/gpu/drm/panel/panel-khadas-ts050.c index b942a0162274..c54be0cc3f08 100644 --- a/drivers/gpu/drm/panel/panel-khadas-ts050.c +++ b/drivers/gpu/drm/panel/panel-khadas-ts050.c @@ -25,6 +25,7 @@ struct khadas_ts050_panel { struct regulator *supply; struct gpio_desc *reset_gpio; struct gpio_desc *enable_gpio; + struct khadas_ts050_panel_data *panel_data; bool prepared; bool enabled; @@ -32,544 +33,601 @@ struct khadas_ts050_panel { struct khadas_ts050_panel_cmd { u8 cmd; - u8 data; + u8 data[55]; + u8 size; +}; + +struct khadas_ts050_panel_data { + struct khadas_ts050_panel_cmd *init_code; + int len; +}; + +static const struct khadas_ts050_panel_cmd ts050v2_init_code[] = { + {0xB9, {0xFF, 0x83, 0x99}, 0x03}, + {0xBA, {0x63, 0x23, 0x68, 0xCF}, 0x04}, + {0xD2, {0x55}, 0x01}, + {0xB1, {0x02, 0x04, 0x70, 0x90, 0x01, 0x32, 0x33, + 0x11, 0x11, 0x4D, 0x57, 0x56, 0x73, 0x02, 0x02}, 0x0f}, + {0xB2, {0x00, 0x80, 0x80, 0xAE, 0x0A, 0x0E, 0x75, 0x11, 0x00, 0x00, 0x00}, 0x0b}, + {0xB4, {0x00, 0xFF, 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, + 0x00, 0x24, 0x02, 0x04, 0x0A, 0x21, 0x03, 0x00, 0x00, 0x08, 0xA6, 0x88, + 0x04, 0xA4, 0x02, 0xA0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x24, + 0x02, 0x04, 0x0A, 0x00, 0x00, 0x08, 0xA6, 0x00, 0x08, 0x11}, 0x2e}, + {0xD3, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x18, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x11, 0x00, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0A, + 0x40}, 0x21}, + {0xD5, {0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x19, 0x19, 0x19, + 0x19, 0x18, 0x18, 0x18, 0x18, 0x03, 0x02, 0x01, 0x00, 0x2F, 0x2F, + 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, + {0xD6, {0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 0x19, 0x19, 0x18, 0x18, 0x19, + 0x19, 0x18, 0x18, 0x18, 0x18, 0x00, 0x01, 0x02, 0x03, 0x2F, 0x2F, + 0x30, 0x30, 0x31, 0x31, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18}, 0x20}, + {0xD8, {0x0A, 0xBE, 0xFA, 0xA0, 0x0A, 0xBE, 0xFA, 0xA0}, 0x08}, + {0xBD, {0x01}, 0x01}, + {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, + {0xBD, {0x02}, 0x01}, + {0xD8, {0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0}, 0x08}, + {0xBD, {0x00}, 0x01}, + {0xE0, {0x01, 0x35, 0x41, 0x3B, 0x79, 0x81, 0x8C, 0x85, 0x8E, + 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, 0xB3, 0xB7, 0xC5, 0xBD, 0xC5, + 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, 0x73, 0x01, 0x35, 0x41, 0x3B, + 0x79, 0x81, 0x8C, 0x85, 0x8E, 0x95, 0x9B, 0xA0, 0xA4, 0xAB, 0xB1, + 0xB3, 0xB7, 0xB5, 0xBD, 0xC5, 0xB6, 0xC2, 0xC2, 0x62, 0x5D, 0x66, + 0x73}, 0x36}, + {0xB6, {0x97, 0x97}, 0x02}, + {0xCC, {0xC8}, 0x02}, + {0xBF, {0x40, 0x41, 0x50, 0x19}, 0x04}, + {0xC6, {0xFF, 0xF9}, 0x02}, + {0xC0, {0x25, 0x5A}, 0x02}, }; /* Only the CMD1 User Command set is documented */ -static const struct khadas_ts050_panel_cmd init_code[] = { +static const struct khadas_ts050_panel_cmd ts050_init_code[] = { /* Select Unknown CMD Page (Undocumented) */ - {0xff, 0xee}, + {0xff, {0xee}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, - {0x1f, 0x45}, - {0x24, 0x4f}, - {0x38, 0xc8}, - {0x39, 0x27}, - {0x1e, 0x77}, - {0x1d, 0x0f}, - {0x7e, 0x71}, - {0x7c, 0x03}, - {0xff, 0x00}, - {0xfb, 0x01}, - {0x35, 0x01}, + {0xfb, {0x01}, 0x01}, + {0x1f, {0x45}, 0x01}, + {0x24, {0x4f}, 0x01}, + {0x38, {0xc8}, 0x01}, + {0x39, {0x27}, 0x01}, + {0x1e, {0x77}, 0x01}, + {0x1d, {0x0f}, 0x01}, + {0x7e, {0x71}, 0x01}, + {0x7c, {0x03}, 0x01}, + {0xff, {0x00}, 0x01}, + {0xfb, {0x01}, 0x01}, + {0x35, {0x01}, 0x01}, /* Select CMD2 Page0 (Undocumented) */ - {0xff, 0x01}, + {0xff, {0x01}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, - {0x00, 0x01}, - {0x01, 0x55}, - {0x02, 0x40}, - {0x05, 0x40}, - {0x06, 0x4a}, - {0x07, 0x24}, - {0x08, 0x0c}, - {0x0b, 0x7d}, - {0x0c, 0x7d}, - {0x0e, 0xb0}, - {0x0f, 0xae}, - {0x11, 0x10}, - {0x12, 0x10}, - {0x13, 0x03}, - {0x14, 0x4a}, - {0x15, 0x12}, - {0x16, 0x12}, - {0x18, 0x00}, - {0x19, 0x77}, - {0x1a, 0x55}, - {0x1b, 0x13}, - {0x1c, 0x00}, - {0x1d, 0x00}, - {0x1e, 0x13}, - {0x1f, 0x00}, - {0x23, 0x00}, - {0x24, 0x00}, - {0x25, 0x00}, - {0x26, 0x00}, - {0x27, 0x00}, - {0x28, 0x00}, - {0x35, 0x00}, - {0x66, 0x00}, - {0x58, 0x82}, - {0x59, 0x02}, - {0x5a, 0x02}, - {0x5b, 0x02}, - {0x5c, 0x82}, - {0x5d, 0x82}, - {0x5e, 0x02}, - {0x5f, 0x02}, - {0x72, 0x31}, + {0xfb, {0x01}, 0x01}, + {0x00, {0x01}, 0x01}, + {0x01, {0x55}, 0x01}, + {0x02, {0x40}, 0x01}, + {0x05, {0x40}, 0x01}, + {0x06, {0x4a}, 0x01}, + {0x07, {0x24}, 0x01}, + {0x08, {0x0c}, 0x01}, + {0x0b, {0x7d}, 0x01}, + {0x0c, {0x7d}, 0x01}, + {0x0e, {0xb0}, 0x01}, + {0x0f, {0xae}, 0x01}, + {0x11, {0x10}, 0x01}, + {0x12, {0x10}, 0x01}, + {0x13, {0x03}, 0x01}, + {0x14, {0x4a}, 0x01}, + {0x15, {0x12}, 0x01}, + {0x16, {0x12}, 0x01}, + {0x18, {0x00}, 0x01}, + {0x19, {0x77}, 0x01}, + {0x1a, {0x55}, 0x01}, + {0x1b, {0x13}, 0x01}, + {0x1c, {0x00}, 0x01}, + {0x1d, {0x00}, 0x01}, + {0x1e, {0x13}, 0x01}, + {0x1f, {0x00}, 0x01}, + {0x23, {0x00}, 0x01}, + {0x24, {0x00}, 0x01}, + {0x25, {0x00}, 0x01}, + {0x26, {0x00}, 0x01}, + {0x27, {0x00}, 0x01}, + {0x28, {0x00}, 0x01}, + {0x35, {0x00}, 0x01}, + {0x66, {0x00}, 0x01}, + {0x58, {0x82}, 0x01}, + {0x59, {0x02}, 0x01}, + {0x5a, {0x02}, 0x01}, + {0x5b, {0x02}, 0x01}, + {0x5c, {0x82}, 0x01}, + {0x5d, {0x82}, 0x01}, + {0x5e, {0x02}, 0x01}, + {0x5f, {0x02}, 0x01}, + {0x72, {0x31}, 0x01}, /* Select CMD2 Page4 (Undocumented) */ - {0xff, 0x05}, + {0xff, {0x05}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, - {0x00, 0x01}, - {0x01, 0x0b}, - {0x02, 0x0c}, - {0x03, 0x09}, - {0x04, 0x0a}, - {0x05, 0x00}, - {0x06, 0x0f}, - {0x07, 0x10}, - {0x08, 0x00}, - {0x09, 0x00}, - {0x0a, 0x00}, - {0x0b, 0x00}, - {0x0c, 0x00}, - {0x0d, 0x13}, - {0x0e, 0x15}, - {0x0f, 0x17}, - {0x10, 0x01}, - {0x11, 0x0b}, - {0x12, 0x0c}, - {0x13, 0x09}, - {0x14, 0x0a}, - {0x15, 0x00}, - {0x16, 0x0f}, - {0x17, 0x10}, - {0x18, 0x00}, - {0x19, 0x00}, - {0x1a, 0x00}, - {0x1b, 0x00}, - {0x1c, 0x00}, - {0x1d, 0x13}, - {0x1e, 0x15}, - {0x1f, 0x17}, - {0x20, 0x00}, - {0x21, 0x03}, - {0x22, 0x01}, - {0x23, 0x40}, - {0x24, 0x40}, - {0x25, 0xed}, - {0x29, 0x58}, - {0x2a, 0x12}, - {0x2b, 0x01}, - {0x4b, 0x06}, - {0x4c, 0x11}, - {0x4d, 0x20}, - {0x4e, 0x02}, - {0x4f, 0x02}, - {0x50, 0x20}, - {0x51, 0x61}, - {0x52, 0x01}, - {0x53, 0x63}, - {0x54, 0x77}, - {0x55, 0xed}, - {0x5b, 0x00}, - {0x5c, 0x00}, - {0x5d, 0x00}, - {0x5e, 0x00}, - {0x5f, 0x15}, - {0x60, 0x75}, - {0x61, 0x00}, - {0x62, 0x00}, - {0x63, 0x00}, - {0x64, 0x00}, - {0x65, 0x00}, - {0x66, 0x00}, - {0x67, 0x00}, - {0x68, 0x04}, - {0x69, 0x00}, - {0x6a, 0x00}, - {0x6c, 0x40}, - {0x75, 0x01}, - {0x76, 0x01}, - {0x7a, 0x80}, - {0x7b, 0xa3}, - {0x7c, 0xd8}, - {0x7d, 0x60}, - {0x7f, 0x15}, - {0x80, 0x81}, - {0x83, 0x05}, - {0x93, 0x08}, - {0x94, 0x10}, - {0x8a, 0x00}, - {0x9b, 0x0f}, - {0xea, 0xff}, - {0xec, 0x00}, + {0xfb, {0x01}, 0x01}, + {0x00, {0x01}, 0x01}, + {0x01, {0x0b}, 0x01}, + {0x02, {0x0c}, 0x01}, + {0x03, {0x09}, 0x01}, + {0x04, {0x0a}, 0x01}, + {0x05, {0x00}, 0x01}, + {0x06, {0x0f}, 0x01}, + {0x07, {0x10}, 0x01}, + {0x08, {0x00}, 0x01}, + {0x09, {0x00}, 0x01}, + {0x0a, {0x00}, 0x01}, + {0x0b, {0x00}, 0x01}, + {0x0c, {0x00}, 0x01}, + {0x0d, {0x13}, 0x01}, + {0x0e, {0x15}, 0x01}, + {0x0f, {0x17}, 0x01}, + {0x10, {0x01}, 0x01}, + {0x11, {0x0b}, 0x01}, + {0x12, {0x0c}, 0x01}, + {0x13, {0x09}, 0x01}, + {0x14, {0x0a}, 0x01}, + {0x15, {0x00}, 0x01}, + {0x16, {0x0f}, 0x01}, + {0x17, {0x10}, 0x01}, + {0x18, {0x00}, 0x01}, + {0x19, {0x00}, 0x01}, + {0x1a, {0x00}, 0x01}, + {0x1b, {0x00}, 0x01}, + {0x1c, {0x00}, 0x01}, + {0x1d, {0x13}, 0x01}, + {0x1e, {0x15}, 0x01}, + {0x1f, {0x17}, 0x01}, + {0x20, {0x00}, 0x01}, + {0x21, {0x03}, 0x01}, + {0x22, {0x01}, 0x01}, + {0x23, {0x40}, 0x01}, + {0x24, {0x40}, 0x01}, + {0x25, {0xed}, 0x01}, + {0x29, {0x58}, 0x01}, + {0x2a, {0x12}, 0x01}, + {0x2b, {0x01}, 0x01}, + {0x4b, {0x06}, 0x01}, + {0x4c, {0x11}, 0x01}, + {0x4d, {0x20}, 0x01}, + {0x4e, {0x02}, 0x01}, + {0x4f, {0x02}, 0x01}, + {0x50, {0x20}, 0x01}, + {0x51, {0x61}, 0x01}, + {0x52, {0x01}, 0x01}, + {0x53, {0x63}, 0x01}, + {0x54, {0x77}, 0x01}, + {0x55, {0xed}, 0x01}, + {0x5b, {0x00}, 0x01}, + {0x5c, {0x00}, 0x01}, + {0x5d, {0x00}, 0x01}, + {0x5e, {0x00}, 0x01}, + {0x5f, {0x15}, 0x01}, + {0x60, {0x75}, 0x01}, + {0x61, {0x00}, 0x01}, + {0x62, {0x00}, 0x01}, + {0x63, {0x00}, 0x01}, + {0x64, {0x00}, 0x01}, + {0x65, {0x00}, 0x01}, + {0x66, {0x00}, 0x01}, + {0x67, {0x00}, 0x01}, + {0x68, {0x04}, 0x01}, + {0x69, {0x00}, 0x01}, + {0x6a, {0x00}, 0x01}, + {0x6c, {0x40}, 0x01}, + {0x75, {0x01}, 0x01}, + {0x76, {0x01}, 0x01}, + {0x7a, {0x80}, 0x01}, + {0x7b, {0xa3}, 0x01}, + {0x7c, {0xd8}, 0x01}, + {0x7d, {0x60}, 0x01}, + {0x7f, {0x15}, 0x01}, + {0x80, {0x81}, 0x01}, + {0x83, {0x05}, 0x01}, + {0x93, {0x08}, 0x01}, + {0x94, {0x10}, 0x01}, + {0x8a, {0x00}, 0x01}, + {0x9b, {0x0f}, 0x01}, + {0xea, {0xff}, 0x01}, + {0xec, {0x00}, 0x01}, /* Select CMD2 Page0 (Undocumented) */ - {0xff, 0x01}, + {0xff, {0x01}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, - {0x75, 0x00}, - {0x76, 0xdf}, - {0x77, 0x00}, - {0x78, 0xe4}, - {0x79, 0x00}, - {0x7a, 0xed}, - {0x7b, 0x00}, - {0x7c, 0xf6}, - {0x7d, 0x00}, - {0x7e, 0xff}, - {0x7f, 0x01}, - {0x80, 0x07}, - {0x81, 0x01}, - {0x82, 0x10}, - {0x83, 0x01}, - {0x84, 0x18}, - {0x85, 0x01}, - {0x86, 0x20}, - {0x87, 0x01}, - {0x88, 0x3d}, - {0x89, 0x01}, - {0x8a, 0x56}, - {0x8b, 0x01}, - {0x8c, 0x84}, - {0x8d, 0x01}, - {0x8e, 0xab}, - {0x8f, 0x01}, - {0x90, 0xec}, - {0x91, 0x02}, - {0x92, 0x22}, - {0x93, 0x02}, - {0x94, 0x23}, - {0x95, 0x02}, - {0x96, 0x55}, - {0x97, 0x02}, - {0x98, 0x8b}, - {0x99, 0x02}, - {0x9a, 0xaf}, - {0x9b, 0x02}, - {0x9c, 0xdf}, - {0x9d, 0x03}, - {0x9e, 0x01}, - {0x9f, 0x03}, - {0xa0, 0x2c}, - {0xa2, 0x03}, - {0xa3, 0x39}, - {0xa4, 0x03}, - {0xa5, 0x47}, - {0xa6, 0x03}, - {0xa7, 0x56}, - {0xa9, 0x03}, - {0xaa, 0x66}, - {0xab, 0x03}, - {0xac, 0x76}, - {0xad, 0x03}, - {0xae, 0x85}, - {0xaf, 0x03}, - {0xb0, 0x90}, - {0xb1, 0x03}, - {0xb2, 0xcb}, - {0xb3, 0x00}, - {0xb4, 0xdf}, - {0xb5, 0x00}, - {0xb6, 0xe4}, - {0xb7, 0x00}, - {0xb8, 0xed}, - {0xb9, 0x00}, - {0xba, 0xf6}, - {0xbb, 0x00}, - {0xbc, 0xff}, - {0xbd, 0x01}, - {0xbe, 0x07}, - {0xbf, 0x01}, - {0xc0, 0x10}, - {0xc1, 0x01}, - {0xc2, 0x18}, - {0xc3, 0x01}, - {0xc4, 0x20}, - {0xc5, 0x01}, - {0xc6, 0x3d}, - {0xc7, 0x01}, - {0xc8, 0x56}, - {0xc9, 0x01}, - {0xca, 0x84}, - {0xcb, 0x01}, - {0xcc, 0xab}, - {0xcd, 0x01}, - {0xce, 0xec}, - {0xcf, 0x02}, - {0xd0, 0x22}, - {0xd1, 0x02}, - {0xd2, 0x23}, - {0xd3, 0x02}, - {0xd4, 0x55}, - {0xd5, 0x02}, - {0xd6, 0x8b}, - {0xd7, 0x02}, - {0xd8, 0xaf}, - {0xd9, 0x02}, - {0xda, 0xdf}, - {0xdb, 0x03}, - {0xdc, 0x01}, - {0xdd, 0x03}, - {0xde, 0x2c}, - {0xdf, 0x03}, - {0xe0, 0x39}, - {0xe1, 0x03}, - {0xe2, 0x47}, - {0xe3, 0x03}, - {0xe4, 0x56}, - {0xe5, 0x03}, - {0xe6, 0x66}, - {0xe7, 0x03}, - {0xe8, 0x76}, - {0xe9, 0x03}, - {0xea, 0x85}, - {0xeb, 0x03}, - {0xec, 0x90}, - {0xed, 0x03}, - {0xee, 0xcb}, - {0xef, 0x00}, - {0xf0, 0xbb}, - {0xf1, 0x00}, - {0xf2, 0xc0}, - {0xf3, 0x00}, - {0xf4, 0xcc}, - {0xf5, 0x00}, - {0xf6, 0xd6}, - {0xf7, 0x00}, - {0xf8, 0xe1}, - {0xf9, 0x00}, - {0xfa, 0xea}, + {0xfb, {0x01}, 0x01}, + {0x75, {0x00}, 0x01}, + {0x76, {0xdf}, 0x01}, + {0x77, {0x00}, 0x01}, + {0x78, {0xe4}, 0x01}, + {0x79, {0x00}, 0x01}, + {0x7a, {0xed}, 0x01}, + {0x7b, {0x00}, 0x01}, + {0x7c, {0xf6}, 0x01}, + {0x7d, {0x00}, 0x01}, + {0x7e, {0xff}, 0x01}, + {0x7f, {0x01}, 0x01}, + {0x80, {0x07}, 0x01}, + {0x81, {0x01}, 0x01}, + {0x82, {0x10}, 0x01}, + {0x83, {0x01}, 0x01}, + {0x84, {0x18}, 0x01}, + {0x85, {0x01}, 0x01}, + {0x86, {0x20}, 0x01}, + {0x87, {0x01}, 0x01}, + {0x88, {0x3d}, 0x01}, + {0x89, {0x01}, 0x01}, + {0x8a, {0x56}, 0x01}, + {0x8b, {0x01}, 0x01}, + {0x8c, {0x84}, 0x01}, + {0x8d, {0x01}, 0x01}, + {0x8e, {0xab}, 0x01}, + {0x8f, {0x01}, 0x01}, + {0x90, {0xec}, 0x01}, + {0x91, {0x02}, 0x01}, + {0x92, {0x22}, 0x01}, + {0x93, {0x02}, 0x01}, + {0x94, {0x23}, 0x01}, + {0x95, {0x02}, 0x01}, + {0x96, {0x55}, 0x01}, + {0x97, {0x02}, 0x01}, + {0x98, {0x8b}, 0x01}, + {0x99, {0x02}, 0x01}, + {0x9a, {0xaf}, 0x01}, + {0x9b, {0x02}, 0x01}, + {0x9c, {0xdf}, 0x01}, + {0x9d, {0x03}, 0x01}, + {0x9e, {0x01}, 0x01}, + {0x9f, {0x03}, 0x01}, + {0xa0, {0x2c}, 0x01}, + {0xa2, {0x03}, 0x01}, + {0xa3, {0x39}, 0x01}, + {0xa4, {0x03}, 0x01}, + {0xa5, {0x47}, 0x01}, + {0xa6, {0x03}, 0x01}, + {0xa7, {0x56}, 0x01}, + {0xa9, {0x03}, 0x01}, + {0xaa, {0x66}, 0x01}, + {0xab, {0x03}, 0x01}, + {0xac, {0x76}, 0x01}, + {0xad, {0x03}, 0x01}, + {0xae, {0x85}, 0x01}, + {0xaf, {0x03}, 0x01}, + {0xb0, {0x90}, 0x01}, + {0xb1, {0x03}, 0x01}, + {0xb2, {0xcb}, 0x01}, + {0xb3, {0x00}, 0x01}, + {0xb4, {0xdf}, 0x01}, + {0xb5, {0x00}, 0x01}, + {0xb6, {0xe4}, 0x01}, + {0xb7, {0x00}, 0x01}, + {0xb8, {0xed}, 0x01}, + {0xb9, {0x00}, 0x01}, + {0xba, {0xf6}, 0x01}, + {0xbb, {0x00}, 0x01}, + {0xbc, {0xff}, 0x01}, + {0xbd, {0x01}, 0x01}, + {0xbe, {0x07}, 0x01}, + {0xbf, {0x01}, 0x01}, + {0xc0, {0x10}, 0x01}, + {0xc1, {0x01}, 0x01}, + {0xc2, {0x18}, 0x01}, + {0xc3, {0x01}, 0x01}, + {0xc4, {0x20}, 0x01}, + {0xc5, {0x01}, 0x01}, + {0xc6, {0x3d}, 0x01}, + {0xc7, {0x01}, 0x01}, + {0xc8, {0x56}, 0x01}, + {0xc9, {0x01}, 0x01}, + {0xca, {0x84}, 0x01}, + {0xcb, {0x01}, 0x01}, + {0xcc, {0xab}, 0x01}, + {0xcd, {0x01}, 0x01}, + {0xce, {0xec}, 0x01}, + {0xcf, {0x02}, 0x01}, + {0xd0, {0x22}, 0x01}, + {0xd1, {0x02}, 0x01}, + {0xd2, {0x23}, 0x01}, + {0xd3, {0x02}, 0x01}, + {0xd4, {0x55}, 0x01}, + {0xd5, {0x02}, 0x01}, + {0xd6, {0x8b}, 0x01}, + {0xd7, {0x02}, 0x01}, + {0xd8, {0xaf}, 0x01}, + {0xd9, {0x02}, 0x01}, + {0xda, {0xdf}, 0x01}, + {0xdb, {0x03}, 0x01}, + {0xdc, {0x01}, 0x01}, + {0xdd, {0x03}, 0x01}, + {0xde, {0x2c}, 0x01}, + {0xdf, {0x03}, 0x01}, + {0xe0, {0x39}, 0x01}, + {0xe1, {0x03}, 0x01}, + {0xe2, {0x47}, 0x01}, + {0xe3, {0x03}, 0x01}, + {0xe4, {0x56}, 0x01}, + {0xe5, {0x03}, 0x01}, + {0xe6, {0x66}, 0x01}, + {0xe7, {0x03}, 0x01}, + {0xe8, {0x76}, 0x01}, + {0xe9, {0x03}, 0x01}, + {0xea, {0x85}, 0x01}, + {0xeb, {0x03}, 0x01}, + {0xec, {0x90}, 0x01}, + {0xed, {0x03}, 0x01}, + {0xee, {0xcb}, 0x01}, + {0xef, {0x00}, 0x01}, + {0xf0, {0xbb}, 0x01}, + {0xf1, {0x00}, 0x01}, + {0xf2, {0xc0}, 0x01}, + {0xf3, {0x00}, 0x01}, + {0xf4, {0xcc}, 0x01}, + {0xf5, {0x00}, 0x01}, + {0xf6, {0xd6}, 0x01}, + {0xf7, {0x00}, 0x01}, + {0xf8, {0xe1}, 0x01}, + {0xf9, {0x00}, 0x01}, + {0xfa, {0xea}, 0x01}, /* Select CMD2 Page2 (Undocumented) */ - {0xff, 0x02}, + {0xff, {0x02}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, - {0x00, 0x00}, - {0x01, 0xf4}, - {0x02, 0x00}, - {0x03, 0xef}, - {0x04, 0x01}, - {0x05, 0x07}, - {0x06, 0x01}, - {0x07, 0x28}, - {0x08, 0x01}, - {0x09, 0x44}, - {0x0a, 0x01}, - {0x0b, 0x76}, - {0x0c, 0x01}, - {0x0d, 0xa0}, - {0x0e, 0x01}, - {0x0f, 0xe7}, - {0x10, 0x02}, - {0x11, 0x1f}, - {0x12, 0x02}, - {0x13, 0x22}, - {0x14, 0x02}, - {0x15, 0x54}, - {0x16, 0x02}, - {0x17, 0x8b}, - {0x18, 0x02}, - {0x19, 0xaf}, - {0x1a, 0x02}, - {0x1b, 0xe0}, - {0x1c, 0x03}, - {0x1d, 0x01}, - {0x1e, 0x03}, - {0x1f, 0x2d}, - {0x20, 0x03}, - {0x21, 0x39}, - {0x22, 0x03}, - {0x23, 0x47}, - {0x24, 0x03}, - {0x25, 0x57}, - {0x26, 0x03}, - {0x27, 0x65}, - {0x28, 0x03}, - {0x29, 0x77}, - {0x2a, 0x03}, - {0x2b, 0x85}, - {0x2d, 0x03}, - {0x2f, 0x8f}, - {0x30, 0x03}, - {0x31, 0xcb}, - {0x32, 0x00}, - {0x33, 0xbb}, - {0x34, 0x00}, - {0x35, 0xc0}, - {0x36, 0x00}, - {0x37, 0xcc}, - {0x38, 0x00}, - {0x39, 0xd6}, - {0x3a, 0x00}, - {0x3b, 0xe1}, - {0x3d, 0x00}, - {0x3f, 0xea}, - {0x40, 0x00}, - {0x41, 0xf4}, - {0x42, 0x00}, - {0x43, 0xfe}, - {0x44, 0x01}, - {0x45, 0x07}, - {0x46, 0x01}, - {0x47, 0x28}, - {0x48, 0x01}, - {0x49, 0x44}, - {0x4a, 0x01}, - {0x4b, 0x76}, - {0x4c, 0x01}, - {0x4d, 0xa0}, - {0x4e, 0x01}, - {0x4f, 0xe7}, - {0x50, 0x02}, - {0x51, 0x1f}, - {0x52, 0x02}, - {0x53, 0x22}, - {0x54, 0x02}, - {0x55, 0x54}, - {0x56, 0x02}, - {0x58, 0x8b}, - {0x59, 0x02}, - {0x5a, 0xaf}, - {0x5b, 0x02}, - {0x5c, 0xe0}, - {0x5d, 0x03}, - {0x5e, 0x01}, - {0x5f, 0x03}, - {0x60, 0x2d}, - {0x61, 0x03}, - {0x62, 0x39}, - {0x63, 0x03}, - {0x64, 0x47}, - {0x65, 0x03}, - {0x66, 0x57}, - {0x67, 0x03}, - {0x68, 0x65}, - {0x69, 0x03}, - {0x6a, 0x77}, - {0x6b, 0x03}, - {0x6c, 0x85}, - {0x6d, 0x03}, - {0x6e, 0x8f}, - {0x6f, 0x03}, - {0x70, 0xcb}, - {0x71, 0x00}, - {0x72, 0x00}, - {0x73, 0x00}, - {0x74, 0x21}, - {0x75, 0x00}, - {0x76, 0x4c}, - {0x77, 0x00}, - {0x78, 0x6b}, - {0x79, 0x00}, - {0x7a, 0x85}, - {0x7b, 0x00}, - {0x7c, 0x9a}, - {0x7d, 0x00}, - {0x7e, 0xad}, - {0x7f, 0x00}, - {0x80, 0xbe}, - {0x81, 0x00}, - {0x82, 0xcd}, - {0x83, 0x01}, - {0x84, 0x01}, - {0x85, 0x01}, - {0x86, 0x29}, - {0x87, 0x01}, - {0x88, 0x68}, - {0x89, 0x01}, - {0x8a, 0x98}, - {0x8b, 0x01}, - {0x8c, 0xe5}, - {0x8d, 0x02}, - {0x8e, 0x1e}, - {0x8f, 0x02}, - {0x90, 0x30}, - {0x91, 0x02}, - {0x92, 0x52}, - {0x93, 0x02}, - {0x94, 0x88}, - {0x95, 0x02}, - {0x96, 0xaa}, - {0x97, 0x02}, - {0x98, 0xd7}, - {0x99, 0x02}, - {0x9a, 0xf7}, - {0x9b, 0x03}, - {0x9c, 0x21}, - {0x9d, 0x03}, - {0x9e, 0x2e}, - {0x9f, 0x03}, - {0xa0, 0x3d}, - {0xa2, 0x03}, - {0xa3, 0x4c}, - {0xa4, 0x03}, - {0xa5, 0x5e}, - {0xa6, 0x03}, - {0xa7, 0x71}, - {0xa9, 0x03}, - {0xaa, 0x86}, - {0xab, 0x03}, - {0xac, 0x94}, - {0xad, 0x03}, - {0xae, 0xfa}, - {0xaf, 0x00}, - {0xb0, 0x00}, - {0xb1, 0x00}, - {0xb2, 0x21}, - {0xb3, 0x00}, - {0xb4, 0x4c}, - {0xb5, 0x00}, - {0xb6, 0x6b}, - {0xb7, 0x00}, - {0xb8, 0x85}, - {0xb9, 0x00}, - {0xba, 0x9a}, - {0xbb, 0x00}, - {0xbc, 0xad}, - {0xbd, 0x00}, - {0xbe, 0xbe}, - {0xbf, 0x00}, - {0xc0, 0xcd}, - {0xc1, 0x01}, - {0xc2, 0x01}, - {0xc3, 0x01}, - {0xc4, 0x29}, - {0xc5, 0x01}, - {0xc6, 0x68}, - {0xc7, 0x01}, - {0xc8, 0x98}, - {0xc9, 0x01}, - {0xca, 0xe5}, - {0xcb, 0x02}, - {0xcc, 0x1e}, - {0xcd, 0x02}, - {0xce, 0x20}, - {0xcf, 0x02}, - {0xd0, 0x52}, - {0xd1, 0x02}, - {0xd2, 0x88}, - {0xd3, 0x02}, - {0xd4, 0xaa}, - {0xd5, 0x02}, - {0xd6, 0xd7}, - {0xd7, 0x02}, - {0xd8, 0xf7}, - {0xd9, 0x03}, - {0xda, 0x21}, - {0xdb, 0x03}, - {0xdc, 0x2e}, - {0xdd, 0x03}, - {0xde, 0x3d}, - {0xdf, 0x03}, - {0xe0, 0x4c}, - {0xe1, 0x03}, - {0xe2, 0x5e}, - {0xe3, 0x03}, - {0xe4, 0x71}, - {0xe5, 0x03}, - {0xe6, 0x86}, - {0xe7, 0x03}, - {0xe8, 0x94}, - {0xe9, 0x03}, - {0xea, 0xfa}, + {0xfb, {0x01}, 0x01}, + {0x00, {0x00}, 0x01}, + {0x01, {0xf4}, 0x01}, + {0x02, {0x00}, 0x01}, + {0x03, {0xef}, 0x01}, + {0x04, {0x01}, 0x01}, + {0x05, {0x07}, 0x01}, + {0x06, {0x01}, 0x01}, + {0x07, {0x28}, 0x01}, + {0x08, {0x01}, 0x01}, + {0x09, {0x44}, 0x01}, + {0x0a, {0x01}, 0x01}, + {0x0b, {0x76}, 0x01}, + {0x0c, {0x01}, 0x01}, + {0x0d, {0xa0}, 0x01}, + {0x0e, {0x01}, 0x01}, + {0x0f, {0xe7}, 0x01}, + {0x10, {0x02}, 0x01}, + {0x11, {0x1f}, 0x01}, + {0x12, {0x02}, 0x01}, + {0x13, {0x22}, 0x01}, + {0x14, {0x02}, 0x01}, + {0x15, {0x54}, 0x01}, + {0x16, {0x02}, 0x01}, + {0x17, {0x8b}, 0x01}, + {0x18, {0x02}, 0x01}, + {0x19, {0xaf}, 0x01}, + {0x1a, {0x02}, 0x01}, + {0x1b, {0xe0}, 0x01}, + {0x1c, {0x03}, 0x01}, + {0x1d, {0x01}, 0x01}, + {0x1e, {0x03}, 0x01}, + {0x1f, {0x2d}, 0x01}, + {0x20, {0x03}, 0x01}, + {0x21, {0x39}, 0x01}, + {0x22, {0x03}, 0x01}, + {0x23, {0x47}, 0x01}, + {0x24, {0x03}, 0x01}, + {0x25, {0x57}, 0x01}, + {0x26, {0x03}, 0x01}, + {0x27, {0x65}, 0x01}, + {0x28, {0x03}, 0x01}, + {0x29, {0x77}, 0x01}, + {0x2a, {0x03}, 0x01}, + {0x2b, {0x85}, 0x01}, + {0x2d, {0x03}, 0x01}, + {0x2f, {0x8f}, 0x01}, + {0x30, {0x03}, 0x01}, + {0x31, {0xcb}, 0x01}, + {0x32, {0x00}, 0x01}, + {0x33, {0xbb}, 0x01}, + {0x34, {0x00}, 0x01}, + {0x35, {0xc0}, 0x01}, + {0x36, {0x00}, 0x01}, + {0x37, {0xcc}, 0x01}, + {0x38, {0x00}, 0x01}, + {0x39, {0xd6}, 0x01}, + {0x3a, {0x00}, 0x01}, + {0x3b, {0xe1}, 0x01}, + {0x3d, {0x00}, 0x01}, + {0x3f, {0xea}, 0x01}, + {0x40, {0x00}, 0x01}, + {0x41, {0xf4}, 0x01}, + {0x42, {0x00}, 0x01}, + {0x43, {0xfe}, 0x01}, + {0x44, {0x01}, 0x01}, + {0x45, {0x07}, 0x01}, + {0x46, {0x01}, 0x01}, + {0x47, {0x28}, 0x01}, + {0x48, {0x01}, 0x01}, + {0x49, {0x44}, 0x01}, + {0x4a, {0x01}, 0x01}, + {0x4b, {0x76}, 0x01}, + {0x4c, {0x01}, 0x01}, + {0x4d, {0xa0}, 0x01}, + {0x4e, {0x01}, 0x01}, + {0x4f, {0xe7}, 0x01}, + {0x50, {0x02}, 0x01}, + {0x51, {0x1f}, 0x01}, + {0x52, {0x02}, 0x01}, + {0x53, {0x22}, 0x01}, + {0x54, {0x02}, 0x01}, + {0x55, {0x54}, 0x01}, + {0x56, {0x02}, 0x01}, + {0x58, {0x8b}, 0x01}, + {0x59, {0x02}, 0x01}, + {0x5a, {0xaf}, 0x01}, + {0x5b, {0x02}, 0x01}, + {0x5c, {0xe0}, 0x01}, + {0x5d, {0x03}, 0x01}, + {0x5e, {0x01}, 0x01}, + {0x5f, {0x03}, 0x01}, + {0x60, {0x2d}, 0x01}, + {0x61, {0x03}, 0x01}, + {0x62, {0x39}, 0x01}, + {0x63, {0x03}, 0x01}, + {0x64, {0x47}, 0x01}, + {0x65, {0x03}, 0x01}, + {0x66, {0x57}, 0x01}, + {0x67, {0x03}, 0x01}, + {0x68, {0x65}, 0x01}, + {0x69, {0x03}, 0x01}, + {0x6a, {0x77}, 0x01}, + {0x6b, {0x03}, 0x01}, + {0x6c, {0x85}, 0x01}, + {0x6d, {0x03}, 0x01}, + {0x6e, {0x8f}, 0x01}, + {0x6f, {0x03}, 0x01}, + {0x70, {0xcb}, 0x01}, + {0x71, {0x00}, 0x01}, + {0x72, {0x00}, 0x01}, + {0x73, {0x00}, 0x01}, + {0x74, {0x21}, 0x01}, + {0x75, {0x00}, 0x01}, + {0x76, {0x4c}, 0x01}, + {0x77, {0x00}, 0x01}, + {0x78, {0x6b}, 0x01}, + {0x79, {0x00}, 0x01}, + {0x7a, {0x85}, 0x01}, + {0x7b, {0x00}, 0x01}, + {0x7c, {0x9a}, 0x01}, + {0x7d, {0x00}, 0x01}, + {0x7e, {0xad}, 0x01}, + {0x7f, {0x00}, 0x01}, + {0x80, {0xbe}, 0x01}, + {0x81, {0x00}, 0x01}, + {0x82, {0xcd}, 0x01}, + {0x83, {0x01}, 0x01}, + {0x84, {0x01}, 0x01}, + {0x85, {0x01}, 0x01}, + {0x86, {0x29}, 0x01}, + {0x87, {0x01}, 0x01}, + {0x88, {0x68}, 0x01}, + {0x89, {0x01}, 0x01}, + {0x8a, {0x98}, 0x01}, + {0x8b, {0x01}, 0x01}, + {0x8c, {0xe5}, 0x01}, + {0x8d, {0x02}, 0x01}, + {0x8e, {0x1e}, 0x01}, + {0x8f, {0x02}, 0x01}, + {0x90, {0x30}, 0x01}, + {0x91, {0x02}, 0x01}, + {0x92, {0x52}, 0x01}, + {0x93, {0x02}, 0x01}, + {0x94, {0x88}, 0x01}, + {0x95, {0x02}, 0x01}, + {0x96, {0xaa}, 0x01}, + {0x97, {0x02}, 0x01}, + {0x98, {0xd7}, 0x01}, + {0x99, {0x02}, 0x01}, + {0x9a, {0xf7}, 0x01}, + {0x9b, {0x03}, 0x01}, + {0x9c, {0x21}, 0x01}, + {0x9d, {0x03}, 0x01}, + {0x9e, {0x2e}, 0x01}, + {0x9f, {0x03}, 0x01}, + {0xa0, {0x3d}, 0x01}, + {0xa2, {0x03}, 0x01}, + {0xa3, {0x4c}, 0x01}, + {0xa4, {0x03}, 0x01}, + {0xa5, {0x5e}, 0x01}, + {0xa6, {0x03}, 0x01}, + {0xa7, {0x71}, 0x01}, + {0xa9, {0x03}, 0x01}, + {0xaa, {0x86}, 0x01}, + {0xab, {0x03}, 0x01}, + {0xac, {0x94}, 0x01}, + {0xad, {0x03}, 0x01}, + {0xae, {0xfa}, 0x01}, + {0xaf, {0x00}, 0x01}, + {0xb0, {0x00}, 0x01}, + {0xb1, {0x00}, 0x01}, + {0xb2, {0x21}, 0x01}, + {0xb3, {0x00}, 0x01}, + {0xb4, {0x4c}, 0x01}, + {0xb5, {0x00}, 0x01}, + {0xb6, {0x6b}, 0x01}, + {0xb7, {0x00}, 0x01}, + {0xb8, {0x85}, 0x01}, + {0xb9, {0x00}, 0x01}, + {0xba, {0x9a}, 0x01}, + {0xbb, {0x00}, 0x01}, + {0xbc, {0xad}, 0x01}, + {0xbd, {0x00}, 0x01}, + {0xbe, {0xbe}, 0x01}, + {0xbf, {0x00}, 0x01}, + {0xc0, {0xcd}, 0x01}, + {0xc1, {0x01}, 0x01}, + {0xc2, {0x01}, 0x01}, + {0xc3, {0x01}, 0x01}, + {0xc4, {0x29}, 0x01}, + {0xc5, {0x01}, 0x01}, + {0xc6, {0x68}, 0x01}, + {0xc7, {0x01}, 0x01}, + {0xc8, {0x98}, 0x01}, + {0xc9, {0x01}, 0x01}, + {0xca, {0xe5}, 0x01}, + {0xcb, {0x02}, 0x01}, + {0xcc, {0x1e}, 0x01}, + {0xcd, {0x02}, 0x01}, + {0xce, {0x20}, 0x01}, + {0xcf, {0x02}, 0x01}, + {0xd0, {0x52}, 0x01}, + {0xd1, {0x02}, 0x01}, + {0xd2, {0x88}, 0x01}, + {0xd3, {0x02}, 0x01}, + {0xd4, {0xaa}, 0x01}, + {0xd5, {0x02}, 0x01}, + {0xd6, {0xd7}, 0x01}, + {0xd7, {0x02}, 0x01}, + {0xd8, {0xf7}, 0x01}, + {0xd9, {0x03}, 0x01}, + {0xda, {0x21}, 0x01}, + {0xdb, {0x03}, 0x01}, + {0xdc, {0x2e}, 0x01}, + {0xdd, {0x03}, 0x01}, + {0xde, {0x3d}, 0x01}, + {0xdf, {0x03}, 0x01}, + {0xe0, {0x4c}, 0x01}, + {0xe1, {0x03}, 0x01}, + {0xe2, {0x5e}, 0x01}, + {0xe3, {0x03}, 0x01}, + {0xe4, {0x71}, 0x01}, + {0xe5, {0x03}, 0x01}, + {0xe6, {0x86}, 0x01}, + {0xe7, {0x03}, 0x01}, + {0xe8, {0x94}, 0x01}, + {0xe9, {0x03}, 0x01}, + {0xea, {0xfa}, 0x01}, /* Select CMD2 Page0 (Undocumented) */ - {0xff, 0x01}, + {0xff, {0x01}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, + {0xfb, {0x01}, 0x01}, /* Select CMD2 Page1 (Undocumented) */ - {0xff, 0x02}, + {0xff, {0x02}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, + {0xfb, {0x01}, 0x01}, /* Select CMD2 Page3 (Undocumented) */ - {0xff, 0x04}, + {0xff, {0x04}, 0x01}, /* Reload CMD1: Don't reload default value to register */ - {0xfb, 0x01}, + {0xfb, {0x01}, 0x01}, /* Select CMD1 */ - {0xff, 0x00}, - {0xd3, 0x22}, /* RGBMIPICTRL: VSYNC back porch = 34 */ - {0xd4, 0x04}, /* RGBMIPICTRL: VSYNC front porch = 4 */ + {0xff, {0x00}, 0x01}, + {0xd3, {0x22}, 0x01}, /* RGBMIPICTRL: VSYNC back porch = 34 */ + {0xd4, {0x04}, 0x01}, /* RGBMIPICTRL: VSYNC front porch = 4 */ +}; + +struct khadas_ts050_panel_data ts050_panel_data = { + .init_code = (struct khadas_ts050_panel_cmd *)ts050_init_code, + .len = ARRAY_SIZE(ts050_init_code) +}; + +struct khadas_ts050_panel_data ts050v2_panel_data = { + .init_code = (struct khadas_ts050_panel_cmd *)ts050v2_init_code, + .len = ARRAY_SIZE(ts050v2_init_code) }; static inline @@ -613,10 +671,11 @@ static int khadas_ts050_panel_prepare(struct drm_panel *panel) msleep(100); - for (i = 0; i < ARRAY_SIZE(init_code); i++) { + for (i = 0; i < khadas_ts050->panel_data->len; i++) { err = mipi_dsi_dcs_write(khadas_ts050->link, - init_code[i].cmd, - &init_code[i].data, 1); + khadas_ts050->panel_data->init_code[i].cmd, + &khadas_ts050->panel_data->init_code[i].data, + khadas_ts050->panel_data->init_code[i].size); if (err < 0) { dev_err(panel->dev, "failed write cmds: %d\n", err); goto poweroff; @@ -762,7 +821,8 @@ static const struct drm_panel_funcs khadas_ts050_panel_funcs = { }; static const struct of_device_id khadas_ts050_of_match[] = { - { .compatible = "khadas,ts050", }, + { .compatible = "khadas,ts050", .data = &ts050_panel_data, }, + { .compatible = "khadas,ts050v2", .data = &ts050v2_panel_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, khadas_ts050_of_match); @@ -806,6 +866,13 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi) struct khadas_ts050_panel *khadas_ts050; int err; + const void *data = of_device_get_match_data(&dsi->dev); + + if (!data) { + dev_err(&dsi->dev, "No matching data\n"); + return -ENODEV; + } + dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | @@ -816,6 +883,7 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi) if (!khadas_ts050) return -ENOMEM; + khadas_ts050->panel_data = (struct khadas_ts050_panel_data *)data; mipi_dsi_set_drvdata(dsi, khadas_ts050); khadas_ts050->link = dsi; diff --git a/drivers/gpu/drm/panel/panel-lg-sw43408.c b/drivers/gpu/drm/panel/panel-lg-sw43408.c new file mode 100644 index 000000000000..115f4702d59f --- /dev/null +++ b/drivers/gpu/drm/panel/panel-lg-sw43408.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019-2024 Linaro Ltd + * Author: Sumit Semwal + * Dmitry Baryshkov + */ + +#include +#include +#include +#include +#include +#include + +#include